Implement food spawning system and basic scoring
This commit is contained in:
parent
520eba279b
commit
424cd4c727
42
ROADMAP.md
42
ROADMAP.md
@ -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
52
src/food.py
Normal 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
|
82
src/game.py
82
src/game.py
@ -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()
|
||||||
|
Loading…
Reference in New Issue
Block a user