pygame小游戏——贪吃蛇

前言

贪吃蛇(也叫做贪食蛇)游戏是一款休闲益智类游戏,既简单又耐玩,唯一的目标就是做这条gai上最长(pang)的蛇(zhu)

玩贪吃蛇最考验的就是走位(简称蛇皮走位),各种漂移过人,唉,就是玩儿!

在这里插入图片描述

基本设置

# 基本设置
lattice_wh = 20
snake_color = (84, 255, 159)
snake_head_color = (123, 104, 238)
food_color = (255, 64, 64)

绘制屏幕

# 绘制屏幕
pygame.init()
screen = pygame.display.set_mode((25*lattice_wh, 25*lattice_wh))
pygame.display.set_caption("贪吃蛇")

# 帧率,每秒刷新屏幕次数
FPS = 10
# 帧率变化系数
level = 1.5
# 时间对象
FPSCLOCK = pygame.time.Clock()
# 游戏结束标志
game_over = 0
# 前进方向
direction = 0
# 进食数量
num = 0

蛇类

# 蛇
class Snake():
    def __init__(self, snake_color, snake_head_color, x, y, lattice_wh):
        self.color = snake_color
        self.head_color = snake_head_color
        # 左上顶点坐标
        self.pos = (x, y)
        self.lattice_wh = lattice_wh
      	# 绘制蛇体
        self.rect = pygame.rect.Rect(x, y, self.lattice_wh, self.lattice_wh)
        # 左上顶点坐标变化
        self.pos_change = {
            # 上移
            1:(0, -self.lattice_wh),
            # 下移
            2:(0, self.lattice_wh),
            # 左移
            3:(-self.lattice_wh, 0),
            # 右移
            4:(self.lattice_wh, 0)
        }
	
    def move(self, direction):
        self.rect.x += self.pos_change[direction][0]
        self.rect.y += self.pos_change[direction][1]

    def forecast(self, direction):
        return (self.rect.x+self.pos_change[direction][0], self.rect.y+self.pos_change[direction][1])

食物类

# 食物
class Food():
    def __init__(self, food_color, screen, lattice_wh, x, y):
        self.screen = screen
        self.color = food_color
        self.lattice_wh = lattice_wh
        # 半径
        self.radius = lattice_wh/2
        self.x, self.y = x, y

    def draw(self):
        # 圆心
        pos = (self.x+self.lattice_wh/2, self.y+self.lattice_wh/2)
        # 绘制食物
        pygame.draw.circle(self.screen, self.color, pos, self.radius, int(self.radius))

初始状态

# 贪吃蛇
snakes = list()
snakes.append(Snake(snake_color, snake_head_color, lattice_wh, 24*lattice_wh, lattice_wh))
snakes.append(Snake(snake_color, snake_head_color, 0, 24*lattice_wh, lattice_wh))

# 食物
food = create_food(food_color, screen, lattice_wh, snakes)

# 游戏状态
game_stats = [game_over, direction, num, food]

生成食物

# 生成食物
def create_food(food_color, screen, lattice_wh, snakes):
    # 食物是否生成成功
    create_success = 0
    # 食物位置坐标
    food_x, food_y = 0, 0
    while not create_success:
        food_x, food_y = randint(0, 24), randint(0, 24)
        food_x *= lattice_wh
        food_y *= lattice_wh
        # 检查食物位置是否与贪吃蛇位置重合
        for snake in snakes:
            if (food_x, food_y) != (snake.rect.x, snake.rect.y):
                create_success = 1
                break
    # 在指定位置生成食物
    food = Food(food_color, screen, lattice_wh, food_x, food_y)
    return food

响应键鼠

# 响应键鼠
def check_events(game_stats):
    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_UP and game_stats[1] != 2:
                game_stats[1] = 1
            elif event.key == pygame.K_DOWN and game_stats[1] != 1:
                game_stats[1] = 2
            elif event.key == pygame.K_LEFT and game_stats[1] != 4:
                game_stats[1] = 3
            elif event.key == pygame.K_RIGHT and game_stats[1] != 3:
                game_stats[1] = 4
            else:
                game_stats[1] = game_stats[1]

更新屏幕

