You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将猎鸭风格飞机游戏的函数式代码转换为面向对象类结构?

如何将猎鸭风格飞机游戏的函数式代码转换为面向对象类结构?

别担心,把函数式代码转成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()

为什么这样改更好?

  1. 更清晰:每个飞机的属性(x/y/速度)和行为(移动、绘制)都在同一个类里,不用到处找字典的键
  2. 易扩展:要给飞机加新功能(比如被击中后爆炸、掉血),直接给Plane类加explode()或者take_damage()方法就行
  3. 少全局变量:把飞机的固定参数(比如y范围、碰撞箱尺寸)都放到类属性里,代码更整洁

备注:内容来源于stack exchange,提问作者Fowl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 15:57:57