import pygame import random import sys from enum import Enum pygame.init() SCREEN_WIDTH=800 SCREEN_HEIGHT=600 BLOCK_SIZE=20 GAME_SPEED=10 class Colors: BG_TOP = (15, 32, 39) BG_BOTTOM = (44, 83, 100) #Snake Colors SNAKE_HEAD = (46, 213, 115) SNAKE_BODY_1 = (34, 166, 90) SNAKE_BODY_2 = (25, 130, 70) FOOD_COLOR = (252, 92, 101) FOOD_GLOW = (255, 159, 165) # UI TEXT_COLOR = (255, 255, 255) SCORE_BG = (30, 39, 46, 180) GAME_OVER_BG = (44, 62, 80, 230) GRID_COLOR = (40, 55, 71) pygame.font.init() FONT_LARGE = pygame.font.Font(None, 72) FONT_MEDIUM = pygame.font.Font(None, 48) FONT_SMALL = pygame.font.Font(None, 36) class Direction(Enum): UP = 1 DOWN = 2 LEFT = 3 RIGHT = 4 def draw_gradient_background(screen): for y in range(SCREEN_HEIGHT): ratio = y / SCREEN_HEIGHT r = int(Colors.BG_TOP[0] * (1 - ratio) + Colors.BG_BOTTOM[0] * ratio) g = int(Colors.BG_TOP[1] * (1 - ratio) + Colors.BG_BOTTOM[1] * ratio) b = int(Colors.BG_TOP[2] * (1 - ratio) + Colors.BG_BOTTOM[2] * ratio) pygame.draw.line(screen, (r, g, b), (0, y), (SCREEN_WIDTH, y)) def draw_grid(screen): for x in range(0, SCREEN_WIDTH, BLOCK_SIZE): pygame.draw.line(screen, Colors.GRID_COLOR, (x, 0), (x, SCREEN_HEIGHT), 1) for y in range(0, SCREEN_HEIGHT, BLOCK_SIZE): pygame.draw.line(screen, Colors.GRID_COLOR, (0, y), (SCREEN_WIDTH, y), 1) def draw_rounded_rect(surface, color, rect, corner_radius): pygame.draw.rect(surface, color, rect, border_radius=corner_radius) class Snake: def __init__(self): """Initialize snake in the center""" # Starting position (center of screen) start_x = SCREEN_WIDTH // 2 start_y = SCREEN_HEIGHT // 2 # Snake body (list of positions) self.body = [ [start_x, start_y], [start_x - BLOCK_SIZE, start_y], [start_x - (2 * BLOCK_SIZE), start_y] ] self.direction = Direction.RIGHT self.grow = False # Flag to grow snake def get_head(self): """Return head position""" return self.body[0] def move(self, new_direction): """Move snake in given direction""" # Prevent 180-degree turns if new_direction == Direction.UP and self.direction != Direction.DOWN: self.direction = new_direction elif new_direction == Direction.DOWN and self.direction != Direction.UP: self.direction = new_direction elif new_direction == Direction.LEFT and self.direction != Direction.RIGHT: self.direction = new_direction elif new_direction == Direction.RIGHT and self.direction != Direction.LEFT: self.direction = new_direction # Calculate new head position head = self.get_head().copy() if self.direction == Direction.UP: head[1] -= BLOCK_SIZE elif self.direction == Direction.DOWN: head[1] += BLOCK_SIZE elif self.direction == Direction.LEFT: head[0] -= BLOCK_SIZE elif self.direction == Direction.RIGHT: head[0] += BLOCK_SIZE # Add new head self.body.insert(0, head) # Remove tail unless growing if not self.grow: self.body.pop() else: self.grow = False def grow_snake(self): """Mark snake to grow on next move""" self.grow = True def check_collision(self): """Check if snake collided with walls or itself""" head = self.get_head() # Wall collision if (head[0] < 0 or head[0] >= SCREEN_WIDTH or head[1] < 0 or head[1] >= SCREEN_HEIGHT): return True if head in self.body[1:]: return True return False def draw(self, screen): for i, segment in enumerate(self.body): # Head is brightest if i == 0: color = Colors.SNAKE_HEAD # Draw head with slight glow effect glow_rect = pygame.Rect( segment[0] - 2, segment[1] - 2, BLOCK_SIZE + 4, BLOCK_SIZE + 4 ) pygame.draw.rect(screen, Colors.SNAKE_BODY_1, glow_rect, border_radius=6) else: if i % 2 == 0: color = Colors.SNAKE_BODY_1 else: color = Colors.SNAKE_BODY_2 rect = pygame.Rect(segment[0], segment[1], BLOCK_SIZE, BLOCK_SIZE) pygame.draw.rect(screen, color, rect, border_radius=5) highlight = pygame.Rect( segment[0] + 2, segment[1] + 2, BLOCK_SIZE - 10, BLOCK_SIZE - 10 ) highlight_color = tuple(min(c + 30, 255) for c in color) pygame.draw.rect(screen, highlight_color, highlight, border_radius=3) class Food: def __init__(self): """Initialize food at random position""" self.position = [0, 0] self.pulse = 0 # For pulsing animation self.respawn() def respawn(self, snake_body=None): while True: self.position = [ random.randint(0, (SCREEN_WIDTH - BLOCK_SIZE) // BLOCK_SIZE) * BLOCK_SIZE, random.randint(0, (SCREEN_HEIGHT - BLOCK_SIZE) // BLOCK_SIZE) * BLOCK_SIZE ] # Make sure food doesn't spawn on snake if snake_body is None or self.position not in snake_body: break def draw(self, screen): # Pulsing animation self.pulse += 0.1 pulse_size = int(2 * abs(pygame.math.Vector2(1, 0).rotate(self.pulse * 10).x)) # Outer glow glow_rect = pygame.Rect( self.position[0] - pulse_size - 2, self.position[1] - pulse_size - 2, BLOCK_SIZE + (pulse_size * 2) + 4, BLOCK_SIZE + (pulse_size * 2) + 4 ) pygame.draw.rect(screen, Colors.FOOD_GLOW, glow_rect, border_radius=BLOCK_SIZE // 2) # Main food circle food_rect = pygame.Rect( self.position[0], self.position[1], BLOCK_SIZE, BLOCK_SIZE ) pygame.draw.rect(screen, Colors.FOOD_COLOR, food_rect, border_radius=BLOCK_SIZE // 2) # Inner shine shine_rect = pygame.Rect( self.position[0] + 4, self.position[1] + 4, BLOCK_SIZE - 12, BLOCK_SIZE - 12 ) shine_color = tuple(min(c + 50, 255) for c in Colors.FOOD_COLOR) pygame.draw.rect(screen, shine_color, shine_rect, border_radius=BLOCK_SIZE // 2) class SnakeGame: def __init__(self): self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption('🐍 Beautiful Snake Game') self.clock = pygame.time.Clock() # Game objects self.snake = Snake() self.food = Food() self.food.respawn(self.snake.body) # Game state self.score = 0 self.high_score = 0 self.game_over = False self.paused = False def reset(self): """Reset game to start new round""" self.snake = Snake() self.food = Food() self.score = 0 self.game_over = False self.paused = False def handle_input(self): """Process keyboard input""" for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if event.type == pygame.KEYDOWN: if self.game_over: if event.key == pygame.K_SPACE: self.reset() elif event.key == pygame.K_ESCAPE: pygame.quit() sys.exit() else: # Movement controls if event.key == pygame.K_UP or event.key == pygame.K_w: self.snake.move(Direction.UP) elif event.key == pygame.K_DOWN or event.key == pygame.K_s: self.snake.move(Direction.DOWN) elif event.key == pygame.K_LEFT or event.key == pygame.K_a: self.snake.move(Direction.LEFT) elif event.key == pygame.K_RIGHT or event.key == pygame.K_d: self.snake.move(Direction.RIGHT) elif event.key == pygame.K_SPACE: self.paused = not self.paused elif event.key == pygame.K_ESCAPE: pygame.quit() sys.exit() def update(self): if self.game_over or self.paused: return # Move snake self.snake.move(self.snake.direction) # Get head position head = self.snake.get_head() # Check collision with food (compare x and y coordinates) if head[0] == self.food.position[0] and head[1] == self.food.position[1]: # Food eaten! self.score += 2 self.snake.grow_snake() self.food.respawn(self.snake.body) # Update high score if self.score > self.high_score: self.high_score = self.score # Check collision with walls or self if self.snake.check_collision(): self.game_over = True def draw_ui(self): """Draw score and UI elements""" # Score panel (top-left) panel_width = 250 panel_height = 80 panel = pygame.Surface((panel_width, panel_height), pygame.SRCALPHA) panel.fill(Colors.SCORE_BG) # Draw score text score_text = FONT_SMALL.render(f'Score: {self.score}', True, Colors.TEXT_COLOR) high_score_text = FONT_SMALL.render(f'Best: {self.high_score}', True, Colors.TEXT_COLOR) panel.blit(score_text, (10, 10)) panel.blit(high_score_text, (10, 45)) self.screen.blit(panel, (10, 10)) # Pause indicator if self.paused: pause_text = FONT_LARGE.render('PAUSED', True, Colors.TEXT_COLOR) text_rect = pause_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)) # Semi-transparent background overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA) overlay.fill((0, 0, 0, 128)) self.screen.blit(overlay, (0, 0)) self.screen.blit(pause_text, text_rect) def draw_game_over(self): """Draw game over screen""" # Semi-transparent overlay overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA) overlay.fill((0, 0, 0, 180)) self.screen.blit(overlay, (0, 0)) # Game Over panel panel_width = 500 panel_height = 350 panel = pygame.Surface((panel_width, panel_height), pygame.SRCALPHA) panel.fill(Colors.GAME_OVER_BG) # Text game_over_text = FONT_LARGE.render('GAME OVER', True, Colors.TEXT_COLOR) score_text = FONT_MEDIUM.render(f'Final Score: {self.score}', True, Colors.TEXT_COLOR) high_score_text = FONT_MEDIUM.render(f'High Score: {self.high_score}', True, Colors.TEXT_COLOR) restart_text = FONT_SMALL.render('Press SPACE to restart', True, Colors.TEXT_COLOR) quit_text = FONT_SMALL.render('Press ESC to quit', True, Colors.TEXT_COLOR) # Position text on panel panel.blit(game_over_text, (panel_width // 2 - game_over_text.get_width() // 2, 30)) panel.blit(score_text, (panel_width // 2 - score_text.get_width() // 2, 120)) panel.blit(high_score_text, (panel_width // 2 - high_score_text.get_width() // 2, 180)) panel.blit(restart_text, (panel_width // 2 - restart_text.get_width() // 2, 250)) panel.blit(quit_text, (panel_width // 2 - quit_text.get_width() // 2, 290)) # Draw panel centered panel_x = (SCREEN_WIDTH - panel_width) // 2 panel_y = (SCREEN_HEIGHT - panel_height) // 2 self.screen.blit(panel, (panel_x, panel_y)) def draw(self): """Draw everything""" # Background draw_gradient_background(self.screen) draw_grid(self.screen) # Game objects self.food.draw(self.screen) self.snake.draw(self.screen) # UI self.draw_ui() # Game over screen if self.game_over: self.draw_game_over() pygame.display.flip() def run(self): """Main game loop""" while True: self.handle_input() self.update() self.draw() self.clock.tick(GAME_SPEED) if __name__ == '__main__': game = SnakeGame() game.run()