首页 > 解决方案 > Python Pygame 直接在 Class 中使用 command 或调用 def 会导致不同的效果,为什么?

问题描述

现在在某人的帮助下,我可以在 Pygame 中按键射击子弹,但我遇到了另一个新问题。我在类 Bullet 中定义它:

def move(self):
    self.y -= self.speed
    self.bullet.y=self.y
def draw(self,setting):
    p.draw.rect(setting.screen,self.color,self.bullet)
def bullet_blit(self,bullets,setting):
    for bullet in bullets.sprites():
        p.draw.rect(setting.screen,self.color,self.bullet)
        self.y -= self.speed
        self.bullet.y=self.y

最后,当我只使用代码bullet.bullet_blit(bullets,setting)时,当我按下键时它只会一个子弹。相反,我使用

for bullet in bullets.sprites():
    bullet.draw(setting)
    bullet.move()

它工作正常。我不知道为什么。它们是一样的,但它们的作用是不一样的。这是代码:

#! /usr/bin/python
import pygame as p
import sys

class Setting():
    def __init__(self,width,height):
        self.w=width
        self.h=height
        self.flag=p.RESIZABLE
        self.color=(255,255,255)
        self.speed=1
        self.screen=p.display.set_mode((self.w,self.h),self.flag)
        p.display.set_caption("Bullet")
        self.bullet_s=1
        self.bullet_w=5
        self.bullet_h=30
        self.bullet_c=(0,0,0)

class Bullet(p.sprite.Sprite):
    def __init__(self,setting):
        super().__init__()
        self.screen_rect=setting.screen.get_rect()
        self.screen_center=self.screen_rect.center
        self.bullet=p.Rect((0,0),(setting.bullet_w,setting.bullet_h))
        self.bullet.center=self.screen_center
        self.bullet.bottom=self.screen_rect.bottom
        self.color=setting.bullet_c
        self.speed=setting.bullet_s
        self.y=float(self.bullet.centery)
    def bullet_check(self,bullets,setting):
        for event in p.event.get():
            if event.type == p.QUIT:
                sys.exit()
            elif event.type == p.KEYDOWN:
                if event.key ==p.K_SPACE:
                    bullets.add(Bullet(setting))
    def move(self):
        self.y -= self.speed
        self.bullet.y=self.y
    def draw(self,setting):
        p.draw.rect(setting.screen,self.color,self.bullet)
    def bullet_blit(self,bullets,setting):
        for bullet in bullets.sprites():
            p.draw.rect(setting.screen,self.color,self.bullet)
            self.y -= self.speed
            self.bullet.y=self.y



def game():
    p.init()
    setting=Setting(1200,800)
    bullet=Bullet(setting)
    bullets=p.sprite.Group()                

    while True:
        bullet.bullet_check(bullets,setting)
        setting.screen.fill((255,0,0))
        bullet.bullet_blit(bullets,setting)      <—--this cant create many bullets,only one bullet
#        for bullet in bullets.sprites():
#            bullet.draw(setting)
#            bullet.move()
        p.display.flip()
game()

标签: pythonpygame

解决方案


问题是实例方法

class Bullet(p.sprite.Sprite):

   # [...]
   def bullet_blit(self,bullets,setting):
       for bullet in bullets.sprites():
           p.draw.rect(setting.screen,self.color,self.bullet)
           self.y -= self.speed
           self.bullet.y=self.y

您想遍历所有项目符号并移动blit每个项目符号,但您只使用实例 ( self) 的属性而不是列表中的对象bullet

转向bullet_blit类方法:

class Bullet(p.sprite.Sprite):   

    def bullet_blit(bullets,setting):
        for bullet in bullets.sprites():
            p.draw.rect(setting.screen,bullet.color,bullet.bullet)
            bullet.y -= bullet.speed
            bullet.bullet.y=bullet.y

并称之为:

while True:

    # [...]

    Bullet.bullet_blit(bullets,setting) 

pygame.event.get()获取所有消息并将它们从队列中删除。所以这个函数应该在主应用程序循环中每帧调用一次。

转到bullet_check类方法并将事件列表传递给该方法:

class Bullet(p.sprite.Sprite):

    # [...]

   def bullet_check(events, bullets, setting):
        for event in events:
            if event.type == p.KEYDOWN:
                if event.key ==p.K_SPACE:
                    bullets.add(Bullet(setting))

获取主应用程序循环中的事件并将其传递给函数:

def game():
    p.init()
    setting=Setting(1200,800)
    bullets=p.sprite.Group()                

    while True:
        events = p.event.get()
        for event in events:
            if event.type == p.QUIT:
                sys.exit()

        Bullet.bullet_check(events, bullets, setting)
        setting.screen.fill((255,0,0))
        Bullet.bullet_blit(bullets,setting)
        p.display.flip()

另一种选择是创建一个BulletsGroup类,派生自pygame.sprite.Group

import pygame as p
import sys

class Setting():
    def __init__(self,width,height):
        self.w=width
        self.h=height
        self.flag=p.RESIZABLE
        self.color=(255,255,255)
        self.speed=1
        self.screen=p.display.set_mode((self.w,self.h),self.flag)
        p.display.set_caption("Bullet")
        self.bullet_s=1
        self.bullet_w=5
        self.bullet_h=30
        self.bullet_c=(0,0,0)

class BulletsGroup(p.sprite.Group):
    def __init__(self):
        super().__init__()
    def move_bullets(self):
        for bullet in self:
            bullet.move()
    def draw_bullets(self, setting):
        for bullet in self:
            bullet.draw(setting) 
    def bullet_check(self, events, setting):
        for event in events:
            if event.type == p.KEYDOWN:
                if event.key ==p.K_SPACE:
                    self.add(Bullet(setting))

class Bullet(p.sprite.Sprite):
    def __init__(self,setting):
        super().__init__()
        self.screen_rect=setting.screen.get_rect()
        self.screen_center=self.screen_rect.center
        self.bullet=p.Rect((0,0),(setting.bullet_w,setting.bullet_h))
        self.bullet.center=self.screen_center
        self.bullet.bottom=self.screen_rect.bottom
        self.color=setting.bullet_c
        self.speed=setting.bullet_s
        self.y=float(self.bullet.centery)
    def move(self):
        self.y -= self.speed
        self.bullet.y=self.y
    def draw(self, setting):
        p.draw.rect(setting.screen,self.color,self.bullet)

def game():
    p.init()
    setting = Setting(1200,800)
    bullets = BulletsGroup()                

    while True:
        events = p.event.get()
        for event in events:
            if event.type == p.QUIT:
                sys.exit()

        bullets.bullet_check(events, setting)
        bullets.move_bullets()

        setting.screen.fill((255,0,0))
        bullets.draw_bullets(setting)
        p.display.flip()
game()

推荐阅读