wei/测试/snake_game.py

345 lines
12 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import pygame
import sys
import random
import time
# 初始化 Pygame
pygame.init()
# 游戏常量
WIDTH, HEIGHT = 800, 600
GRID_SIZE = 20
GRID_WIDTH = WIDTH // GRID_SIZE
GRID_HEIGHT = HEIGHT // GRID_SIZE
FPS = 10 # 控制游戏速度
# 颜色定义
BACKGROUND = (15, 15, 30)
GRID_COLOR = (30, 30, 60)
SNAKE_HEAD = (50, 205, 50) # 蛇头颜色 - 浅绿色
SNAKE_BODY = (34, 139, 34) # 蛇身颜色 - 绿色
FOOD_COLOR = (220, 20, 60) # 食物颜色 - 红色
TEXT_COLOR = (220, 220, 220)
SCORE_COLOR = (255, 215, 0)
# 方向常量
UP = (0, -1)
DOWN = (0, 1)
LEFT = (-1, 0)
RIGHT = (1, 0)
class Snake:
def __init__(self):
self.reset()
def reset(self):
"""重置蛇的状态"""
# 蛇初始位置在屏幕中央
self.length = 3
self.positions = [(GRID_WIDTH // 2, GRID_HEIGHT // 2)]
self.direction = RIGHT
self.score = 0
self.grow_to = 3 # 初始长度
self.is_alive = True
# 初始添加蛇身
for i in range(1, self.length):
self.positions.append((self.positions[0][0] - i, self.positions[0][1]))
def get_head_position(self):
"""获取蛇头位置"""
return self.positions[0]
def turn(self, direction):
"""改变蛇的方向(不能直接反向)"""
# 防止蛇直接反向移动
if (direction[0] * -1, direction[1] * -1) != self.direction:
self.direction = direction
def move(self):
"""移动蛇"""
if not self.is_alive:
return
head = self.get_head_position()
new_x = (head[0] + self.direction[0]) % GRID_WIDTH
new_y = (head[1] + self.direction[1]) % GRID_HEIGHT
new_position = (new_x, new_y)
# 检查是否撞到自己
if new_position in self.positions[1:]:
self.is_alive = False
return
# 添加新的头部
self.positions.insert(0, new_position)
# 如果蛇需要生长,则保留尾部,否则移除尾部
if len(self.positions) > self.grow_to:
self.positions.pop()
def draw(self, surface):
"""绘制蛇"""
for i, pos in enumerate(self.positions):
# 蛇头用不同颜色
color = SNAKE_HEAD if i == 0 else SNAKE_BODY
# 绘制蛇身矩形
rect = pygame.Rect(
pos[0] * GRID_SIZE,
pos[1] * GRID_SIZE,
GRID_SIZE,
GRID_SIZE
)
pygame.draw.rect(surface, color, rect)
pygame.draw.rect(surface, (color[0]//2, color[1]//2, color[2]//2), rect, 1)
# 绘制蛇眼睛(头部)
if i == 0:
# 根据方向确定眼睛位置
eye_size = GRID_SIZE // 5
if self.direction == RIGHT:
left_eye = (rect.right - eye_size*2, rect.top + eye_size*2)
right_eye = (rect.right - eye_size*2, rect.bottom - eye_size*3)
elif self.direction == LEFT:
left_eye = (rect.left + eye_size, rect.top + eye_size*2)
right_eye = (rect.left + eye_size, rect.bottom - eye_size*3)
elif self.direction == UP:
left_eye = (rect.left + eye_size*2, rect.top + eye_size)
right_eye = (rect.right - eye_size*3, rect.top + eye_size)
else: # DOWN
left_eye = (rect.left + eye_size*2, rect.bottom - eye_size*2)
right_eye = (rect.right - eye_size*3, rect.bottom - eye_size*2)
pygame.draw.circle(surface, (255, 255, 255), left_eye, eye_size)
pygame.draw.circle(surface, (255, 255, 255), right_eye, eye_size)
pygame.draw.circle(surface, (0, 0, 0), left_eye, eye_size//2)
pygame.draw.circle(surface, (0, 0, 0), right_eye, eye_size//2)
def grow(self):
"""蛇生长"""
self.grow_to += 1
self.score += 10
class Food:
def __init__(self):
self.position = (0, 0)
self.randomize_position()
def randomize_position(self):
"""随机生成食物位置"""
self.position = (
random.randint(0, GRID_WIDTH - 1),
random.randint(0, GRID_HEIGHT - 1)
)
def draw(self, surface):
"""绘制食物"""
rect = pygame.Rect(
self.position[0] * GRID_SIZE,
self.position[1] * GRID_SIZE,
GRID_SIZE, GRID_SIZE
)
# 绘制一个苹果形状的食物
pygame.draw.rect(surface, FOOD_COLOR, rect, border_radius=GRID_SIZE//3)
# 添加一个小茎
stem_rect = pygame.Rect(
rect.centerx - GRID_SIZE//10,
rect.top - GRID_SIZE//4,
GRID_SIZE//5,
GRID_SIZE//4
)
pygame.draw.rect(surface, (139, 69, 19), stem_rect)
# 添加一个高光
highlight = pygame.Rect(
rect.left + GRID_SIZE//4,
rect.top + GRID_SIZE//4,
GRID_SIZE//4,
GRID_SIZE//4
)
pygame.draw.ellipse(surface, (255, 100, 100), highlight)
class Game:
def __init__(self):
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("贪吃蛇游戏 - Python版")
self.clock = pygame.time.Clock()
self.font = pygame.font.SysFont('simhei', 25)
self.big_font = pygame.font.SysFont('simhei', 50)
self.snake = Snake()
self.food = Food()
self.speed = FPS
self.game_over = False
self.paused = False
# 确保食物不在蛇身上
while self.food.position in self.snake.positions:
self.food.randomize_position()
def draw_grid(self):
"""绘制游戏网格"""
for x in range(0, WIDTH, GRID_SIZE):
pygame.draw.line(self.screen, GRID_COLOR, (x, 0), (x, HEIGHT))
for y in range(0, HEIGHT, GRID_SIZE):
pygame.draw.line(self.screen, GRID_COLOR, (0, y), (WIDTH, y))
def draw_score(self):
"""绘制分数"""
score_text = self.font.render(f"分数: {self.snake.score}", True, SCORE_COLOR)
length_text = self.font.render(f"长度: {len(self.snake.positions)}", True, SCORE_COLOR)
self.screen.blit(score_text, (10, 10))
self.screen.blit(length_text, (10, 40))
# 绘制操作说明
controls = [
"方向键: 控制移动",
"空格键: 暂停/继续",
"R键: 重新开始",
"ESC键: 退出游戏"
]
for i, text in enumerate(controls):
control_text = self.font.render(text, True, TEXT_COLOR)
self.screen.blit(control_text, (WIDTH - control_text.get_width() - 10, 10 + i * 30))
def draw_game_over(self):
"""绘制游戏结束画面"""
game_over_surface = self.big_font.render("游戏结束!", True, (255, 50, 50))
score_surface = self.font.render(f"最终分数: {self.snake.score}", True, SCORE_COLOR)
restart_surface = self.font.render("按R键重新开始按ESC键退出", True, TEXT_COLOR)
# 居中显示
self.screen.blit(game_over_surface, (WIDTH//2 - game_over_surface.get_width()//2, HEIGHT//2 - 60))
self.screen.blit(score_surface, (WIDTH//2 - score_surface.get_width()//2, HEIGHT//2))
self.screen.blit(restart_surface, (WIDTH//2 - restart_surface.get_width()//2, HEIGHT//2 + 50))
def draw_pause(self):
"""绘制暂停画面"""
# 半透明覆盖层
overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
overlay.fill((0, 0, 0, 150))
self.screen.blit(overlay, (0, 0))
# 暂停文字
pause_surface = self.big_font.render("游戏暂停", True, (100, 200, 255))
continue_surface = self.font.render("按空格键继续游戏", True, TEXT_COLOR)
self.screen.blit(pause_surface, (WIDTH//2 - pause_surface.get_width()//2, HEIGHT//2 - 40))
self.screen.blit(continue_surface, (WIDTH//2 - continue_surface.get_width()//2, HEIGHT//2 + 20))
def check_food_collision(self):
"""检查是否吃到食物"""
if self.snake.get_head_position() == self.food.position:
self.snake.grow()
# 重新生成食物,确保不在蛇身上
while True:
self.food.randomize_position()
if self.food.position not in self.snake.positions:
break
# 每得100分增加一点速度
if self.snake.score % 100 == 0:
self.speed = min(self.speed + 1, 20) # 最大速度限制
def handle_events(self):
"""处理游戏事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
elif event.key == pygame.K_r:
# 重置游戏
self.__init__()
elif event.key == pygame.K_SPACE:
# 暂停/继续游戏
self.paused = not self.paused
# 方向控制
if not self.paused and not self.game_over:
if event.key == pygame.K_UP:
self.snake.turn(UP)
elif event.key == pygame.K_DOWN:
self.snake.turn(DOWN)
elif event.key == pygame.K_LEFT:
self.snake.turn(LEFT)
elif event.key == pygame.K_RIGHT:
self.snake.turn(RIGHT)
def run(self):
"""运行游戏主循环"""
while True:
self.handle_events()
# 如果游戏暂停,只绘制界面不更新游戏状态
if self.paused:
self.screen.fill(BACKGROUND)
self.draw_grid()
self.snake.draw(self.screen)
self.food.draw(self.screen)
self.draw_score()
self.draw_pause()
pygame.display.update()
self.clock.tick(FPS)
continue
# 如果游戏结束,显示结束画面
if self.game_over:
self.screen.fill(BACKGROUND)
self.draw_grid()
self.snake.draw(self.screen)
self.food.draw(self.screen)
self.draw_score()
self.draw_game_over()
pygame.display.update()
self.clock.tick(FPS)
continue
# 更新游戏状态
self.snake.move()
# 检查游戏是否结束
if not self.snake.is_alive:
self.game_over = True
# 检查是否吃到食物
self.check_food_collision()
# 绘制游戏
self.screen.fill(BACKGROUND)
self.draw_grid()
self.snake.draw(self.screen)
self.food.draw(self.screen)
self.draw_score()
# 如果游戏快结束了,闪烁提示
if not self.snake.is_alive:
# 蛇死亡时的闪烁效果
if int(time.time() * 10) % 2 == 0:
death_overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
death_overlay.fill((255, 50, 50, 50))
self.screen.blit(death_overlay, (0, 0))
pygame.display.update()
self.clock.tick(self.speed)
if __name__ == "__main__":
# 检查是否安装了pygame
try:
game = Game()
game.run()
except pygame.error as e:
print(f"错误: {e}")
print("请确保已安装pygame库可以使用以下命令安装:")
print("pip install pygame")
input("按回车键退出...")