【MVCD 7】

CS 41 课程九:游戏开发(5月24日)

一、课程基本信息

日期 :2023年5月24日
主题:🐍 Gaming(游戏开发)

课程安排

下周预览

  • 单元测试(Unit Testing)
  • Pygame游戏开发

二、使用Python制作游戏

1. 游戏示例展示

Example Games(课堂演示各种Python游戏)

2. Pygame安装

安装说明

  • Pygame是非标准库包(上周学习内容)
  • 需要使用pip安装
bash 复制代码
pip install pygame

三、游戏循环(Game Loop)

1. 游戏循环概念

核心作用

  • 游戏控制的中心
  • 更新游戏状态
  • 每个循环周期就是一帧(frame)

基本结构

python 复制代码
running = True
while running:
    # 1. 处理事件
    # 2. 更新游戏状态
    # 3. 绘制画面
    # 4. 刷新显示

四、事件系统(Events)

1. 什么是事件?

定义

  • 用户操作,游戏循环围绕这些操作展开
  • 通过事件处理器(event handler)访问
  • 每个事件都有一个类型

2. 事件类型

常见事件类型

事件类型 说明
QUIT 退出事件
ACTIVEEVENT 窗口激活事件
KEYDOWN 按键按下
KEYUP 按键释放
MOUSEMOTION 鼠标移动
MOUSEBUTTONUP 鼠标按钮释放
MOUSEBUTTONDOWN 鼠标按钮按下
JOYAXISMOTION 游戏手柄轴移动
JOYBALLMOTION 游戏手柄球移动
JOYHATMOTION 游戏手柄帽移动
JOYBUTTONUP 游戏手柄按钮释放
JOYBUTTONDOWN 游戏手柄按钮按下
VIDEORESIZE 视频窗口调整大小
VIDEOEXPOSE 视频窗口曝光
USEREVENT 用户自定义事件

3. 事件队列

访问事件

python 复制代码
for event in pygame.event.get():
    # 处理事件

事件对象示例

python 复制代码
<Event(768-KeyDown {
    'unicode': '', 
    'key': 1073741906, 
    'mod': 0, 
    'scancode': 82, 
    'window': None
})>

<Event(769-KeyUp {
    'unicode': '', 
    'key': 1073741906, 
    'mod': 0, 
    'scancode': 82, 
    'window': None
})>

特点

  • 事件存储在队列中
  • 按顺序处理
  • 包含详细的事件信息

五、第一个图形窗口

1. 完整代码示例

python 复制代码
import pygame

pygame.init()
screen = pygame.display.set_mode((500, 500))
white = (255, 255, 255)
blue = (0, 0, 255)

running = True

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    
    # 用白色填充背景
    screen.fill(white)
    
    # 在中心绘制蓝色实心圆
    pygame.draw.circle(screen, blue, (250, 250), 75)
    
    # 更新显示
    pygame.display.update()  # 或使用 pygame.display.flip()

# 游戏结束时
pygame.quit()

2. 代码详解

(1) 初始化窗口
python 复制代码
import pygame
pygame.init()
screen = pygame.display.set_mode((500, 500))
  • 导入pygame库
  • 初始化pygame
  • 创建500x500像素的窗口
(2) 定义颜色
python 复制代码
white = (255, 255, 255)
blue = (0, 0, 255)
  • 使用RGB元组表示颜色
  • (R, G, B) 每个值范围0-255
(3) 初始化游戏循环
python 复制代码
running = True
while running:
  • 控制游戏运行状态
  • 循环直到running变为False
(4) 获取事件队列
python 复制代码
for event in pygame.event.get():
  • 获取所有事件
  • 遍历事件队列
(5) 检查事件类型
python 复制代码
if event.type == pygame.QUIT:
    running = False
  • 检查是否点击关闭按钮
  • 退出游戏循环
