python - 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()
解决方案
问题是实例方法
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()
推荐阅读
- c++ - C++:+ 或 - 可以告诉编译器一个值应该是一个 int 吗?
- java - JDA 获取所有渠道
- amazon-web-services - 在 terraform 的嵌套模块中引用变量
- prometheus - 备份和恢复 prometheus 指标
- c# - 从 FileStream 读取 JSON
- excel - 如何快速复制和粘贴/拖动公式到多行和多列
- spring - 春天 i18N 视频
- oracle - Oracle PL/SQL 似乎忽略了我的函数的 WHERE 子句
- ruby-on-rails - 在 Ruby on rails 中注释掉一个 '=begin'
- gridview - 如何在 DevExpress GridView 中获取新行的值?