我正在pygame中开发一款游戏,我已经在屏幕上画了基本的图形,但用户输入让我很困惑。我有一个玩家类:
class Player(pygame.sprite.Sprite):
def __init__(self):
super(Player, self).__init__()
self.surf = pygame.Surface((75, 25))
self.surf.fill((255, 255, 255))
self.rect = self.surf.get_rect()
def update(self, pressed_keys):
if pressed_keys[K_UP]:
self.rect.move_ip(0, -5)
if pressed_keys[K_DOWN]:
self.rect.move_ip(0, 5)
if pressed_keys[K_LEFT]:
self.rect.move_ip(-5, 0)
if pressed_keys[K_RIGHT]:
self.rect.move_ip(5, 0)
pygame.event.pump()
但每当我按下键时,什么都不会发生。这是剧本的结尾,画出了东西:
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
pressed_keys = pygame.key.get_pressed()
player.update(pressed_keys)
screen.fill((0, 0, 0))
surf = pygame.Surface((50, 50))
surf.fill((0, 0, 0))
rect = surf.get_rect()
screen.blit(player.surf, (SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
pygame.display.flip()
我不知道发生了什么,但我找不到任何东西来解决它。一切都很顺利,但没有其他事情。
问题:在屏幕上进行闪电扫描时的逻辑错误
在你的游戏循环中:
player.update
通过按键移动播放器blit
正在绘制玩家始终固定在中心(SCREEN_WIDTH/2, SCREEN_HEIGHT/2)
-,尽管玩家的位置发生了移动
因此,尽管您移动了它,并且它的位置(在rect
中(被箭头键更改,但您的玩家在视觉上仍会将固定在屏幕中央。
调试
添加一些调试print
语句
- 在
blit
之前监视更新后玩家位置是否移动: - 在
blit
之后监视其作为绘制矩形的返回值
print("player's rect after update:", player.rect)
drawn_rect = screen.blit(player.surf, (SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
print("rect drawn by blit:", drawn_rect)
研究
假设您使用blit
的意图是:
- 初始绘制时将播放器置于屏幕中央
- 使用
blit
在屏幕上绘制播放器
让我们咨询PyGame文档以获得一些支持。
使Surface
对象居中
阅读关于如何使用get_rect()
:居中的Surface
文档
您可以将关键字参数值传递给此函数。在返回Rect之前,这些命名值将应用于Rect的属性。一个例子是
mysurf.get_rect(center=(100, 100))
,它为位于给定位置中心的曲面创建一个矩形。
使用blit
来自blit(source, dest, area=None, special_flags=0)
上的文档
在此曲面上绘制
source
曲面。绘图可以使用dest
参数进行定位。dest
自变量可以是表示blit左上角位置的坐标对,也可以是Rect
设计修复
在创建过程中,在初始位置生成玩家,例如centered
(在屏幕上(。
然后,您的游戏循环对draw
负有单一责任,即screen
上的player
。
玩家:居中、移动、绘制
class Player(pygame.sprite.Sprite):
def __init__(self):
super(Player, self).__init__()
self.surf = pygame.Surface((75, 25))
self.surf.fill((255, 255, 255))
self.rect = self.centered() # spawn it centerd
def update(self, pressed_keys):
if pressed_keys[K_UP]:
self.move(0, -5)
if pressed_keys[K_DOWN]:
self.move(0, 5)
if pressed_keys[K_LEFT]:
self.move(-5, 0)
if pressed_keys[K_RIGHT]:
self.move(5, 0)
pygame.event.pump()
## added some methods
def centered():
return self.surf.get_rect(center=(SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
def move(x, y):
self.rect.move_ip(x,y)
def draw_on(surface): # visitor-pattern
surface.blit(self.surf, self.rect)
注:为Player
添加了一些功能
centered
定位在恒定屏幕尺寸内的中心move
用矢量(x,y(移动玩家draw_on
在给定的表面上绘制玩家的精灵/表面,如screen
绘制
然后在你的游戏循环内替换:
screen.blit(player.surf, (SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
通过新命令:
# new player is centered, moved player is located anywhere
player.draw_on(screen)
注意:_visitor-pattern将语句更改为<subject>.<verb>(<object>)
形式的可读语句,并且比以前少了一个自变量(内部化(。
奖金:建议
可以改进面向对象的设计,以增强可读性、简化测试和简化使用:
- 通过命令等功能控制玩家
- 选择一种简单的游戏语言(领域术语(
- 并使用它来命名抽象(对象、函数、变量(
示例:Player
、screen
、move
、centered
、draw
、_to
、_on
(名词、形容词或动词相似,用介词表示关系(
通常,设计改进可以更容易地识别逻辑错误或在调试期间分析控制流——希望如此。
您必须将玩家blit
存储在rect
属性中的位置:
screen.blit(player.surf, (SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
screen.blit(player.surf, player.rect)