赛博红兔的科技博客

CyberHongTu shares news, insights, and musings on fascinating technology subjects.


和我一起做3A游戏《贪吃蛇》

大家好,我是赛博红兔。欢迎继续收看我的《和我一起做3A游戏》系列!在介绍今天的游戏之前,我建议没有任何pygame基础的小伙伴们先去看看本系列的前三集基础教学,链接我会放在下方评论区。今天,带给大伙的是一款家喻户晓的经典游戏——贪吃蛇。”贪吃蛇”最早可以追溯到1976年的街机游戏《Blockade》,它经过了诺基亚手机的成功移植,迅速成为手机游戏的代表作之一。在游戏中,玩家控制一条蛇在屏幕上移动,吃掉食物来增加长度。游戏的目标是尽可能让蛇变长,同时避免撞到墙壁或蛇自己的身体。随着蛇的长度增加,游戏难度逐渐提升,玩家需要快速的反应和策略来避免碰撞。那么作为学习Pygame的一个小项目,我们也来山寨这款老游戏。我已经把这个游戏用到的资源、代码还有EXE的应用程序打包放在百度网盘了,链接会放在下面,代码也可以去我的GitHub或者博客下载。你可以按照上面的安装说明部署项目,都写得比较详细了。如果,只想玩这个游戏的朋友,可以直接运行我打包好的EXE应用文件,在电脑上直接跑不需要安装python。记住,跑这个游戏的电脑需要有一张声卡来运行背景音乐,而且一定要把应用程序和assets也就是游戏资源包放在一起,不然会出错。

想继续学习这游戏是怎么做的朋友请往下看。首先,我在第一集已经介绍了我所有的游戏资源,包括图片、声效、BGM,都是从这两个开源网站下载的,大家也可以共享一下自己了解的游戏资源库。接下来我们看到的是游戏源代码,这里,我主要会重点介绍之前没有见过的pygame功能和游戏特色部分的代码。具体大伙可以按照我的源代码去学习和拓展。

1. 导入模块

from random import randint
from sys import exit
import pygame as pg
  • randint: 用于生成随机整数,用于生成食物的位置。
  • exit: 用于在游戏结束时退出程序。
  • pygame: 一个用于制作2D游戏的Python库,提供了绘图、声音、事件处理等功能。

2. 游戏参数设置

WIDTH, HEIGHT = 800, 800
GRID_WIDTH = 40
ROW_NUMBER = WIDTH // GRID_WIDTH
REACTION_TIME = 100
DELAY_TIME = 4000
FPS = 30
MOVING_SPEED = GRID_WIDTH
UP, DOWN, LEFT, RIGHT = range(4)
DIRECTIONS = {
    UP: (0, -MOVING_SPEED),
    DOWN: (0, MOVING_SPEED),
    LEFT: (-MOVING_SPEED, 0),
    RIGHT: (MOVING_SPEED, 0),
}
  • 设置游戏的窗口大小、网格大小和行数。
  • REACTION_TIME:反应延迟,确保玩家有足够时间操作。
  • FPS:帧率,用于控制游戏的运行速度。
  • MOVING_SPEED:蛇每次移动的距离与网格大小一致。
  • DIRECTIONS:蛇移动的方向与相应的坐标偏移值。

3. 加载资源路径

GRASS_BACKGROUND = 'assets/image/grass.png'
SNAKE_HEAD = ['assets/image/head_up.png', 'assets/image/head_down.png',
              'assets/image/head_left.png', 'assets/image/head_right.png']
SNAKE_BODY = 'assets/image/body.png'
FOOD = 'assets/image/food.png'
BITE_SOUND = 'assets/sound/apple_bite.ogg'
HIT_SOUND = 'assets/sound/hit.mp3'
MUSIC = 'assets/sound/snake_bgm.mp3'
  • 定义游戏使用的图片和音频文件的路径,包括背景、蛇头、蛇身、食物、咬食音效、碰撞音效和背景音乐。

4. 定义事件

SNAKE_GROW = pg.USEREVENT + 1
SNAKE_HIT = pg.USEREVENT + 2
  • 自定义两个Pygame事件:SNAKE_GROW用于蛇吃到食物后增长,SNAKE_HIT用于蛇撞到自己后游戏结束。

5. Snake类

class Snake(pg.sprite.Sprite):
    def __init__(self, idx=0, ishead=True, position=None, direction=LEFT):
        ...
    def move(self):
        ...
    def update(self):
        self.move()
  • Snake类继承自Pygame的Sprite类,表示游戏中的蛇。
  • __init__:初始化蛇的头或身体部位,加载相应的图像资源。
  • move:控制蛇的移动,蛇头根据键盘方向键改变方向,身体则跟随头部移动。
  • update:每帧更新蛇的位置。

6. Food类

class Food(pg.sprite.Sprite):
    def __init__(self):
        ...
    def food_spawn(self):
        ...
  • Food类继承自Sprite,表示游戏中的食物。
  • food_spawn:随机生成食物位置,确保食物不会出现在蛇的身体上。

7. Game类

class Game:
    def __init__(self):
        ...
    def draw_grid(self):
        ...
    def draw_grass(self):
        ...
    def draw_score(self, text):
        ...
    def snake_grow(self):
        ...
    def collision(self):
        ...
    def handle_events(self):
        ...
    def main_loop(self):
        ...
  • Game类负责游戏的整体控制,包括界面绘制、音乐播放、事件处理等。
  • __init__:初始化Pygame,加载背景音乐和音效,创建窗口。
  • draw_griddraw_grass:绘制游戏背景和网格。
  • draw_score:在游戏结束时显示分数信息。
  • snake_grow:增加蛇的长度。
  • collision:处理蛇与食物、蛇与自身的碰撞。
  • handle_events:处理键盘和游戏事件,如关闭窗口、蛇吃到食物或蛇死亡。
  • main_loop:主游戏循环,持续更新游戏状态,检测事件和碰撞。

8. 游戏主逻辑

game = Game()
snake = pg.sprite.Group()
snake.add(Snake())
food = pg.sprite.GroupSingle()
food.add(Food())
game.main_loop()
  • 实例化游戏、蛇和食物,并启动主游戏循环。

总结

这段代码实现了一个简单的贪吃蛇游戏,主要功能包括:

  • 控制蛇的移动;
  • 随机生成食物;
  • 处理蛇与自身的碰撞(游戏结束)和蛇吃到食物(长度增加)。


Leave a comment