如何使用 Python 的 Pygame 库更改 class 中的参数值
How to change the value of parameters in a class using Python's Pygame library
我正在尝试编写一个 space 类入侵者游戏。我最初编写我的代码只提供 1 个入侵者给我一些东西来构建。当我开始添加更多入侵者时,我决定创建一个 class,我可以在其中循环入侵者列表。
我试图在我的列表中的一个方法中更改入侵者的 x 坐标,但我发现它没有改变值,因此入侵者留在原地。任何帮助将不胜感激!
这是我正在处理的 class:
import sys, pygame, random
from pygame.locals import *
import itertools
#from bullet import Invader
pygame.init()
screen_height = 600
screen_width = 1200
DISPLAYSURF = pygame.display.set_mode((screen_width, screen_height))
FPS = 200
score = 0
pygame.display.set_caption('Testing Pygame')
spaceship = pygame.image.load('spaceship copy.bmp')
spaceship_rect = spaceship.get_rect()
DISPLAYSURF_rect = DISPLAYSURF.get_rect()
FONT = pygame.font.Font('freesansbold.ttf', 32)
text = FONT.render('Score ' + str(score), True, (180, 180, 180))
text_rect = text.get_rect()
text_rect.centerx = DISPLAYSURF_rect.centerx
text_rect.centery = DISPLAYSURF_rect.centery
invader_right_movement = False
invader_left_movement = True
class Invader():
def __init__(self, invader, invader_x, invader_y):
self.invader = invader
self.rect = invader.get_rect()
self.rect.x = invader_x
self.rect.y = invader_y
def move_invader(self, movement):
#self.x = self.rect.x
#self.y = self.rect.y
#Move invader
if invader_right_movement == True:
self.rect.x += movement
if invader_left_movement == True:
self.rect.x -= movement
DISPLAYSURF.blit(self.invader, (self.rect.x, self.rect.y))
invaders_x = [10, 90, 170, 250, 330, 410, 490, 570, 650, 730]
invaders_y = 40
invader_image = pygame.image.load('invader.bmp')
invaders = []
for x in invaders_x:
invaders.append(Invader(invader_image,x,invaders_y))
invaders_rect = []
for invader, x in zip(invaders, invaders_x):
invader.centerx = x
invader.centery = invaders_y
spaceship_rect.centerx = DISPLAYSURF_rect.centerx
spaceship_rect.centery = DISPLAYSURF_rect.bottom - 40
move_right = False
move_left = False
move_rate = 5
bullet_firing = False
#Testing bullet firing
RED = (240, 0, 0)
x = spaceship_rect.centerx - 3
y = spaceship_rect.top
width = 6
height = 24
#bullet = pygame.draw.rect(DISPLAYSURF, RED, (x, y, width, height))
#bullet.centerx = spaceship_rect.centerx - 3
#bullet.centery = spaceship_rect.top + height
#bullet_rect = pygame.draw.rect(DISPLAYSURF, RED, (x, y, width, height))
bullets_fired = []
bullet_fired = False
while True:
DISPLAYSURF.fill((0, 0, 0))
DISPLAYSURF.blit(spaceship, spaceship_rect)
DISPLAYSURF.blit(text, text_rect)
#get invader to move 1-8 pixels randomly to one side before turning back
num_movements = random.randint(1, 8)
for invader in invaders:
invader.move_invader(num_movements)
for invader in invaders:
if invader.rect.centerx >= screen_width - 30:
invader_left_movement = True
invader_right_movement = False
if invader.rect.centerx <= 0 + 30:
invader_left_movement = False
invader_right_movement = True
FPSCLOCK = pygame.time.Clock()
#movement of bullet
for bullet in range(len(bullets_fired)-1,-1,-1):
for invader in invaders:
if invader.rect.colliderect(bullets_fired[bullet]):
score += 1
invader_x = DISPLAYSURF_rect.centerx
invader_x = DISPLAYSURF_rect.top + 40
del bullets_fired[bullet]
bullet_fired = False
elif bullets_fired[bullet].y > 0:
bullet_fired = True
bullets_fired[bullet].y -= 14
pygame.draw.rect(DISPLAYSURF,RED,bullets_fired[bullet])
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
#Movement of player
if event.key == K_RIGHT:
move_right = True
elif event.key == K_LEFT:
move_left = True
#Bullet firing
elif event.key == K_SPACE:
if bullet_fired == False:
rect = spaceship_rect
rect.x = spaceship_rect.centerx - 3
rect.y = spaceship_rect.top
bullets_fired.append(rect)
elif event.type == KEYUP:
#Movement of player
if event.key == K_RIGHT:
move_right = False
elif event.key == K_LEFT:
move_left = False
text = FONT.render('Score ' + str(score), True, (180, 180, 180))
if move_right == True and spaceship_rect.right <= screen_width:
spaceship_rect.centerx += move_rate
if move_left == True and spaceship_rect.left >= 0:
spaceship_rect.centerx -= move_rate
pygame.display.update()
FPSCLOCK.tick(FPS)
问题是您在每一帧调用 class,这会将其值返回到 __init__
中指定的值。您应该在开始时调用 class 一次,然后每帧调用这些方法。这是 Link 以了解有关 classes 的更多信息。
要修复您的代码,请执行以下操作:
while True:
#do other stuff
for invader in invaders:
invader.move_invader()
#do other stuff
并且由于所有入侵者都具有相同的图像,因此您可以
invader_image = pygame.image.load('invader.bmp')
invaders = []
for x in invader_x:
invaders.append(Invader(invader_image,x,40,1))
这应该每帧将每个入侵者移动 1 个像素
要获得碰撞的矩形,您可以将矩形添加到 class
class Invader
def __init__(self, invader, invader_x, invader_y, movement):
self.rect = invader.get_rect()
self.rect.x = invader_x
self.rect.y = invader_y
#rest of code
def move_invader(self):
#if moveing move x
self.rect.x = x
#rest of code
和碰撞
for bullet in range(len(bullets_fired)-1,-1,-1):
for invader in invaders:
if invader.rect.colliderect(bullets_fired[bullet]):
score += 1
invader_x = DISPLAYSURF_rect.centerx
invader_x = DISPLAYSURF_rect.top + 40
del bullets_fired[bullet]
invaders.remove(invader) #to get rid of the invader too
bullet_fired = False
break
elif bullets_fired[bullet].y > 0:
bullet_fired = True
bullets_fired[bullet].y -= 14
bullet_rect = pygame.draw.rect(DISPLAYSURF, RED, (x, y, width, height))
对于碰撞,我向后循环,因为如果您删除列表中的第二个项目符号,则第三个项目符号将变为第二个项目符号,并且循环转到第三个项目符号(这是第四个项目符号)跳过项目符号。但是如果你往回走,如果你删除了一颗子弹,你已经检查过的子弹就会移动,你可以继续检查下一颗。
对于子弹,你有子弹和 bullet_rect 是同一件事,你有一个子弹列表,就个人而言,我会去掉 bullet_rect
bullet = pygame.draw.rect(screen,RED,(x,y,w,y))
对于
pygame.draw.rect(screen,RED,bullets_fired[bullet]
现在对于你添加项目符号的地方,当你按下空格键时,不是得到 y,而是得到 rect
elif event.key == K_SPACE:
if bullet_fired == False:
rect = spaceship_rect.copy() # this makes the bullet the same size as the ship
#you could also do rect = pygame.rect(0,0,0,0)
rect.x = spaceship_rect.centerx - 3
rect.y = spaceship_rect.top
#rect.w = width
#rect.h = height
bullets_fired.append(rect)
然后回到碰撞循环,将 y 更改为 bullets_fired[bullet].y
我正在尝试编写一个 space 类入侵者游戏。我最初编写我的代码只提供 1 个入侵者给我一些东西来构建。当我开始添加更多入侵者时,我决定创建一个 class,我可以在其中循环入侵者列表。
我试图在我的列表中的一个方法中更改入侵者的 x 坐标,但我发现它没有改变值,因此入侵者留在原地。任何帮助将不胜感激!
这是我正在处理的 class:
import sys, pygame, random
from pygame.locals import *
import itertools
#from bullet import Invader
pygame.init()
screen_height = 600
screen_width = 1200
DISPLAYSURF = pygame.display.set_mode((screen_width, screen_height))
FPS = 200
score = 0
pygame.display.set_caption('Testing Pygame')
spaceship = pygame.image.load('spaceship copy.bmp')
spaceship_rect = spaceship.get_rect()
DISPLAYSURF_rect = DISPLAYSURF.get_rect()
FONT = pygame.font.Font('freesansbold.ttf', 32)
text = FONT.render('Score ' + str(score), True, (180, 180, 180))
text_rect = text.get_rect()
text_rect.centerx = DISPLAYSURF_rect.centerx
text_rect.centery = DISPLAYSURF_rect.centery
invader_right_movement = False
invader_left_movement = True
class Invader():
def __init__(self, invader, invader_x, invader_y):
self.invader = invader
self.rect = invader.get_rect()
self.rect.x = invader_x
self.rect.y = invader_y
def move_invader(self, movement):
#self.x = self.rect.x
#self.y = self.rect.y
#Move invader
if invader_right_movement == True:
self.rect.x += movement
if invader_left_movement == True:
self.rect.x -= movement
DISPLAYSURF.blit(self.invader, (self.rect.x, self.rect.y))
invaders_x = [10, 90, 170, 250, 330, 410, 490, 570, 650, 730]
invaders_y = 40
invader_image = pygame.image.load('invader.bmp')
invaders = []
for x in invaders_x:
invaders.append(Invader(invader_image,x,invaders_y))
invaders_rect = []
for invader, x in zip(invaders, invaders_x):
invader.centerx = x
invader.centery = invaders_y
spaceship_rect.centerx = DISPLAYSURF_rect.centerx
spaceship_rect.centery = DISPLAYSURF_rect.bottom - 40
move_right = False
move_left = False
move_rate = 5
bullet_firing = False
#Testing bullet firing
RED = (240, 0, 0)
x = spaceship_rect.centerx - 3
y = spaceship_rect.top
width = 6
height = 24
#bullet = pygame.draw.rect(DISPLAYSURF, RED, (x, y, width, height))
#bullet.centerx = spaceship_rect.centerx - 3
#bullet.centery = spaceship_rect.top + height
#bullet_rect = pygame.draw.rect(DISPLAYSURF, RED, (x, y, width, height))
bullets_fired = []
bullet_fired = False
while True:
DISPLAYSURF.fill((0, 0, 0))
DISPLAYSURF.blit(spaceship, spaceship_rect)
DISPLAYSURF.blit(text, text_rect)
#get invader to move 1-8 pixels randomly to one side before turning back
num_movements = random.randint(1, 8)
for invader in invaders:
invader.move_invader(num_movements)
for invader in invaders:
if invader.rect.centerx >= screen_width - 30:
invader_left_movement = True
invader_right_movement = False
if invader.rect.centerx <= 0 + 30:
invader_left_movement = False
invader_right_movement = True
FPSCLOCK = pygame.time.Clock()
#movement of bullet
for bullet in range(len(bullets_fired)-1,-1,-1):
for invader in invaders:
if invader.rect.colliderect(bullets_fired[bullet]):
score += 1
invader_x = DISPLAYSURF_rect.centerx
invader_x = DISPLAYSURF_rect.top + 40
del bullets_fired[bullet]
bullet_fired = False
elif bullets_fired[bullet].y > 0:
bullet_fired = True
bullets_fired[bullet].y -= 14
pygame.draw.rect(DISPLAYSURF,RED,bullets_fired[bullet])
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
#Movement of player
if event.key == K_RIGHT:
move_right = True
elif event.key == K_LEFT:
move_left = True
#Bullet firing
elif event.key == K_SPACE:
if bullet_fired == False:
rect = spaceship_rect
rect.x = spaceship_rect.centerx - 3
rect.y = spaceship_rect.top
bullets_fired.append(rect)
elif event.type == KEYUP:
#Movement of player
if event.key == K_RIGHT:
move_right = False
elif event.key == K_LEFT:
move_left = False
text = FONT.render('Score ' + str(score), True, (180, 180, 180))
if move_right == True and spaceship_rect.right <= screen_width:
spaceship_rect.centerx += move_rate
if move_left == True and spaceship_rect.left >= 0:
spaceship_rect.centerx -= move_rate
pygame.display.update()
FPSCLOCK.tick(FPS)
问题是您在每一帧调用 class,这会将其值返回到 __init__
中指定的值。您应该在开始时调用 class 一次,然后每帧调用这些方法。这是 Link 以了解有关 classes 的更多信息。
要修复您的代码,请执行以下操作:
while True:
#do other stuff
for invader in invaders:
invader.move_invader()
#do other stuff
并且由于所有入侵者都具有相同的图像,因此您可以
invader_image = pygame.image.load('invader.bmp')
invaders = []
for x in invader_x:
invaders.append(Invader(invader_image,x,40,1))
这应该每帧将每个入侵者移动 1 个像素
要获得碰撞的矩形,您可以将矩形添加到 class
class Invader
def __init__(self, invader, invader_x, invader_y, movement):
self.rect = invader.get_rect()
self.rect.x = invader_x
self.rect.y = invader_y
#rest of code
def move_invader(self):
#if moveing move x
self.rect.x = x
#rest of code
和碰撞
for bullet in range(len(bullets_fired)-1,-1,-1):
for invader in invaders:
if invader.rect.colliderect(bullets_fired[bullet]):
score += 1
invader_x = DISPLAYSURF_rect.centerx
invader_x = DISPLAYSURF_rect.top + 40
del bullets_fired[bullet]
invaders.remove(invader) #to get rid of the invader too
bullet_fired = False
break
elif bullets_fired[bullet].y > 0:
bullet_fired = True
bullets_fired[bullet].y -= 14
bullet_rect = pygame.draw.rect(DISPLAYSURF, RED, (x, y, width, height))
对于碰撞,我向后循环,因为如果您删除列表中的第二个项目符号,则第三个项目符号将变为第二个项目符号,并且循环转到第三个项目符号(这是第四个项目符号)跳过项目符号。但是如果你往回走,如果你删除了一颗子弹,你已经检查过的子弹就会移动,你可以继续检查下一颗。
对于子弹,你有子弹和 bullet_rect 是同一件事,你有一个子弹列表,就个人而言,我会去掉 bullet_rect
bullet = pygame.draw.rect(screen,RED,(x,y,w,y))
对于
pygame.draw.rect(screen,RED,bullets_fired[bullet]
现在对于你添加项目符号的地方,当你按下空格键时,不是得到 y,而是得到 rect
elif event.key == K_SPACE:
if bullet_fired == False:
rect = spaceship_rect.copy() # this makes the bullet the same size as the ship
#you could also do rect = pygame.rect(0,0,0,0)
rect.x = spaceship_rect.centerx - 3
rect.y = spaceship_rect.top
#rect.w = width
#rect.h = height
bullets_fired.append(rect)
然后回到碰撞循环,将 y 更改为 bullets_fired[bullet].y