Python 如何在pygame中制造一个向上移动的投射物?
我写了一个游戏,当按下空格键时,它会在屏幕上弹出一个蓝色方块。然而,我得到的只是射击手正上方的蓝色正方形。这是我的密码:Python 如何在pygame中制造一个向上移动的投射物?,python,pygame,self,rect,Python,Pygame,Self,Rect,我写了一个游戏,当按下空格键时,它会在屏幕上弹出一个蓝色方块。然而,我得到的只是射击手正上方的蓝色正方形。这是我的密码: import pygame, sys, random from gameobjects import * def main(): pygame.init() screen = pygame.display.set_mode((800, 800)) numberOfColumns = 5 columnWidth = screen.get
import pygame, sys, random
from gameobjects import *
def main():
pygame.init()
screen = pygame.display.set_mode((800, 800))
numberOfColumns = 5
columnWidth = screen.get_width() / numberOfColumns
numberOfRows = 5
rowWidth = screen.get_width() / numberOfRows
magazineImage = pygame.image.load("images/Magazine.bmp")
magazineIssueOneImage = pygame.image.load("images/Magazine #1.bmp")
monsterState1 = pygame.image.load("images/Zombie Pos 1.bmp")
monsterState2 = pygame.image.load("images/Zombie Pos 2.bmp")
monsterState3 = pygame.image.load("images/Zombie Pos 3.bmp")
monsters = []
forryState1 = pygame.image.load("images/Forry Pos 1.bmp")
forryState2 = pygame.image.load("images/Forry Pos 2.bmp")
forryDelayTime = 8
gameObjects = []
gameObjectBlittingCounter = 0
monsterSpawnSpotList = [(rowWidth * -5), (rowWidth * -4), (rowWidth * -3), (rowWidth * -2), (rowWidth * -1)]
for monster in range(0, 5):
monster = Monster(monsterState1, monsterState2, monsterState3, ((columnWidth / 2 - monsterState1.get_width() / 2) + gameObjectBlittingCounter * columnWidth), random.choice(monsterSpawnSpotList))
monsters.append(monster)
gameObjects.append(monster)
gameObjectBlittingCounter += 1
forry = Forry(forryState1, forryState2, columnWidth, rowWidth, screen, forryDelayTime, magazineImage, magazineIssueOneImage)
gameObjects.append(forry)
while True:
screen.fill((0,255,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
#Update Projectiles
if forry.projectileCall == True:
magazine = Magazine(magazineImage, forry)
gameObjects.append(magazine)
#Update Game Objects
for gameObject in gameObjects:
gameObject.update()
#Render
gameObjectBlittingCounter = 0
for gameObject in gameObjects:
screen.blit(gameObjects[gameObjectBlittingCounter].image, ((gameObjects[gameObjectBlittingCounter].rect.x), (gameObjects[gameObjectBlittingCounter].rect.y)))
gameObjectBlittingCounter += 1
pygame.display.flip()
if __name__ == "__main__":
main()
gameobjects.py文件如下所示:
import pygame
class Monster(pygame.sprite.Sprite):
def __init__(self, monsterState1, monsterState2, monsterState3, xCoord, yCoord):
self.monsterState1 = monsterState1
self.monsterState2 = monsterState2
self.monsterState3 = monsterState3
self.image = self.monsterState1
self.rect = self.image.get_rect()
self.rect.y = yCoord
self.rect.x = xCoord
def update(self):
self.moveDown()
def moveDown(self):
self.rect.y += 1
def onSpawn(self):
return
def onDeath(self):
return
def reset(self):
return
class Forry(pygame.sprite.Sprite):
def __init__(self, forryState1, forryState2, columnWidth, rowWidth, screen, delayTime, magazineImage, magazineIssueOneImage):
self.forryState1 = forryState1
self.forryState2 = forryState2
self.image = self.forryState1
self.columnWidth = columnWidth
self.rowWidth = rowWidth
self.rect = self.image.get_rect()
self.rect.y = self.columnWidth / 2 - self.image.get_width() / 2
self.rect.y = screen.get_height() - (self.rowWidth / 2 - self.image.get_height() / 2)
self.delayTime = delayTime
self.delay = 0
self.magazineImage = magazineImage
self.magazineIssueOneImage = magazineIssueOneImage
self.projectileCall = False
self.rightBound = screen.get_width() - (self.columnWidth / 2 + self.image.get_width() / 2)
self.leftBound = (self.columnWidth / 2 - self.image.get_width() / 2)
def update(self):
#Check Player Input
playerInput = self.checkPlayerInput()
#Update Position
if self.delay > 0:
self.delay -= 1
elif self.delay < 0:
self.delay = 0
else:
self.updatePosition(playerInput)
#Keep on the Screen
self.keepOnScreen()
def checkPlayerInput(self):
left = pygame.key.get_pressed() [pygame.K_LEFT]
right = pygame.key.get_pressed() [pygame.K_RIGHT]
shoot = pygame.key.get_pressed() [pygame.K_SPACE]
return (left, right, shoot)
def updatePosition(self, playerInput):
left = playerInput[0]
right = playerInput[1]
shoot = playerInput[2]
if self.projectileCall == True:
self.projectileCall = False
self.image = self.forryState1
if shoot:
self.image = self.forryState2
self.projectileCall = True
self.delay = self.delayTime
if left:
self.rect.x -= self.columnWidth
self.delay = self.delayTime
if right:
self.rect.x += self.columnWidth
self.delay = self.delayTime
def keepOnScreen(self):
if self.rect.x >= self.rightBound:
self.rect.x = self.rightBound
elif self.rect.x <= self.leftBound:
self.rect.x = self.leftBound
def onSpawn(self):
return
def onDeath(self):
return
def reset(self):
return
class Magazine(pygame.sprite.Sprite):
def __init__(self, image, shooter):
self.image = image
self.rect = image.get_rect()
self.rect.x = shooter.rect.x
self.rect.y = shooter.rect.y - shooter.image.get_height()
def update(self):
self.rect.y -= 5
if self.rect.y <= 0 - self.image.get_height():
self.kill()
我的杂志是一本蓝色的正方形
那为什么我的射弹没有出现在屏幕上
++++++++
下面的答案中包含了所有修复,现在我又出现了另一个错误:
当蓝色框离开屏幕时,它应该被杀死,因为杂志类的更新函数中有self.kill
然而,当其中一个离开屏幕时,我看到的不是被杀死,而是以下错误:
Traceback (most recent call last):
File "main.py", line 106, in <module>
main()
File "main.py", line 78, in main
projectileObject.update()
File "/Users/number1son100/Desktop/Famous Monsters Game/gameobjects.py", line 117, in update
self.kill()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pygame/sprite.py", line 174, in kill
for c in self.__g.keys():
AttributeError: 'Magazine' object has no attribute '_Sprite__g'
答复
有一阵子难住了我,这是我们眼皮底下的一个典型案例:
看一下Magazine下更新函数的缩进,它向右缩进了一个太远的位置,这意味着它是一个定义为-inside-\uuuu init\uuuu的函数,而不是您想要的Magazine方法。如果这对你来说没有多大意义,就去掉那个块,让它看起来像这样
class Magazine(pygame.sprite.Sprite):
def __init__(self, image, shooter):
self.image = image
self.rect = image.get_rect()
self.rect.x = shooter.rect.x
self.rect.y = shooter.rect.y - shooter.image.get_height()
def update(self):
self.rect.y -= 5
if self.rect.y <= 0 - self.image.get_height():
self.kill()
稍后在“渲染”部分中,即:
#Render
gameObjectBlittingCounter = 0
for gameObject in gameObjects:
screen.blit(gameObjects[gameObjectBlittingCounter].image, ((gameObjects[gameObjectBlittingCounter].rect.x), (gameObjects[gameObjectBlittingCounter].rect.y)))
gameObjectBlittingCounter += 1
变成:
for gameObject in gameObjects:
screen.blit(gameObject.image, gameObject.rect)
另外请注意,您可以只传递整个rect,而不是将其拆分为rect.x和rect.y
2.
一旦你修复了更新功能,你就会注意到这一点,当你按下空格键时,你当前的代码会生成多个快照,这是因为你的生成机制会检查空格键是否被按住并在每个循环中生成一个投射物,试着从循环中删除这个生成物,在按下或释放空格时只执行一次
3.
限制帧率
在我的测试中,帧率可能会非常高,使游戏运行异常。使用pygame.Clock对象并在循环中调用Clock.tickframerate来限制帧速率
4.
<> P>为进一步的复杂性做准备,考虑把你的游戏对象列表分割成几个不同类型的敌人对象,投射物体等,因为这些可能需要在某个时候进行不同的处理,或者保存你在整个列表中循环,如果发生的话只影响敌人。
最后是我的网站的一个小插件,我有一些pygame库的源代码和文档,您可以使用,将来可能会对您有所帮助。非常感谢!这件事困扰了我好几个星期。我还有一个问题要问。我会把它写在我的帖子底部。很高兴我能帮上忙。这个问题可能是因为您没有调用继承的pygame.sprite.sprite类的_init_u方法,因此没有初始化_sprite_ug属性。如果您不知道类继承的含义,请查看类继承是如何工作的:将这个:pygame.sprite.sprite.\uuuu init\uu self添加到类的u init\uu方法中,希望这能解决您的问题
for gameObject in gameObjects:
screen.blit(gameObject.image, gameObject.rect)