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)