(6) 绘制图形
python 复制代码
screen.fill(white)
pygame.draw.circle(screen, blue, (250, 250), 75)
  • screen.fill(white): 填充背景色
  • pygame.draw.circle(): 绘制圆形
    • 参数1: 绘制表面
    • 参数2: 颜色
    • 参数3: (x, y) 圆心坐标
    • 参数4: 半径
(7) 更新显示
python 复制代码
pygame.display.update()  # 或 pygame.display.flip()
  • 刷新屏幕显示
  • 显示所有绘制内容

运行代码:Let's run this code


六、制作贪吃蛇游戏

1. 绘制矩形基础

python 复制代码
pygame.draw.rect(surface, color, rect)

参数说明

  • surface: 绘制表面(screen)
  • color: 颜色元组
  • rect: 矩形 [left, top, width, height]

示例

python 复制代码
# 绘制一个蛇的方块
pygame.draw.rect(screen, blue, [100, 100, 10, 10])

2. 键盘控制

检测按键事件
python 复制代码
if event.type == pygame.KEYDOWN:
    if event.key == pygame.K_LEFT:
        # 向左移动
    if event.key == pygame.K_RIGHT:
        # 向右移动
    if event.key == pygame.K_UP:
        # 向上移动
    if event.key == pygame.K_DOWN:
        # 向下移动

按键常量

  • pygame.K_LEFT: 左箭头
  • pygame.K_RIGHT: 右箭头
  • pygame.K_UP: 上箭头
  • pygame.K_DOWN: 下箭头

3. 蛇的表示与移动

数据结构
python 复制代码
# 使用坐标元组列表表示蛇
snake = [(100, 100), (100, 110), (100, 120)]
移动策略问题

方法1:更新所有坐标(复杂)

