Implement food spawning system and basic scoring

This commit is contained in:
Rbanh 2025-02-23 12:05:36 -05:00
parent 520eba279b
commit 424cd4c727
3 changed files with 134 additions and 42 deletions

View File

@ -3,7 +3,11 @@
This is a living document that tracks the development progress of the AI Snake Game project. This is a living document that tracks the development progress of the AI Snake Game project.
## Current Status ## Current Status
Last Updated: [Initial Version] Last Updated: [Food System Implementation]
- Added Food class with spawning mechanics
- Integrated food system with main game loop
- Implemented basic scoring system
- Added game over screen with score display
## Phase 1: Project Setup and Basic Structure ✅ ## Phase 1: Project Setup and Basic Structure ✅
- [x] Create project structure and virtual environment - [x] Create project structure and virtual environment
@ -15,16 +19,16 @@ Last Updated: [Initial Version]
## Phase 2: Core Game Development 🔄 ## Phase 2: Core Game Development 🔄
- [x] Implement basic game window using Pygame - [x] Implement basic game window using Pygame
- [x] Create Snake class with movement mechanics - [x] Create Snake class with movement mechanics
- [ ] Implement food spawning system - [x] Implement food spawning system
- [ ] Create Food class - [x] Create Food class
- [ ] Add random food placement - [x] Add random food placement
- [ ] Add collision detection with food - [x] Add collision detection with food
- [x] Add collision detection (walls and self) - [x] Add collision detection (walls and self)
- [ ] Implement scoring system - [x] Implement scoring system
- [ ] Add score display - [x] Add score display
- [ ] Add high score tracking - [ ] Add high score tracking
- [ ] Add game over conditions - [x] Add game over conditions
- [ ] Implement game over state transition - [x] Implement game over state transition
- [ ] Add restart functionality - [ ] Add restart functionality
## Phase 3: Game Polish and UI ## Phase 3: Game Polish and UI
@ -73,18 +77,18 @@ Last Updated: [Initial Version]
- [ ] Final testing and refinements - [ ] Final testing and refinements
## Next Steps ## Next Steps
1. Implement the food spawning system 1. Add restart functionality
- Create Food class - Implement game restart on key press
- Add random food placement logic - Reset score and snake position
2. Add scoring system 2. Create main menu interface
- Implement score tracking
- Add score display
3. Complete game over conditions
- Add game over state handling
- Implement restart functionality
4. Create main menu interface
- Design menu layout - Design menu layout
- Implement menu navigation - Implement menu navigation
3. Add high score system
- Implement score persistence
- Add high score display
4. Add visual and sound effects
- Implement basic animations
- Add game sounds
## Known Issues ## Known Issues
- None reported yet - None reported yet

52
src/food.py Normal file
View File

@ -0,0 +1,52 @@
import pygame
import random
from typing import Tuple, List
class Food:
def __init__(self, block_size: int, color: Tuple[int, int, int] = (255, 0, 0)):
self.block_size = block_size
self.color = color
self.position = (0, 0) # Will be set by spawn()
def spawn(self, width: int, height: int, occupied_positions: List[Tuple[int, int]]) -> None:
"""
Spawn food at a random position that isn't occupied by the snake.
Args:
width: Game area width
height: Game area height
occupied_positions: List of positions (typically snake body positions) where food shouldn't spawn
"""
# Calculate valid grid positions
valid_x = range(0, width, self.block_size)
valid_y = range(0, height, self.block_size)
# Create list of all possible positions
all_positions = [
(x, y) for x in valid_x for y in valid_y
if (x, y) not in occupied_positions
]
if not all_positions:
# No valid positions (snake fills screen) - game should be won
return
# Choose random position
self.position = random.choice(all_positions)
def draw(self, screen: pygame.Surface) -> None:
"""Draw the food on the screen"""
pygame.draw.rect(
screen,
self.color,
pygame.Rect(
self.position[0],
self.position[1],
self.block_size,
self.block_size
)
)
def check_collision(self, position: Tuple[int, int]) -> bool:
"""Check if the given position collides with the food"""
return self.position == position