# 更新屏幕
def update(screen, lattice_wh, snakes, game_stats):
    screen.fill((255, 255, 255))
    # 绘制蛇头
    pygame.draw.rect(screen, snakes[0].head_color, snakes[0].rect)
    # 绘制蛇身
    for i in range(1, len(snakes)):
        pygame.draw.rect(screen, snakes[i].color, snakes[i].rect)
    # 绘制横线
    for i in range(25):
        pygame.draw.line(screen, (105, 105, 105), (0, lattice_wh*i), (500, lattice_wh*i))
    # 绘制竖线
    for i in range(25):
        pygame.draw.line(screen, (105, 105, 105), (lattice_wh*i, 0), (lattice_wh*i, 500))
    # 绘制食物
    game_stats[3].draw()
    # 更新屏幕
    pygame.display.flip()

移动进食

# 移动进食
def going(screen, game_stats, snakes, snake_head_color, snake_color, food_color, lattice_wh):
    if not game_stats[1]:
        return
    # 蛇头下一前进位置
    (x, y) = snakes[0].forecast(game_stats[1])
    # 检查是否触碰边界
    if x == -lattice_wh or x == 25*lattice_wh or y == -lattice_wh or y == 25*lattice_wh:
        game_stats[0] = 1
        return
    # 检查是否触碰食物
    if (x, y) == (game_stats[3].x, game_stats[3].y):
        # 更新蛇头
        new_head = Snake(snake_color, snake_head_color, x, y, lattice_wh)
        snakes.insert(0, new_head)
        # 更新分数
        game_stats[2] += 1
        # 重新生成食物
        game_stats[3] = create_food(food_color, screen, lattice_wh, snakes)
        return
    # 检查是否触碰蛇身
    for snake in snakes:
        if (x, y) == (snake.rect.x, snake.rect.y):
            game_stats[0] = 1
            return
    # 更新所有蛇身位置
    for i in range(len(snakes)-1, 0, -1):
        snakes[i].rect.x = snakes[i-1].rect.x
        snakes[i].rect.y = snakes[i-1].rect.y
    # 更新蛇头位置
    snakes[0].move(game_stats[1])

游戏入口

# 游戏入口
while not game_stats[0]:
    update(screen, lattice_wh, snakes, game_stats)
    check_events(game_stats)
    going(screen, game_stats, snakes, snake_head_color, snake_color, food_color, lattice_wh)
    FPSCLOCK.tick(FPS * level ** num if FPS * level ** num < 60 else 60)

snake.py

import pygame

# 蛇
class Snake():
    def __init__(self, snake_color, snake_head_color, x, y, lattice_wh):
        self.color = snake_color
        self.head_color = snake_head_color
        # 左上顶点坐标
        self.pos = (x, y)
        self.lattice_wh = lattice_wh
        # 绘制蛇体
        self.rect = pygame.rect.Rect(x, y, self.lattice_wh, self.lattice_wh)
        # 左上顶点坐标变化
        self.pos_change = {
            # 上移
            1:(0, -self.lattice_wh),
            # 下移
            2:(0, self.lattice_wh),
            # 左移
            3:(-self.lattice_wh, 0),
            # 右移
            4:(self.lattice_wh, 0)
        }

    # 移动
    def move(self, direction):
        self.rect.x += self.pos_change[direction][0]
        self.rect.y += self.pos_change[direction][1]

    # 下一前进位置
    def forecast(self, direction):
        return (self.rect.x+self.pos_change[direction][0], self.rect.y+self.pos_change[direction][1])

food.py

import pygame

# 食物
class Food():
    def __init__(self, food_color, screen, lattice_wh, x, y):
        self.screen = screen
        self.color = food_color
        self.lattice_wh = lattice_wh
        # 半径
        self.radius = lattice_wh/2
        self.x, self.y = x, y

    def draw(self):
        # 圆心
        pos = (self.x+self.lattice_wh/2, self.y+self.lattice_wh/2)
        # 绘制食物
        pygame.draw.circle(self.screen, self.color, pos, self.radius, int(self.radius))

function.py

import pygame
import sys
from random import randint
from food import Food
from snake import Snake

# 生成食物
def create_food(food_color, screen, lattice_wh, snakes):
    # 食物是否生成成功
    create_success = 0
    # 食物位置坐标
    food_x, food_y = 0, 0
    while not create_success:
        food_x, food_y = randint(0, 24), randint(0, 24)
        food_x *= lattice_wh
        food_y *= lattice_wh
        # 检查食物位置是否与贪吃蛇位置重合
        for snake in snakes:
            if (food_x, food_y) != (snake.rect.x, snake.rect.y):
                create_success = 1
                break
    # 在指定位置生成食物
    food = Food(food_color, screen, lattice_wh, food_x, food_y)
    return food

