Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions ned_soup/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Ned's Soup Foraging Frenzy

This is a simple retro-style arcade game built with **pygame**. Help Ned forage for soup ingredients while avoiding (or stunning) roaming Lugnutz.

## Requirements
- Python 3.x
- pygame (`pip install pygame`)

## Running the Game
```
python main.py
```

Use the arrow keys to move Ned. Press `SPACE` to forage at nearby spots. If you collect junk, you can throw it at the nearest Lugnutz with `SHIFT`.

Collect four ingredients and return to the home square to win. Have fun!
264 changes: 264 additions & 0 deletions ned_soup/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
# Simple skeleton for Ned's Soup Foraging Frenzy
import pygame
import random
import math

pygame.init()

# Screen dimensions
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Ned's Soup Foraging Frenzy")
clock = pygame.time.Clock()

# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (200, 50, 50)
GREEN = (50, 200, 50)
BLUE = (50, 50, 200)
YELLOW = (200, 200, 50)
ORANGE = (200, 150, 50)

FONT = pygame.font.SysFont("Courier", 16)

# Parameters for walking
FOOT_OFFSET = 5
STRIDE_LENGTH = 15
STEP_SPEED = 2

class Walker:
def __init__(self, pos, color, scale=1.0):
self.color = color
self.scale = scale
self.body = pygame.Vector2(pos)
offset = pygame.Vector2(0, FOOT_OFFSET * scale)
self.left_foot = self.body + pygame.Vector2(-offset.x, offset.y)
self.right_foot = self.body + pygame.Vector2(offset.x, offset.y)
self.swing = "left"
self.direction = pygame.Vector2(0, 0)

def update(self, direction):
if direction.length_squared() > 0:
direction = direction.normalize()
self.direction = direction
self._step()
self.body = (self.left_foot + self.right_foot) / 2

def _step(self):
if self.direction.length_squared() == 0:
return
perp = pygame.Vector2(-self.direction.y, self.direction.x)
if self.swing == "left":
step_foot = self.left_foot
support = self.right_foot
sign = -1
else:
step_foot = self.right_foot
support = self.left_foot
sign = 1
target = support + self.direction * STRIDE_LENGTH * self.scale + perp * FOOT_OFFSET * sign * self.scale
move = target - step_foot
if move.length() > STEP_SPEED * self.scale:
move.scale_to_length(STEP_SPEED * self.scale)
if self.swing == "left":
self.left_foot += move
if (target - self.left_foot).length() < 0.5:
self.left_foot = target
self.swing = "right"
else:
self.right_foot += move
if (target - self.right_foot).length() < 0.5:
self.right_foot = target
self.swing = "left"

def draw(self, surface):
r = int(3 * self.scale)
pygame.draw.circle(surface, self.color, self.left_foot, r)
pygame.draw.circle(surface, self.color, self.right_foot, r)
pygame.draw.circle(surface, self.color, self.body, int(4 * self.scale))

class ForageSpot:
def __init__(self, pos, good=True):
self.pos = pygame.Vector2(pos)
self.good = good
self.collected = False
self.timer = 0

def update(self):
if self.collected:
self.timer += 1

def draw(self, surface):
if self.collected:
if self.timer < 180:
color = ORANGE if self.good else RED
pygame.draw.rect(surface, color, (*self.pos - pygame.Vector2(5, 5), 10, 10))
else:
color = GREEN if self.good else YELLOW
pygame.draw.rect(surface, color, (*self.pos - pygame.Vector2(5, 5), 10, 10))

class Lugnutz(Walker):
def __init__(self, pos):
super().__init__(pos, BLUE, scale=1.8)
self.state = "wander"
self.cooldown = 0

def think(self, player):
if self.cooldown > 0:
self.cooldown -= 1
direction = pygame.Vector2(0, 0)
to_player = player.body - self.body
dist = to_player.length()
if self.cooldown == 0:
if dist < 150:
direction = to_player
self.state = "chase"
else:
self.state = "wander"
direction = pygame.Vector2(random.uniform(-1, 1), random.uniform(-1, 1))
else:
self.state = "flee"
direction = -to_player
self.update(direction)

def hit(self):
self.cooldown = 120

