Python面向对象的pygame大炮游戏。炮弹无法移动

0 投票
3 回答
2037 浏览
提问于 2025-04-17 03:40

我正在做一个软件工程课的作业,正在创建一个面向对象的大炮游戏。我们现在只需要创建一个大炮并发射炮弹。

目前,我的代码可以在大炮的炮口位置创建一个炮弹,但移动功能不幸的是没有让炮弹向上移动(我想先试这个,再开始真正的炮弹弧线发射)。现在,炮弹(我把它设成红色,方便查看是否在炮口位置创建)停在原地,而我看到大炮本身在右下角移动。我很困惑,不知道自己哪里做错了,或者为什么炮弹不能按预期移动。

    import pygame
    from colors import color

class Cannonball(object):
'''
classdocs
'''
    _x = 135
    _y = 310

    def __init__(self):
        '''
        Constructor for cannonball. Initiates x and y at initial values
        of x == 135 and y == 310. at 30 FPS 
        '''
        self._x = Cannonball._x
        self._y = Cannonball._y
        clock = pygame.time.Clock()
        time_passed = clock.tick(30)
        time_passed_seconds = time_passed / 1000.0


    def draw(self, screen):  
        '''
        Draws the cannonball
        '''      
        sprite = pygame.draw.circle(screen, color["red"], (self._x,self._y), 5)
        return sprite

    def move(self, screen, time_passed):
        '''
        initiates the cannonball to move until its past the screen
        '''
        speed = 50
        self._x += speed+time_passed
        self._y -= speed+time_passed    
        pygame.display.flip()

这是我的炮弹类

    import pygame
    import sys
    from cannon import Cannon
    from cannonball import Cannonball
    from colors import color

    pygame.init()
    '''create the GUI window'''
    screen = pygame.display.set_mode((640,480))
    pygame.display.set_caption("Cannon Game")       
    background = screen.fill(color["white"])

    clock = pygame.time.Clock()
    '''draw the Cannon onto the window'''
    aCannon = Cannon
    aCannon.draw(aCannon, screen)
    pygame.display.flip()

    while True: 
        '''handle keydown and quit events for Cannon Game. Space bar
        fires the cannonball
        '''
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
            if event.type == pygame.KEYDOWN:
                 if event.key == pygame.K_SPACE: 
                 aCannonball = aCannon.fire(screen)
                 cannon_ball = True
            if cannon_ball == True:
                 aCannonball.draw(screen)
                 aCannonball.move(screen, time_passed)
                 pygame.display.flip()

这是我的驱动程序。我现在尽量保持简单,因为这帮助我创建了很多东西。

    import pygame
    from colors import color
    from cannonball import Cannonball

    class Cannon (object):
        '''
        classdocs
        '''

    def __init__(self):
            '''
            Constructor
            '''


        def draw(self, screen):
            pygame.draw.circle(screen, color["black"], (40,400), 20)
            pygame.draw.polygon(screen, color["black"], ([30,400], [135, 300], [150,          320], [50,400]), 0)

        def fire (self, screen):   
            print("Fire") //used this as a tester to make sure the fire call worked before attempting to have a cannonball created and move. 
            aCannonball = Cannonball()
            aCannonball.draw(screen)
            aCannonball.move(screen)

最后是我的大炮类,它包含了发射功能,负责创建炮弹、将其绘制到界面上并让它开始移动。

我还在研究自己可能做错了什么,但任何帮助都将非常感激。

编辑:我找到了代码中的问题,导致我的炮弹无法移动。我是把速度乘以经过的时间,而不是加上。这样炮弹几乎在被看到之前就飞出屏幕了。

谢谢你的帮助!也许我可以继续进行弧线发射的部分。

3 个回答

0

我为一个游戏写过类似的类。也许这对你有帮助:

'''
Created on Oct 2, 2011

@author: Mac Spinks
'''
import math
import pygame

class Cannonball(object):

    RADIUS = 4

    def __init__(self, initial_x, initial_y, launch_angle, launch_velocity, time_interval):
        self.x = initial_x
        self.y = initial_y
        self.time_interval = time_interval
        self.angle = launch_angle
        self.x_velocity = launch_velocity*math.cos(self.angle)
        self.y_velocity = launch_velocity*math.sin(self.angle)
        self.is_flying = True
        self.x_delta = self.time_interval * self.x_velocity

    def move(self):

        prev_y_velocity = self.y_velocity
        self.y_velocity = self.y_velocity - (9.8 * self.time_interval)
        self.y = (self.y + (self.time_interval * 
                             ((prev_y_velocity + self.y_velocity)/ 2)))
        self.y = max(self.y, 0)
        self.x += (self.x_delta)
        self.container = pygame.Rect(self.x - self.RADIUS, self.y - self.RADIUS, self.RADIUS*2, self.RADIUS*2)
        self.is_flying = (self.y > 0)
        self.hit_ground = (self.y <= 0)
0

你其实并没有创建一个炮弹(Cannonball)对象,你的aCannonball变量只是指向这个类的一个引用。要真正使用这个类,你需要先创建一个它的实例。等你完成这个步骤后,就可以在方法调用中去掉重复的炮弹引用了。

1

你在这里贴出的框架有几个问题:

  1. 方法和变量没有正确缩进到 CannonBall 类里面,所以它们实际上是全局的,而不是这个类的一部分。

  2. 移动方法不应该有一个 while 循环,试着把你的游戏结构调整成下面的代码那样。

  3. 你在炮弹类里面的 pygame.display 和你主程序里运行的 pygame.display 不是同一个,所以主显示不会更新。要做到你想做的事情,你需要把主程序里的显示传递给炮弹类,以便更新它。

  4. 你需要用 Cannon()CannonBall() 来初始化这些类的构造函数,而不是直接用 CannonCannonBall

游戏框架:

while True: #main loop  
    handle input  
    update spritee 
    draw to screen

并且要把其他循环移出精灵类(在你的例子中是炮弹),因为当这个循环在运行时,你的程序无法接收输入或更新其他精灵。

我建议把移动方法改成(用伪代码写的):

def move(self, screen, time_passed):
    x += speed*time_passed;
    y += speed*time_passed;
    if(x out of screen remove sprite);
    if(y out of screen remove sprite);

撰写回答