# 响应事件
def check_events(game_stats):
    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_UP and game_stats[1] != 2:
                game_stats[1] = 1
            elif event.key == pygame.K_DOWN and game_stats[1] != 1:
                game_stats[1] = 2
            elif event.key == pygame.K_LEFT and game_stats[1] != 4:
                game_stats[1] = 3
            elif event.key == pygame.K_RIGHT and game_stats[1] != 3:
                game_stats[1] = 4
            else:
                game_stats[1] = game_stats[1]

# 更新屏幕
def update(screen, lattice_wh, snakes, game_stats):
    screen.fill((255, 255, 255))
    # 绘制蛇头
    pygame.draw.rect(screen, snakes[0].head_color, snakes[0].rect)
    # 绘制蛇身
    for i in range(1, len(snakes)):
        pygame.draw.rect(screen, snakes[i].color, snakes[i].rect)
    # 绘制横线
    for i in range(25):
        pygame.draw.line(screen, (105, 105, 105), (0, lattice_wh*i), (500, lattice_wh*i))
    # 绘制竖线
    for i in range(25):
        pygame.draw.line(screen, (105, 105, 105), (lattice_wh*i, 0), (lattice_wh*i, 500))
    # 绘制食物
    game_stats[3].draw()
    # 更新屏幕
    pygame.display.flip()

# 移动进食
def going(screen, game_stats, snakes, snake_head_color, snake_color, food_color, lattice_wh):
    if not game_stats[1]:
        return
    # 蛇头下一前进位置
    (x, y) = snakes[0].forecast(game_stats[1])
    # 检查是否触碰边界
    if x == -lattice_wh or x == 25*lattice_wh or y == -lattice_wh or y == 25*lattice_wh:
        game_stats[0] = 1
        return
    # 检查是否触碰食物
    if (x, y) == (game_stats[3].x, game_stats[3].y):
        # 更新蛇头
        new_head = Snake(snake_color, snake_head_color, x, y, lattice_wh)
        snakes.insert(0, new_head)
        # 更新分数
        game_stats[2] += 1
        # 重新生成食物
        game_stats[3] = create_food(food_color, screen, lattice_wh, snakes)
        return
    # 检查是否触碰蛇身
    for snake in snakes:
        if (x, y) == (snake.rect.x, snake.rect.y):
            game_stats[0] = 1
            return
    # 更新所有蛇身位置
    for i in range(len(snakes)-1, 0, -1):
        snakes[i].rect.x = snakes[i-1].rect.x
        snakes[i].rect.y = snakes[i-1].rect.y
    # 更新蛇头位置
    snakes[0].move(game_stats[1])

main.py

import pygame
from function import *
from snake import Snake

# 基本设置
lattice_wh = 20
snake_color = (84, 255, 159)
snake_head_color = (123, 104, 238)
food_color = (255, 64, 64)

# 绘制屏幕
pygame.init()
screen = pygame.display.set_mode((25*lattice_wh, 25*lattice_wh))
pygame.display.set_caption("贪吃蛇")

# 帧率,每秒刷新屏幕次数
FPS = 10
# 帧率变化系数
level = 1.5
# 时间对象
FPSCLOCK = pygame.time.Clock()

# 游戏结束标志
game_over = 0

# 前进方向
direction = 0
# 进食数量
num = 0

# 贪吃蛇
snakes = list()
snakes.append(Snake(snake_color, snake_head_color, lattice_wh, 24*lattice_wh, lattice_wh))
snakes.append(Snake(snake_color, snake_head_color, 0, 24*lattice_wh, lattice_wh))

# 食物
food = create_food(food_color, screen, lattice_wh, snakes)

# 游戏状态
game_stats = [game_over, direction, num, food]

# 游戏入口
while not game_stats[0]:
    update(screen, lattice_wh, snakes, game_stats)
    check_events(game_stats)
    going(screen, game_stats, snakes, snake_head_color, snake_color, food_color, lattice_wh)
    FPSCLOCK.tick(FPS * level ** num if FPS * level ** num < 60 else 60)

敲黑板!!!在控制蛇的移动方向时,易忽略蛇不能直接反向移动这一问题;另外,在生成食物时,要检查食物的位置与蛇的位置是否重合,如果两者位置重合,此时需要生成新的食物。

python小游戏——井字棋:https://blog.csdn.net/KissMoon_/article/details/117437893

凉梦空间

欢迎你进入我的个人博客网站参观交流:https://www.liangmeng.xyz

在这里插入图片描述

  • 7
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凉丶梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值