View File

@ -1,6 +1,8 @@
import pygame import pygame
import sys import sys
from enum import Enum, auto from enum import Enum, auto
from snake import Snake, Direction
from food import Food
class GameState(Enum): class GameState(Enum):
MENU = auto() MENU = auto()
@ -20,9 +22,18 @@ class Game:
self.clock = pygame.time.Clock() self.clock = pygame.time.Clock()
self.fps = 60 self.fps = 60
# Game objects
self.block_size = 20
self.snake = Snake((self.width // 2, self.height // 2), self.block_size)
self.food = Food(self.block_size)
# Spawn initial food
self.food.spawn(self.width, self.height, self.snake.body)
# Game state # Game state
self.state = GameState.MENU self.state = GameState.PLAYING # Changed to start in playing state for now
self.running = True self.running = True
self.score = 0
def handle_events(self): def handle_events(self):
for event in pygame.event.get(): for event in pygame.event.get():
@ -34,37 +45,62 @@ class Game:
self.state = GameState.PAUSED self.state = GameState.PAUSED
elif self.state == GameState.PAUSED: elif self.state == GameState.PAUSED:
self.state = GameState.PLAYING self.state = GameState.PLAYING
elif self.state == GameState.PLAYING:
# Handle snake direction
if event.key == pygame.K_UP:
self.snake.change_direction(Direction.UP)
elif event.key == pygame.K_DOWN:
self.snake.change_direction(Direction.DOWN)
elif event.key == pygame.K_LEFT:
self.snake.change_direction(Direction.LEFT)
elif event.key == pygame.K_RIGHT:
self.snake.change_direction(Direction.RIGHT)
def update(self): def update(self):
if self.state == GameState.PLAYING: if self.state == GameState.PLAYING:
# Update game logic here # Move snake
pass if self.snake.move(pygame.time.get_ticks()):
elif self.state == GameState.MENU: # Check wall collision
# Update menu logic here if self.snake.check_collision(self.width, self.height):
pass self.state = GameState.GAME_OVER
elif self.state == GameState.GAME_OVER: return
# Update game over logic here
pass # Check food collision
elif self.state == GameState.PAUSED: if self.food.check_collision(self.snake.body[0]):
# Update pause menu logic here self.snake.grow()
pass self.score += 1
self.food.spawn(self.width, self.height, self.snake.body)
def render(self): def render(self):
# Clear screen # Clear screen
self.screen.fill((0, 0, 0)) # Black background self.screen.fill((0, 0, 0)) # Black background
if self.state == GameState.PLAYING: if self.state == GameState.PLAYING or self.state == GameState.PAUSED:
# Render game here # Draw game objects
pass self.snake.draw(self.screen)
elif self.state == GameState.MENU: self.food.draw(self.screen)
# Render menu here
pass # Draw score
font = pygame.font.Font(None, 36)
score_text = font.render(f'Score: {self.score}', True, (255, 255, 255))
self.screen.blit(score_text, (10, 10))
# Draw pause indicator
if self.state == GameState.PAUSED:
pause_text = font.render('PAUSED', True, (255, 255, 255))
text_rect = pause_text.get_rect(center=(self.width//2, self.height//2))
self.screen.blit(pause_text, text_rect)
elif self.state == GameState.GAME_OVER: elif self.state == GameState.GAME_OVER:
# Render game over screen here font = pygame.font.Font(None, 74)
pass text = font.render('Game Over!', True, (255, 0, 0))
elif self.state == GameState.PAUSED: score_text = font.render(f'Score: {self.score}', True, (255, 255, 255))
# Render pause menu here
pass text_rect = text.get_rect(center=(self.width//2, self.height//2 - 50))
score_rect = score_text.get_rect(center=(self.width//2, self.height//2 + 50))
self.screen.blit(text, text_rect)
self.screen.blit(score_text, score_rect)
# Update display # Update display
pygame.display.flip() pygame.display.flip()