class Game:
def __init__(self):
self.player = Walker((WIDTH/2, HEIGHT/2), WHITE)
self.lugs = [Lugnutz((random.randint(50, WIDTH-50), random.randint(50, HEIGHT-50))) for _ in range(2)]
self.forage_spots = []
for _ in range(4):
self.spawn_forage()
self.ingredient_count = 0
self.junk_count = 0
self.messages = []
self.spawn_timer = 0
self.home_rect = pygame.Rect(WIDTH-80, HEIGHT-80, 60, 60)
self.running = True
self.in_start = True

def spawn_forage(self):
good = random.random() < 0.6
x = random.randint(40, WIDTH-40)
y = random.randint(40, HEIGHT-40)
self.forage_spots.append(ForageSpot((x, y), good))

def process_events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
if event.type == pygame.KEYDOWN and self.in_start:
if event.key == pygame.K_SPACE:
self.in_start = False

def update(self):
keys = pygame.key.get_pressed()
if self.in_start:
return
direction = pygame.Vector2(0, 0)
if keys[pygame.K_LEFT]:
direction.x -= 1
if keys[pygame.K_RIGHT]:
direction.x += 1
if keys[pygame.K_UP]:
direction.y -= 1
if keys[pygame.K_DOWN]:
direction.y += 1
if direction.length_squared() > 0:
direction = direction.normalize()
self.player.update(direction)

if keys[pygame.K_SPACE]:
for spot in self.forage_spots:
if not spot.collected and (spot.pos - self.player.body).length() < 20:
spot.collected = True
if spot.good:
self.ingredient_count += 1
self.messages.append("Found ingredient!")
else:
self.junk_count += 1
self.messages.append("Found junk!")
break
if keys[pygame.K_LSHIFT] or keys[pygame.K_RSHIFT]:
if self.junk_count > 0:
closest = None
dist = 9999
for lug in self.lugs:
d = (lug.body - self.player.body).length()
if d < dist:
dist = d
closest = lug
if closest and dist < 150:
closest.hit()
self.junk_count -= 1
self.messages.append("Threw junk!")

for lug in self.lugs:
lug.think(self.player)
for spot in self.forage_spots:
spot.update()
self.forage_spots = [s for s in self.forage_spots if not (s.collected and s.timer > 180)]

self.spawn_timer += 1
if self.spawn_timer > 480:
self.spawn_timer = 0
self.spawn_forage()

if self.player.body.x > self.home_rect.x and self.player.body.y > self.home_rect.y:
if self.ingredient_count >= 4:
self.messages.append("You made soup! You win!")
self.running = False
else:
self.messages.append("Need more ingredients before going home!")

def draw_hud(self):
text = FONT.render(f"Ingredients: {self.ingredient_count} Junk: {self.junk_count}", True, WHITE)
screen.blit(text, (10, 10))
if self.messages:
msg = FONT.render(self.messages[-1], True, YELLOW)
screen.blit(msg, (10, HEIGHT - 30))
if self.junk_count > 0:
hint = FONT.render("Press SHIFT to throw junk", True, ORANGE)
screen.blit(hint, (10, HEIGHT - 50))

def draw_start(self):
screen.fill(BLACK)
title = FONT.render("Ned's Soup Foraging Frenzy", True, YELLOW)
legend = FONT.render("Arrow keys: move SPACE: forage", True, WHITE)
prompt = FONT.render("Press SPACE to start", True, GREEN)
screen.blit(title, (WIDTH/2 - title.get_width()/2, HEIGHT/2 - 40))
screen.blit(legend, (WIDTH/2 - legend.get_width()/2, HEIGHT/2))
screen.blit(prompt, (WIDTH/2 - prompt.get_width()/2, HEIGHT/2 + 40))
pygame.display.flip()

def draw(self):
screen.fill((30, 30, 50))
for spot in self.forage_spots:
spot.draw(screen)
pygame.draw.rect(screen, (80, 80, 80), self.home_rect)
self.player.draw(screen)
for lug in self.lugs:
lug.draw(screen)
self.draw_hud()
pygame.display.flip()

def run(self):
while self.running:
self.process_events()
if self.in_start:
self.draw_start()
clock.tick(60)
continue
self.update()
self.draw()
clock.tick(60)

def main():
game = Game()
game.run()

if __name__ == "__main__":
main()