Python游戏开发:Pygame全面指南与实战
第一章 Pygame简介与安装
1.1 Pygame概述
Pygame是一个开源的Python模块,专门用于多媒体应用(如电子游戏)的开发。它基于SDL(Simple DirectMedia Layer)库构建,提供了对图形、声音、输入设备等游戏开发所需功能的访问接口。Pygame最初由Pete Shinners于2000年创建,至今已成为Python游戏开发最流行的库之一。
Pygame的主要特点包括:
- 简单易用的API设计
- 跨平台支持(Windows、Mac OS X、Linux等)
- 无需复杂的环境配置
- 丰富的功能模块
- 活跃的社区支持
1.2 Pygame与其他游戏引擎的比较
与其他游戏开发工具相比,Pygame有其独特的优势和不足:
特性 | Pygame | Unity | Unreal Engine | Godot |
---|---|---|---|---|
学习曲线 | 平缓 | 中等 | 陡峭 | 中等 |
编程语言 | Python | C# | C++ | GDScript |
2D支持 | 优秀 | 良好 | 一般 | 优秀 |
3D支持 | 有限 | 优秀 | 卓越 | 良好 |
性能 | 中等 | 高 | 极高 | 高 |
适合项目规模 | 小型 | 大中型 | 大型 | 中小型 |
1.3 安装Pygame
安装Pygame非常简单,可以通过pip直接安装:
pip install pygame
验证安装是否成功:
import pygame
print(pygame.__version__) # 应输出安装的版本号
1.4 Pygame基础架构
Pygame的核心架构围绕以下几个主要组件构建:
- 显示模块:管理窗口和屏幕显示
- 事件系统:处理用户输入和系统事件
- 图像模块:加载和操作图像
- 声音模块:播放音效和音乐
- 时间控制:管理游戏帧率和计时
- 精灵系统:游戏对象管理
第二章 Pygame基础:第一个游戏窗口
2.1 初始化Pygame
在开始使用Pygame之前,需要先初始化所有模块:
import pygame# 初始化所有Pygame模块
pygame.init()# 设置窗口尺寸
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))# 设置窗口标题
pygame.display.set_caption("我的第一个Pygame窗口")# 游戏主循环
running = True
while running:for event in pygame.event.get():if event.type == pygame.QUIT:running = False# 填充背景色(RGB)screen.fill((135, 206, 235)) # 天蓝色背景# 更新显示pygame.display.flip()# 退出Pygame
pygame.quit()
2.2 游戏主循环解析
游戏主循环是Pygame程序的核心,通常包含以下步骤:
- 事件处理:检查用户输入和系统事件
- 游戏逻辑更新:更新游戏状态
- 渲染绘制:绘制当前帧的画面
- 帧率控制:控制游戏运行速度
2.3 基本绘图功能
Pygame提供了一系列基本绘图函数:
# 绘制矩形
pygame.draw.rect(screen, (255, 0, 0), (100, 100, 200, 100)) # 红色矩形# 绘制圆形
pygame.draw.circle(screen, (0, 255, 0), (400, 300), 50) # 绿色圆形# 绘制线条
pygame.draw.line(screen, (0, 0, 255), (50, 50), (750, 550), 5) # 蓝色线条# 绘制多边形
pygame.draw.polygon(screen, (255, 255, 0), [(200, 200), (300, 100), (400, 200)]) # 黄色多边形
2.4 完整示例:简单绘图板
import pygame
import syspygame.init()# 设置窗口
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("简单绘图板")# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)# 绘图设置
drawing = False
last_pos = None
color = BLACK
radius = 5# 游戏主循环
while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()# 鼠标按下开始绘图elif event.type == pygame.MOUSEBUTTONDOWN:if event.button == 1: # 左键drawing = Truelast_pos = event.poselif event.button == 3: # 右键screen.fill(WHITE) # 清空画布# 鼠标移动时绘图elif event.type == pygame.MOUSEMOTION:if drawing and event.buttons[0]: # 左键拖动if last_pos:pygame.draw.line(screen, color, last_pos, event.pos, radius * 2)last_pos = event.pos# 鼠标释放停止绘图elif event.type == pygame.MOUSEBUTTONUP:if event.button == 1:drawing = Falselast_pos = None# 键盘控制elif event.type == pygame.KEYDOWN:if event.key == pygame.K_r:color = REDelif event.key == pygame.K_g:color = GREENelif event.key == pygame.K_b:color = BLUEelif event.key == pygame.K_UP:radius = min(50, radius + 1)elif event.key == pygame.K_DOWN:radius = max(1, radius - 1)# 显示当前设置info_surface = pygame.Surface((200, 100))info_surface.fill(WHITE)font = pygame.font.SysFont(None, 24)color_text = font.render(f"颜色: {color}", True, BLACK)radius_text = font.render(f"粗细: {radius}", True, BLACK)info_surface.blit(color_text, (10, 10))info_surface.blit(radius_text, (10, 40))screen.blit(info_surface, (10, 10))pygame.display.flip()
第三章 Pygame图像处理与动画
3.1 加载和显示图像
Pygame支持多种图像格式,包括PNG、JPG、BMP等:
# 加载图像
player_img = pygame.image.load("player.png").convert_alpha()# 显示图像
screen.blit(player_img, (100, 100))
convert()
和convert_alpha()
方法可以优化图像显示性能,后者保留alpha通道(透明度)。
3.2 图像变换
Pygame提供了一些基本的图像变换功能:
# 缩放图像
scaled_img = pygame.transform.scale(player_img, (50, 50))# 旋转图像
rotated_img = pygame.transform.rotate(player_img, 45) # 旋转45度# 翻转图像
flipped_img = pygame.transform.flip(player_img, True, False) # 水平翻转
3.3 动画实现原理
游戏动画通常通过快速连续显示一系列略有不同的图像(帧)来实现。在Pygame中,可以通过以下步骤创建动画:
- 加载所有动画帧
- 在游戏循环中按顺序显示这些帧
- 控制帧切换速度
3.4 完整示例:角色动画
import pygame
import ospygame.init()# 设置窗口
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("角色动画演示")# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)# 加载动画帧
animation_frames = []
for i in range(1, 7):frame = pygame.image.load(f"run_animation/frame_{i}.png").convert_alpha()frame = pygame.transform.scale(frame, (100, 100))animation_frames.append(frame)# 动画设置
current_frame = 0
animation_speed = 0.2 # 每秒切换几帧
frame_count = 0# 角色位置
player_x = 100
player_y = 400
player_speed = 3# 游戏时钟
clock = pygame.time.Clock()# 游戏主循环
running = True
while running:# 控制帧率dt = clock.tick(60) / 1000 # 转换为秒# 事件处理for event in pygame.event.get():if event.type == pygame.QUIT:running = False# 获取按键状态keys = pygame.key.get_pressed()if keys[pygame.K_LEFT]:player_x -= player_speedif keys[pygame.K_RIGHT]:player_x += player_speed# 更新动画帧frame_count += animation_speed * dt * 60if frame_count >= 1:current_frame = (current_frame + 1) % len(animation_frames)frame_count = 0# 绘制screen.fill(WHITE)screen.blit(animation_frames[current_frame], (player_x, player_y))# 显示说明文字font = pygame.font.SysFont(None, 36)text = font.render("使用左右方向键移动角色", True, BLACK)screen.blit(text, (50, 50))pygame.display.flip()pygame.quit()
第四章 Pygame精灵系统
4.1 Sprite类简介
Pygame的Sprite
类是为游戏对象设计的基类,提供了以下功能:
- 图像管理
- 位置更新
- 碰撞检测
- 分组管理
4.2 创建自定义精灵
class Player(pygame.sprite.Sprite):def __init__(self, x, y):super().__init__()self.image = pygame.Surface((50, 50))self.image.fill((255, 0, 0)) # 红色方块self.rect = self.image.get_rect()self.rect.x = xself.rect.y = yself.speed = 5def update(self):keys = pygame.key.get_pressed()if keys[pygame.K_LEFT]:self.rect.x -= self.speedif keys[pygame.K_RIGHT]:self.rect.x += self.speedif keys[pygame.K_UP]:self.rect.y -= self.speedif keys[pygame.K_DOWN]:self.rect.y += self.speed
4.3 精灵组的使用
精灵组(Group
)用于管理多个精灵,提供批量更新和绘制功能:
# 创建精灵组
all_sprites = pygame.sprite.Group()
player = Player(100, 100)
all_sprites.add(player)# 在游戏循环中
all_sprites.update() # 更新所有精灵
all_sprites.draw(screen) # 绘制所有精灵
4.4 碰撞检测
Pygame提供了多种碰撞检测方法:
# 矩形碰撞检测
if pygame.sprite.collide_rect(sprite1, sprite2):print("发生碰撞!")# 圆形碰撞检测
if pygame.sprite.collide_circle(sprite1, sprite2):print("圆形碰撞!")# 精灵与组碰撞检测
hits = pygame.sprite.spritecollide(player, enemy_group, True)
for enemy in hits:player.health -= 10
4.5 完整示例:太空射击游戏
import pygame
import random
import ospygame.init()# 屏幕设置
WIDTH = 480
HEIGHT = 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("太空射击游戏")# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)# 加载图像
def load_image(name, scale=1):img = pygame.Surface((50, 40))img.fill(BLUE if name == "player" else RED)return img# 玩家精灵
class Player(pygame.sprite.Sprite):def __init__(self):super().__init__()self.image = load_image("player")self.rect = self.image.get_rect()self.rect.centerx = WIDTH / 2self.rect.bottom = HEIGHT - 10self.speed_x = 0self.health = 100def update(self):self.speed_x = 0keystate = pygame.key.get_pressed()if keystate[pygame.K_LEFT]:self.speed_x = -8if keystate[pygame.K_RIGHT]:self.speed_x = 8self.rect.x += self.speed_x# 边界检查if self.rect.right > WIDTH:self.rect.right = WIDTHif self.rect.left < 0:self.rect.left = 0def shoot(self):bullet = Bullet(self.rect.centerx, self.rect.top)all_sprites.add(bullet)bullets.add(bullet)# 敌人类
class Enemy(pygame.sprite.Sprite):def __init__(self):super().__init__()self.image = load_image("enemy")self.rect = self.image.get_rect()self.rect.x = random.randrange(WIDTH - self.rect.width)self.rect.y = random.randrange(-100, -40)self.speedy = random.randrange(1, 5)self.speedx = random.randrange(-2, 2)def update(self):self.rect.y += self.speedyself.rect.x += self.speedx# 边界检查和重生if self.rect.top > HEIGHT + 10 or self.rect.left < -25 or self.rect.right > WIDTH + 25:self.rect.x = random.randrange(WIDTH - self.rect.width)self.rect.y = random.randrange(-100, -40)self.speedy = random.randrange(1, 5)# 子弹类
class Bullet(pygame.sprite.Sprite):def __init__(self, x, y):super().__init__()self.image = pygame.Surface((10, 20))self.image.fill(GREEN)self.rect = self.image.get_rect()self.rect.centerx = xself.rect.bottom = yself.speedy = -10def update(self):self.rect.y += self.speedy# 如果子弹飞出屏幕顶部,则删除if self.rect.bottom < 0:self.kill()# 创建精灵组
all_sprites = pygame.sprite.Group()
enemies = pygame.sprite.Group()
bullets = pygame.sprite.Group()# 创建玩家
player = Player()
all_sprites.add(player)# 创建敌人
for i in range(8):enemy = Enemy()all_sprites.add(enemy)enemies.add(enemy)# 分数
score = 0
font = pygame.font.SysFont(None, 36)# 游戏循环
clock = pygame.time.Clock()
running = True
while running:# 保持循环以正确的速度运行clock.tick(60)# 处理输入事件for event in pygame.event.get():if event.type == pygame.QUIT:running = Falseelif event.type == pygame.KEYDOWN:if event.key == pygame.K_SPACE:player.shoot()# 更新all_sprites.update()# 检查子弹是否击中敌人hits = pygame.sprite.groupcollide(enemies, bullets, True, True)for hit in hits:score += 10enemy = Enemy()all_sprites.add(enemy)enemies.add(enemy)# 检查敌人是否撞到玩家hits = pygame.sprite.spritecollide(player, enemies, False)if hits:player.health -= 1if player.health <= 0:running = False# 渲染screen.fill(BLACK)all_sprites.draw(screen)# 显示分数score_text = font.render(f"分数: {score}", True, WHITE)screen.blit(score_text, (10, 10))# 显示生命值health_text = font.render(f"生命: {player.health}", True, WHITE)screen.blit(health_text, (10, 50))# 刷新屏幕pygame.display.flip()pygame.quit()
第五章 Pygame声音与音乐
5.1 加载和播放音效
# 加载音效
shoot_sound = pygame.mixer.Sound("shoot.wav")# 播放音效
shoot_sound.play()
5.2 背景音乐控制
# 加载背景音乐
pygame.mixer.music.load("background.mp3")# 播放背景音乐(循环播放)
pygame.mixer.music.play(-1)# 暂停音乐
pygame.mixer.music.pause()# 继续播放
pygame.mixer.music.unpause()# 停止音乐
pygame.mixer.music.stop()
5.3 音量控制
# 设置主音量(0.0到1.0)
pygame.mixer.music.set_volume(0.5)# 设置单个音效音量
shoot_sound.set_volume(0.3)
5.4 完整示例:音乐播放器
import pygame
import ospygame.init()# 屏幕设置
WIDTH = 400
HEIGHT = 300
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("简易音乐播放器")# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (200, 200, 200)# 字体
font = pygame.font.SysFont(None, 24)# 音乐列表
music_files = ["song1.mp3", "song2.mp3", "song3.mp3"]
current_song = 0# 加载第一首歌
pygame.mixer.music.load(music_files[current_song])# 按钮类
class Button:def __init__(self, x, y, width, height, text, color, hover_color):self.rect = pygame.Rect(x, y, width, height)self.text = textself.color = colorself.hover_color = hover_colorself.is_hovered = Falsedef draw(self, surface):color = self.hover_color if self.is_hovered else self.colorpygame.draw.rect(surface, color, self.rect)pygame.draw.rect(surface, BLACK, self.rect, 2)text_surf = font.render(self.text, True, BLACK)text_rect = text_surf.get_rect(center=self.rect.center)surface.blit(text_surf, text_rect)def check_hover(self, pos):self.is_hovered = self.rect.collidepoint(pos)return self.is_hovereddef handle_event(self, event):if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1 and self.is_hovered:return Truereturn False# 创建按钮
play_button = Button(50, 200, 80, 40, "播放", GRAY, WHITE)
pause_button = Button(160, 200, 80, 40, "暂停", GRAY, WHITE)
stop_button = Button(270, 200, 80, 40, "停止", GRAY, WHITE)
next_button = Button(270, 150, 80, 40, "下一首", GRAY, WHITE)
prev_button = Button(50, 150, 80, 40, "上一首", GRAY, WHITE)# 游戏主循环
running = True
clock = pygame.time.Clock()while running:# 事件处理mouse_pos = pygame.mouse.get_pos()for event in pygame.event.get():if event.type == pygame.QUIT:running = False# 检查按钮悬停play_button.check_hover(mouse_pos)pause_button.check_hover(mouse_pos)stop_button.check_hover(mouse_pos)next_button.check_hover(mouse_pos)prev_button.check_hover(mouse_pos)# 处理按钮点击if play_button.handle_event(event):pygame.mixer.music.play()if pause_button.handle_event(event):if pygame.mixer.music.get_busy():pygame.mixer.music.pause()else:pygame.mixer.music.unpause()if stop_button.handle_event(event):pygame.mixer.music.stop()if next_button.handle_event(event):current_song = (current_song + 1) % len(music_files)pygame.mixer.music.load(music_files[current_song])pygame.mixer.music.play()if prev_button.handle_event(event):current_song = (current_song - 1) % len(music_files)pygame.mixer.music.load(music_files[current_song])pygame.mixer.music.play()# 绘制screen.fill(WHITE)# 显示当前歌曲song_text = font.render(f"当前播放: {music_files[current_song]}", True, BLACK)screen.blit(song_text, (20, 50))# 显示播放状态status = "播放中" if pygame.mixer.music.get_busy() else "已停止"status_text = font.render(f"状态: {status}", True, BLACK)screen.blit(status_text, (20, 80))# 绘制按钮play_button.draw(screen)pause_button.draw(screen)stop_button.draw(screen)next_button.draw(screen)prev_button.draw(screen)# 更新显示pygame.display.flip()clock.tick(30)pygame.quit()
第六章 Pygame高级主题
6.1 使用OpenGL加速
Pygame可以通过pygame.OPENGL
标志与OpenGL结合使用:
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *def init():glEnable(GL_DEPTH_TEST)glClearColor(0.5, 0.5, 0.5, 1.0)gluPerspective(45, (800/600), 0.1, 50.0)glTranslatef(0.0, 0.0, -5)def cube():glBegin(GL_QUADS)# 前面glColor3fv((1, 0, 0))glVertex3fv((1, -1, -1))glVertex3fv((1, 1, -1))glVertex3fv((-1, 1, -1))glVertex3fv((-1, -1, -1))# 更多面...glEnd()def main():pygame.init()display = (800, 600)pygame.display.set_mode(display, DOUBLEBUF|OPENGL)init()while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()returnglRotatef(1, 3, 1, 1)glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)cube()pygame.display.flip()pygame.time.wait(10)if __name__ == "__main__":main()
6.2 使用Pygame制作GUI
虽然Pygame不是专门的GUI库,但可以用来创建简单的界面元素:
class Button:def __init__(self, x, y, width, height, text, color, hover_color):self.rect = pygame.Rect(x, y, width, height)self.text = textself.color = colorself.hover_color = hover_colorself.is_hovered = Falsedef draw(self, surface):color = self.hover_color if self.is_hovered else self.colorpygame.draw.rect(surface, color, self.rect)pygame.draw.rect(surface, (0, 0, 0), self.rect, 2)font = pygame.font.SysFont(None, 24)text_surf = font.render(self.text, True, (0, 0, 0))text_rect = text_surf.get_rect(center=self.rect.center)surface.blit(text_surf, text_rect)def check_hover(self, pos):self.is_hovered = self.rect.collidepoint(pos)return self.is_hovereddef handle_event(self, event):if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1 and self.is_hovered:return Truereturn False
6.3 网络游戏开发
Pygame可以与socket
模块结合开发简单的网络游戏:
import socket
import threading
import pygameclass NetworkGame:def __init__(self):pygame.init()self.screen = pygame.display.set_mode((800, 600))self.clock = pygame.time.Clock()self.running = True# 网络设置self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.server_address = ('localhost', 12345)# 连接服务器self.connect_to_server()def connect_to_server(self):try:self.socket.connect(self.server_address)# 启动接收线程receive_thread = threading.Thread(target=self.receive_data)receive_thread.daemon = Truereceive_thread.start()except Exception as e:print(f"连接服务器失败: {e}")def receive_data(self):while self.running:try:data = self.socket.recv(1024).decode()if data:self.handle_network_data(data)except Exception as e:print(f"接收数据错误: {e}")breakdef handle_network_data(self, data):# 处理接收到的网络数据print(f"收到数据: {data}")def send_data(self, data):try:self.socket.sendall(data.encode())except Exception as e:print(f"发送数据失败: {e}")def run(self):while self.running:for event in pygame.event.get():if event.type == pygame.QUIT:self.running = Falseelif event.type == pygame.KEYDOWN:if event.key == pygame.K_SPACE:self.send_data("player_jump")# 游戏逻辑和渲染self.screen.fill((0, 0, 0))pygame.display.flip()self.clock.tick(60)pygame.quit()if __name__ == "__main__":game = NetworkGame()game.run()
第七章 Pygame性能优化
7.1 图像优化技巧
-
使用
convert()
和convert_alpha()
:# 普通图像 image = pygame.image.load("image.png").convert()# 带透明度的图像 image = pygame.image.load("image.png").convert_alpha()
-
避免频繁加载图像:在游戏初始化时加载所有需要的图像
-
使用精灵表:将多个小图像合并到一个大图像中
7.2 游戏循环优化
-
控制帧率:
clock = pygame.time.Clock() while True:clock.tick(60) # 限制为60FPS
-
脏矩形更新:只更新屏幕上发生变化的部分
pygame.display.update(rect_list) # 只更新指定矩形区域
-
分批处理:将相似的绘制操作集中处理
7.3 内存管理
-
及时释放资源:
def unload_resources(self):for image in self.image_cache.values():del imageself.image_cache.clear()
-
使用对象池:对频繁创建销毁的对象进行重用
7.4 性能分析工具
-
Python内置的
cProfile
:python -m cProfile -s cumtime your_game.py
-
Pygame内置的
time
模块:start_time = pygame.time.get_ticks() # 执行代码 end_time = pygame.time.get_ticks() print(f"耗时: {end_time - start_time}毫秒")
第八章 Pygame项目实战:平台游戏
8.1 游戏设计
我们将创建一个简单的平台游戏,包含以下功能:
- 玩家角色可以左右移动和跳跃
- 多个平台供玩家站立
- 收集物品获得分数
- 敌人会移动并伤害玩家
- 简单的关卡设计
8.2 游戏架构
import pygame
import random
import sys# 初始化
pygame.init()
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("平台游戏")
clock = pygame.time.Clock()# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
GRAY = (100, 100, 100)# 玩家类
class Player(pygame.sprite.Sprite):def __init__(self):super().__init__()self.image = pygame.Surface((30, 50))self.image.fill(BLUE)self.rect = self.image.get_rect()self.rect.center = (WIDTH // 2, HEIGHT // 2)self.velocity_y = 0self.velocity_x = 0self.jumping = Falseself.health = 100self.score = 0def update(self):# 重力self.velocity_y += 0.5if self.velocity_y > 10:self.velocity_y = 10# 水平移动self.rect.x += self.velocity_x# 检查水平边界if self.rect.left < 0:self.rect.left = 0if self.rect.right > WIDTH:self.rect.right = WIDTH# 垂直移动self.rect.y += self.velocity_y# 检查是否落地if self.rect.bottom >= HEIGHT - 50:self.rect.bottom = HEIGHT - 50self.velocity_y = 0self.jumping = Falsedef jump(self):if not self.jumping:self.velocity_y = -12self.jumping = True# 平台类
class Platform(pygame.sprite.Sprite):def __init__(self, x, y, width, height):super().__init__()self.image = pygame.Surface((width, height))self.image.fill(GREEN)self.rect = self.image.get_rect()self.rect.x = xself.rect.y = y# 敌人类
class Enemy(pygame.sprite.Sprite):def __init__(self, x, y):super().__init__()self.image = pygame.Surface((30, 30))self.image.fill(RED)self.rect = self.image.get_rect()self.rect.x = xself.rect.y = yself.direction = 1self.speed = 2def update(self):self.rect.x += self.speed * self.direction# 简单的AI:碰到边缘就回头if self.rect.right > WIDTH or self.rect.left < 0:self.direction *= -1# 收集物品类
class Item(pygame.sprite.Sprite):def __init__(self, x, y):super().__init__()self.image = pygame.Surface((20, 20))self.image.fill((255, 255, 0)) # 黄色self.rect = self.image.get_rect()self.rect.center = (x, y)# 创建精灵组
all_sprites = pygame.sprite.Group()
platforms = pygame.sprite.Group()
enemies = pygame.sprite.Group()
items = pygame.sprite.Group()# 创建玩家
player = Player()
all_sprites.add(player)# 创建地面
ground = Platform(0, HEIGHT - 50, WIDTH, 50)
all_sprites.add(ground)
platforms.add(ground)# 创建平台
platform_positions = [(100, 400, 200, 20),(400, 300, 150, 20),(200, 200, 100, 20),(500, 150, 200, 20)
]for pos in platform_positions:p = Platform(*pos)all_sprites.add(p)platforms.add(p)# 创建敌人
enemy_positions = [(200, 350), (450, 250), (300, 150)]
for pos in enemy_positions:e = Enemy(*pos)all_sprites.add(e)enemies.add(e)# 创建收集物品
for i in range(10):x = random.randint(50, WIDTH - 50)y = random.randint(50, HEIGHT - 100)item = Item(x, y)all_sprites.add(item)items.add(item)# 游戏状态
game_over = False
font = pygame.font.SysFont(None, 36)# 游戏主循环
while not game_over:# 事件处理for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()if event.type == pygame.KEYDOWN:if event.key == pygame.K_SPACE:player.jump()# 获取按键状态keys = pygame.key.get_pressed()if keys[pygame.K_LEFT]:player.velocity_x = -5elif keys[pygame.K_RIGHT]:player.velocity_x = 5else:player.velocity_x = 0# 更新all_sprites.update()# 检查玩家是否站在平台上if player.velocity_y > 0: # 正在下落platform_hits = pygame.sprite.spritecollide(player, platforms, False)if platform_hits:player.rect.bottom = platform_hits[0].rect.topplayer.velocity_y = 0player.jumping = False# 检查与敌人的碰撞enemy_hits = pygame.sprite.spritecoll