复制代码
问题:蛇头需要向下移动snake_size
      但需要遍历整个列表更新所有过去的坐标 :(

方法2:添加和删除(优雅)✓

复制代码
步骤1: 在蛇头应该在的位置添加新方块
步骤2: 删除最后一个方块

图示

复制代码
移动前: [█][█][█]
           ↓
添加新头: [█][█][█][█]
           ↓
删除尾部: [█][█][█]  (新位置)

4. 动画速度控制

时钟控制

python 复制代码
pygame.time.Clock().tick(15)

作用

  • 确保游戏循环最多以每秒15帧运行
  • 放在循环内部
  • 控制游戏速度,使其在不同电脑上表现一致

帧率说明

python 复制代码
# 慢速游戏
pygame.time.Clock().tick(10)  # 10 FPS

# 正常速度
pygame.time.Clock().tick(15)  # 15 FPS

# 快速游戏
pygame.time.Clock().tick(30)  # 30 FPS

七、完整贪吃蛇代码实现

1. 常量和初始化

python 复制代码
import time
import random
import pygame

# 常量和变量
white = (255, 255, 255)
blue = (50, 153, 213)
green = (0, 255, 0)

dis_width = 600
dis_height = 400

block_size = 10
snake_length = 15

# 初始化pygame窗口
pygame.init()
screen = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('CS 41 PYTHON')

2. 辅助函数

(1) 初始化蛇
python 复制代码
def initialize_snake(len, start_left, start_top):
    initialize_snake = []
    for i in range(len):
        initialize_snake.append((start_left, start_top + (block_size * i)))
    return initialize_snake
(2) 绘制蛇
python 复制代码
def draw_snake(snake_coords):
    for x, y in snake_coords:
        pygame.draw.rect(screen, blue, [x, y, block_size, block_size])
(3) 更新蛇的位置
python 复制代码
def update_snake(x, y, snake):
    snake.append((x, y))
    if len(snake) > snake_length:
        del snake[0]
    return snake

工作原理

  • 在蛇头位置添加新方块
  • 如果蛇长度超过限制,删除尾部
  • 实现"移动"效果
(4) 生成食物
python 复制代码
def generate_food(snake):
    while True:
        food_x = random.randrange(0, dis_width, block_size)
        food_y = random.randrange(0, dis_height, block_size)
        if (food_x, food_y) not in snake:
            return food_x, food_y

重要细节

  • 使用random.randrange()生成随机坐标
  • 步长为block_size确保食物在网格上
  • 检查食物不与蛇重叠
(5) 绘制食物
python 复制代码
def draw_food(food_x, food_y):
    pygame.draw.rect(screen, green, [food_x, food_y, block_size, block_size])
(6) 碰撞检测
python 复制代码
def check_collision(snake_head, food_x, food_y):
    if snake_head[0] == food_x and snake_head[1] == food_y:
        return True
    return False

3. 主游戏函数

python 复制代码
def game():
    global snake_length  # 使用全局变量
    running = True
    x_change = 0
    y_change = 0
    x = dis_width / 2
    y = dis_height / 2
    snake = initialize_snake(snake_length, x, y)
    food_x, food_y = generate_food(snake)

    while running:
        screen.fill(white)
        draw_snake(snake)
        draw_food(food_x, food_y)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x_change = -block_size
                    y_change = 0
                if event.key == pygame.K_RIGHT:
                    x_change = block_size
                    y_change = 0
                if event.key == pygame.K_UP:
                    x_change = 0
                    y_change = -block_size
                if event.key == pygame.K_DOWN:
                    x_change = 0
                    y_change = block_size

        x += x_change
        y += y_change
        snake = update_snake(x, y, snake)
       
        if check_collision(snake[-1], food_x, food_y):
            snake_length += 1
            food_x, food_y = generate_food(snake)
        draw_snake(snake)

        pygame.time.Clock().tick(15)
        pygame.display.flip()

    pygame.quit()

if __name__ == "__main__":
    game()

4. 游戏逻辑流程

每帧执行步骤

复制代码
1. 清空屏幕(填充白色)
2. 绘制蛇和食物
3. 处理事件(键盘输入、退出)
4. 更新蛇的位置
5. 检查是否吃到食物
6. 如果吃到食物:
   - 增加蛇的长度
   - 生成新食物
7. 重新绘制
8. 控制帧率(15 FPS)
9. 刷新显示

八、小组活动

活动说明

任务:为贪吃蛇游戏添加食物功能

准备工作

  • 确保已安装pygame:pip install pygame
  • 从网站下载starter code

功能要求

  1. 食物碰撞

    • 当蛇碰到食物时,蛇增长1个单位
  2. 食物生成

    • 食物应该出现在窗口的随机位置
    • 被吃掉后重新出现
  3. 提示

    • 思考蛇移动的倍数
    • 食物坐标应该只在这些倍数位置上
  4. 扩展功能(可选):

    • 如果想添加其他有趣的功能,随意发挥!

实现建议

关键点

python 复制代码
# 1. 食物坐标必须是block_size的倍数
food_x = random.randrange(0, dis_width, block_size)
food_y = random.randrange(0, dis_height, block_size)

# 2. 检测碰撞
if snake_head == (food_x, food_y):
    snake_length += 1
    # 生成新食物

# 3. 确保食物不在蛇身上
while (food_x, food_y) in snake:
    # 重新生成

九、课程总结

Pygame核心概念

游戏开发三要素

复制代码
1. 游戏循环(Game Loop)
   └─ 持续运行直到游戏结束

2. 事件处理(Event Handling)
   └─ 响应用户输入

3. 绘制更新(Draw & Update)
   └─ 显示游戏状态

游戏循环模式

python 复制代码
# 标准游戏循环模式
pygame.init()
screen = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()
running = True

while running:
    # 1. 处理事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        # 其他事件处理
    
    # 2. 更新游戏逻辑
    # 更新位置、检测碰撞等
    
    # 3. 绘制
    screen.fill(background_color)
    # 绘制游戏元素
    
    # 4. 刷新和控制帧率
    pygame.display.flip()
    clock.tick(FPS)

pygame.quit()

Pygame常用函数速查

初始化与窗口

python 复制代码
pygame.init()
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Title')

事件处理

python 复制代码
pygame.event.get()           # 获取所有事件
event.type                   # 事件类型
event.key                    # 按键值

绘制函数

python 复制代码
screen.fill(color)                              # 填充背景
pygame.draw.circle(screen, color, (x,y), r)    # 圆形
pygame.draw.rect(screen, color, [x,y,w,h])     # 矩形
pygame.draw.line(screen, color, (x1,y1), (x2,y2)) # 线条

显示更新

python 复制代码
pygame.display.flip()        # 刷新整个屏幕
pygame.display.update()      # 更新特定区域

时间控制

python 复制代码
clock = pygame.time.Clock()
clock.tick(FPS)              # 控制帧率

贪吃蛇实现要点

数据结构选择

python 复制代码
# 用列表存储蛇的所有方块
snake = [(x1, y1), (x2, y2), (x3, y3)]

# 蛇头:snake[-1]
# 蛇尾:snake[0]

移动算法

python 复制代码
# 添加新头
snake.append((new_x, new_y))

# 删除旧尾(如果没吃食物)
if not ate_food:
    del snake[0]

网格对齐

python 复制代码
# 确保所有坐标都是block_size的倍数
x = random.randrange(0, width, block_size)
y = random.randrange(0, height, block_size)

可能的扩展功能

基础扩展

  1. 添加得分显示
  2. 增加游戏难度(随时间加速)
  3. 添加边界检测(撞墙游戏结束)
  4. 添加自咬检测(蛇咬到自己)

进阶扩展

  1. 多个食物

  2. 特殊食物(加速/减速/双倍分数)

  3. 障碍物

  4. 暂停功能

  5. 最高分记录

  6. 音效和背景音乐

调试技巧

常见问题

python 复制代码
# 1. 窗口一闪而过
# 解决:确保有游戏循环和事件处理

# 2. 游戏太快/太慢
# 解决:调整clock.tick()的参数

# 3. 绘制不显示
# 解决:确保调用了pygame.display.flip()

# 4. 蛇移动不连续
# 解决:确保坐标是block_size的倍数

学习资源

官方文档

教程推荐

  • Pygame官方教程
  • Real Python的Pygame系列
  • YouTube上的游戏开发教程

关键要点

  1. 游戏循环是核心

    • 所有游戏都基于循环
    • 每帧更新状态和绘制
  2. 事件驱动编程

    • 响应用户输入
    • 处理各种事件类型
  3. 帧率控制重要

    • 使用Clock控制速度
    • 保证不同设备体验一致
  4. 数据结构选择

    • 合适的数据结构简化逻辑
    • 列表非常适合表示蛇
  5. 模块化设计

    • 将功能分解为函数
    • 提高代码可读性和可维护性
相关推荐
Chris_12197 分钟前
Halcon学习笔记-Day6进阶:工业级视觉系统核心技术详解
人工智能·python·深度学习·halcon
飞鸟真人1 小时前
关于python -m http.server的一些安全问题
python·安全·http
tjjucheng1 小时前
小程序定制开发哪家性价比高
python
No0d1es1 小时前
2025年12月 GESP CCF编程能力等级认证Python六级真题
python·青少年编程·gesp·ccf·六级
亮子AI1 小时前
【Python】比较两个cli库:Click vs Typer
开发语言·python
CappuccinoRose2 小时前
流计算概述
python·flink·流计算·数据流·pyflink
Dragon水魅2 小时前
Fandom Wiki 网站爬取文本信息踩坑实录
爬虫·python
Darkershadow2 小时前
蓝牙学习之unprovision beacon
python·学习·ble
小龙在山东2 小时前
基于 plumbum 跨平台执行Shell脚本
python