如何将猎鸭风格飞机游戏的函数式代码转换为面向对象类结构?
如何将猎鸭风格飞机游戏的函数式代码转换为面向对象类结构?
别担心,把函数式代码转成OOP其实就是把每个飞机的「数据」和「操作数据的行为」打包到一起,后续加新功能(比如飞机血量、爆炸效果)会方便很多。我来一步步帮你改造:
核心思路:把每个飞机做成独立的对象
原来你用字典存每个飞机的x/y/速度/图像,现在我们把这些数据变成Plane类的实例属性,然后把移动、绘制这些操作变成类的方法,让每个飞机自己管理自己的状态。
第一步:定义Plane类
把每个飞机的属性和行为都封装进来:
import pygame import random # 假设你已经定义了这些全局变量(可根据实际情况调整) screen_width = 800 # 替换成你的实际屏幕宽度 plane_vel = 5 # 替换成你的实际飞机速度 plane = pygame.image.load("plane.png") # 你的原始飞机图像 class Plane: # 把飞机的固定参数设为类属性,避免全局变量满天飞 PLANE_LIMIT = 37 PLANE_DECK = 250 HITBOX_OFFSET_X = 5 HITBOX_OFFSET_Y = 2 HITBOX_WIDTH = 103 HITBOX_HEIGHT = 37 def __init__(self, x, y, velocity, image): # 初始化飞机的核心属性 self.x = x self.y = y self.velocity = velocity self.image = image self.width = self.image.get_width() # 提前获取图像宽度,方便判断是否出屏 @classmethod def spawn(cls, screen_width, plane_vel, original_plane): """类方法:随机生成一个飞机实例(替代原来的spawn_plane函数)""" # 随机生成y坐标 plane_y = random.randint(cls.PLANE_LIMIT, cls.PLANE_DECK) # 随机选择飞行方向 direction = random.choice(["left", "right"]) if direction == "right": # 从屏幕左侧外飞入 plane_x = -103 velocity = plane_vel flipped_plane = pygame.transform.flip(original_plane, True, False) else: # 从屏幕右侧外飞入 plane_x = screen_width velocity = -plane_vel flipped_plane = original_plane # 不用翻转,用原始图像 # 返回新创建的飞机实例 return cls(plane_x, plane_y, velocity, flipped_plane) def update(self, screen_width): """更新飞机位置,返回是否还在屏幕内(True=在屏幕里,False=要移除)""" self.x += self.velocity # 判断是否超出屏幕范围 is_on_screen = not (self.x > screen_width or self.x + self.width < 0) return is_on_screen def draw(self, screen): """把飞机和碰撞箱绘制到屏幕上""" # 绘制飞机图像 screen.blit(self.image, (self.x, self.y)) # 绘制碰撞箱 hitbox = ( self.x + self.HITBOX_OFFSET_X, self.y + self.HITBOX_OFFSET_Y, self.HITBOX_WIDTH, self.HITBOX_HEIGHT ) pygame.draw.rect(screen, "green", hitbox, 2)
第二步:改造飞机管理逻辑
原来的current_planes列表现在存Plane实例,update_planes函数也简化成遍历实例、调用各自的方法:
current_planes = [] def update_planes(screen, screen_width): """更新所有飞机状态,移除出屏的飞机,绘制剩余飞机""" global current_planes # 遍历列表的副本,避免删除元素时出错 for plane in current_planes[:]: # 调用飞机的update方法,判断是否还在屏幕内 if not plane.update(screen_width): current_planes.remove(plane) else: # 还在屏幕内就绘制 plane.draw(screen)
第三步:主游戏循环里的调用
和原来的逻辑几乎一致,只是生成飞机的方式变了:
# 初始化pygame的代码(你原来的初始化逻辑不变) pygame.init() screen = pygame.display.set_mode((screen_width, 600)) # 示例高度,替换成你的实际值 clock = pygame.time.Clock() frame_count = 0 running = True while running: # 处理事件(你原来的事件处理逻辑不变) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # 每60帧生成一架飞机 if frame_count % 60 == 0: new_plane = Plane.spawn(screen_width, plane_vel, plane) current_planes.append(new_plane) # 更新并绘制所有飞机 update_planes(screen, screen_width) # 刷新屏幕、控制帧率 pygame.display.update() clock.tick(60) frame_count += 1 pygame.quit()
为什么这样改更好?
- 更清晰:每个飞机的属性(x/y/速度)和行为(移动、绘制)都在同一个类里,不用到处找字典的键
- 易扩展:要给飞机加新功能(比如被击中后爆炸、掉血),直接给
Plane类加explode()或者take_damage()方法就行 - 少全局变量:把飞机的固定参数(比如y范围、碰撞箱尺寸)都放到类属性里,代码更整洁
备注:内容来源于stack exchange,提问作者Fowl
相关产品推荐
相关产品推荐

