我写了一个游戏,用于在按下空格键时在屏幕上拍摄蓝色方块。但是,我得到的只是射手正上方的蓝色方块。这是我的代码:
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'
答案 0 :(得分:0)
困扰我一段时间,这是一个经典案例“在我们的鼻子下”:
查看“杂志”下“更新”功能的缩进,它向右缩进了一个,这意味着它是一个函数定义-inside- __init __()而不是你想要的杂志方法。如果这对你来说没有多大意义,那就是“dedent”阻止它看起来像这样
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()
一些解释为什么没有发生但没有错误:由于你的更新功能不是杂志的方法,它没有覆盖从pygame.sprite.Sprite继承的那个。因此,当从主循环调用它时,调用了placehold / basic方法,而不是自定义方法。这意味着你没有得到错误/异常,但它没有用!
接下来,这里也存在一些与纠正有关的重大问题:
不是一个问题,但你可以像在这里一样使用python“for x in y”语法:
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
变为:
for gameObject in gameObjects:
screen.blit(gameObject.image, gameObject.rect)
另请注意,您只需传递整个rect而不是拆分为rect.x和rect.y
一旦你修复了更新功能,你会注意到这一点,当你按下空格键时,你的当前代码会产生多个镜头,这是因为你的生成机制看起来是否持有空格键并在每个循环中产生一个射弹,尝试从中删除此产卵循环,只需在按下或释放空间时执行一次
限制帧速率
在我的测试中,帧率可能会非常高,并使游戏运行奇怪。使用pygame.Clock对象限制帧速率并在循环中调用clock.tick(framerate)
为了准备进一步的复杂性,请考虑将“gameObjects”列表分成几种不同的类型(enemyObjects,projectileObjects等),因为这些可能需要在某些时候进行不同的处理,或者保存您循环整个列表以仅如果发生这种情况会影响敌人。
最后是我的网站的一个小插件,我有一些你可以使用的pygame库的源代码和文档,可能会对你有所帮助。