diff --git a/main.py b/main.py index 724fc84b006cef4f6f7a992e88f42bbfa72ee8c7..724c1acc6c81078ff874104e7a0e5048f1c809b3 100644 --- a/main.py +++ b/main.py @@ -1,161 +1,216 @@ import pygame import sys import random +import time -# 全局定义 -SCREEN_X = 600 -SCREEN_Y = 600 - - -# 蛇类 -# 点以25为单位 -class Snake(object): - # 初始化各种需要的属性 [开始时默认向右/身体块x5] +class Snake: def __init__(self): - self.dirction = pygame.K_RIGHT + self.reset() + + def reset(self): + self.direction = pygame.K_RIGHT self.body = [] for x in range(5): - self.addnode() - - # 无论何时 都在前端增加蛇块 - def addnode(self): - left,top = (0,0) - if self.body: - left,top = (self.body[0].left,self.body[0].top) - node = pygame.Rect(left,top,25,25) - if self.dirction == pygame.K_LEFT: - node.left -= 25 - elif self.dirction == pygame.K_RIGHT: - node.left += 25 - elif self.dirction == pygame.K_UP: - node.top -= 25 - elif self.dirction == pygame.K_DOWN: - node.top += 25 - self.body.insert(0,node) - - # 删除最后一个块 - def delnode(self): + self.add_node() + self.last_direction = self.direction + + def add_node(self): + head = self.body[0].copy() if self.body else pygame.Rect(0, 0, 25, 25) + + if self.direction == pygame.K_LEFT: + head.x -= 25 + elif self.direction == pygame.K_RIGHT: + head.x += 25 + elif self.direction == pygame.K_UP: + head.y -= 25 + elif self.direction == pygame.K_DOWN: + head.y += 25 + + self.body.insert(0, head) + + def remove_tail(self): self.body.pop() - # 死亡判断 - def isdead(self): - # 撞墙 - if self.body[0].x not in range(SCREEN_X): - return True - if self.body[0].y not in range(SCREEN_Y): + def is_dead(self): + head = self.body[0] + + if head.x < 0 or head.x >= SCREEN_WIDTH or head.y < 0 or head.y >= SCREEN_HEIGHT: return True - # 撞自己 - if self.body[0] in self.body[1:]: + + if head in self.body[1:]: return True + return False - # 移动! def move(self): - self.addnode() - self.delnode() - - # 改变方向 但是左右、上下不能被逆向改变 - def changedirection(self,curkey): - LR = [pygame.K_LEFT,pygame.K_RIGHT] - UD = [pygame.K_UP,pygame.K_DOWN] - if curkey in LR+UD: - if (curkey in LR) and (self.dirction in LR): - return - if (curkey in UD) and (self.dirction in UD): - return - self.dirction = curkey - - -# 食物类 -# 方法: 放置/移除 -# 点以25为单位 + self.last_direction = self.direction + self.add_node() + self.remove_tail() + + def change_direction(self, new_direction): + # 防止180度转向 + if (new_direction == pygame.K_LEFT and self.last_direction == pygame.K_RIGHT or + new_direction == pygame.K_RIGHT and self.last_direction == pygame.K_LEFT or + new_direction == pygame.K_UP and self.last_direction == pygame.K_DOWN or + new_direction == pygame.K_DOWN and self.last_direction == pygame.K_UP): + return + + self.direction = new_direction + class Food: def __init__(self): - self.rect = pygame.Rect(-25,0,25,25) - - def remove(self): - self.rect.x=-25 - - def set(self): - if self.rect.x == -25: - allpos = [] - # 不靠墙太近 25 ~ SCREEN_X-25 之间 - for pos in range(25,SCREEN_X-25,25): - allpos.append(pos) - self.rect.left = random.choice(allpos) - self.rect.top = random.choice(allpos) - print(self.rect) + self.position = pygame.Rect(-25, 0, 25, 25) + self.color = (136, 0, 21) + + def random_position(self, snake_body): + while True: + x = random.randrange(1, SCREEN_WIDTH // 25 - 1) * 25 + y = random.randrange(1, SCREEN_HEIGHT // 25 - 1) * 25 + self.position = pygame.Rect(x, y, 25, 25) + # 确保食物不会生成在蛇身上 + if self.position not in snake_body: + break + + def draw(self, screen): + pygame.draw.rect(screen, self.color, self.position) -def show_text(screen, pos, text, color, font_bold = False, font_size = 60, font_italic = False): - #获取系统字体,并设置文字大小 - cur_font = pygame.font.SysFont("宋体", font_size) - #设置是否加粗属性 - cur_font.set_bold(font_bold) - #设置是否斜体属性 - cur_font.set_italic(font_italic) - #设置文字内容 - text_fmt = cur_font.render(text, 1, color) - #绘制文字 - screen.blit(text_fmt, pos) - - -def main(): - pygame.init() - screen_size = (SCREEN_X,SCREEN_Y) - screen = pygame.display.set_mode(screen_size) - pygame.display.set_caption('Snake') - clock = pygame.time.Clock() - scores = 0 - isdead = False - - # 蛇/食物 - snake = Snake() - food = Food() - - while True: +class Game: + def __init__(self): + pygame.init() + pygame.font.init() + + self.width = SCREEN_WIDTH + self.height = SCREEN_HEIGHT + self.screen = pygame.display.set_mode((self.width, self.height)) + pygame.display.set_caption("贪吃蛇大冒险") + + self.clock = pygame.time.Clock() + self.font = pygame.font.SysFont("SimHei", 30) + + self.snake = Snake() + self.food = Food() + self.score = 0 + self.high_score = 0 + self.game_over = False + self.paused = False + + self.food.random_position(self.snake.body) + + def handle_events(self): for event in pygame.event.get(): if event.type == pygame.QUIT: + pygame.quit() sys.exit() + if event.type == pygame.KEYDOWN: - snake.changedirection(event.key) - # 死后按space重新 - if event.key == pygame.K_SPACE and isdead: - return main() + if event.key == pygame.K_ESCAPE: + pygame.quit() + sys.exit() + + if self.game_over: + if event.key == pygame.K_SPACE: + self.reset_game() + return + + if event.key == pygame.K_p: + self.paused = not self.paused + + self.snake.change_direction(event.key) + def update(self): + if self.game_over or self.paused: + return - screen.fill((255,255,255)) - - # 画蛇身 / 每一步+1分 - if not isdead: - scores+=1 - snake.move() - for rect in snake.body: - pygame.draw.rect(screen,(20,220,39),rect,0) + self.snake.move() + + if self.snake.is_dead(): + self.game_over = True + return - # 显示死亡文字 - isdead = snake.isdead() - if isdead: - show_text(screen,(100,200),'YOU DEAD!',(227,29,18),False,100) - show_text(screen,(150,260),'press space to try again...',(0,0,22),False,30) + if self.snake.body[0].colliderect(self.food.position): + self.score += 50 + self.snake.add_node() + # 确保新食物不会生成在蛇身上 + self.food.random_position(self.snake.body) - # 食物处理 / 吃到+50分 - # 当食物rect与蛇头重合,吃掉 -> Snake增加一个Node - if food.rect == snake.body[0]: - scores+=50 - food.remove() - snake.addnode() - - # 食物投递 - food.set() - pygame.draw.rect(screen,(136,0,21),food.rect,0) - - # 显示分数文字 - show_text(screen,(50,500),'Scores: '+str(scores),(223,223,223)) - - pygame.display.update() - clock.tick(10) - - -if __name__ == '__main__': - main() \ No newline at end of file + # 每吃5个食物加速一次 + if (self.score // 50) % 5 == 0: + self.clock.tick += 2 + + def draw(self): + self.screen.fill((255, 255, 255)) + + # 绘制网格背景 + self.draw_grid() + + # 绘制蛇 + for segment in self.snake.body: + pygame.draw.rect(self.screen, (20, 220, 39), segment) + pygame.draw.rect(self.screen, (0, 0, 0), segment, 1) + + # 绘制蛇头 + head = self.snake.body[0] + pygame.draw.rect(self.screen, (0, 150, 0), head) + + # 绘制食物 + self.food.draw(self.screen) + + # 绘制分数 + self.draw_text(f"分数: {self.score}", 20, 20) + self.draw_text(f"最高分: {self.high_score}", 20, 50) + + # 游戏结束画面 + if self.game_over: + self.draw_centered_text("游戏结束!", 200, 60, (255, 0, 0)) + self.draw_centered_text(f"最终分数: {self.score}", 280, 40) + self.draw_centered_text("按空格键重新开始", 330, 30) + + # 暂停画面 + if self.paused: + self.draw_centered_text("游戏暂停", 250, 60) + self.draw_centered_text("按P键继续", 310, 30) + + pygame.display.flip() + + def draw_grid(self): + for x in range(0, self.width, 25): + pygame.draw.line(self.screen, (240, 240, 240), (x, 0), (x, self.height)) + for y in range(0, self.height, 25): + pygame.draw.line(self.screen, (240, 240, 240), (0, y), (self.width, y)) + + def draw_text(self, text, x, y): + text_surface = self.font.render(text, True, (0, 0, 0)) + self.screen.blit(text_surface, (x, y)) + + def draw_centered_text(self, text, y, size, color=(0, 0, 0)): + font = pygame.font.SysFont("SimHei", size) + text_surface = font.render(text, True, color) + text_rect = text_surface.get_rect(center=(self.width // 2, y)) + self.screen.blit(text_surface, text_rect) + + def reset_game(self): + if self.score > self.high_score: + self.high_score = self.score + + self.score = 0 + self.game_over = False + self.snake.reset() + # 确保新游戏开始时食物不会生成在蛇身上 + self.food.random_position(self.snake.body) + self.clock.tick = 10 + + def run(self): + while True: + self.handle_events() + self.update() + self.draw() + self.clock.tick(10) # 初始速度 + +# 全局设置 +SCREEN_WIDTH = 600 +SCREEN_HEIGHT = 600 + +if __name__ == "__main__": + game = Game() + game.run() \ No newline at end of file