Python面向对象的pygame大炮游戏。炮弹无法移动
我正在做一个软件工程课的作业,正在创建一个面向对象的大炮游戏。我们现在只需要创建一个大炮并发射炮弹。
目前,我的代码可以在大炮的炮口位置创建一个炮弹,但移动功能不幸的是没有让炮弹向上移动(我想先试这个,再开始真正的炮弹弧线发射)。现在,炮弹(我把它设成红色,方便查看是否在炮口位置创建)停在原地,而我看到大炮本身在右下角移动。我很困惑,不知道自己哪里做错了,或者为什么炮弹不能按预期移动。
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 个回答
我为一个游戏写过类似的类。也许这对你有帮助:
'''
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)
你其实并没有创建一个炮弹(Cannonball)对象,你的aCannonball变量只是指向这个类的一个引用。要真正使用这个类,你需要先创建一个它的实例。等你完成这个步骤后,就可以在方法调用中去掉重复的炮弹引用了。
你在这里贴出的框架有几个问题:
方法和变量没有正确缩进到
CannonBall
类里面,所以它们实际上是全局的,而不是这个类的一部分。移动方法不应该有一个 while 循环,试着把你的游戏结构调整成下面的代码那样。
你在炮弹类里面的
pygame.display
和你主程序里运行的pygame.display
不是同一个,所以主显示不会更新。要做到你想做的事情,你需要把主程序里的显示传递给炮弹类,以便更新它。你需要用
Cannon()
和CannonBall()
来初始化这些类的构造函数,而不是直接用Cannon
和CannonBall
。
游戏框架:
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);