在 pygame 教程中使用重力时播放器不会停在屏幕底部边缘
Player does not stop at bottom edge of screen when using gravity in pygame tutorial
我正在尝试按照本教程进行操作 https://opensource.com/article/19/11/simulate-gravity-python 以允许我的 sprite 到达屏幕的底部边缘,仅此而已。但是按照教程代码到它说的地步:
...让你的重力函数看起来像这样:
def gravity(self):
self.movey += 3.2 # how fast player falls
if self.rect.y > worldy and self.movey >= 0:
self.movey = 0
self.rect.y = worldy-ty
即使玩家在使用重力时不会停在屏幕的底部边缘。
我尝试按照教程中的建议再添加一个 ty
... 一个简单的解决方法是在玩家精灵到达游戏世界的底部后,通过在其新的 Y 位置添加另一个 -ty 来使它反弹得更高:
def gravity(self):
self.movey += 3.2 # how fast player falls
if self.rect.y > worldy and self.movey >= 0:
self.movey = 0
self.rect.y = worldy-ty-ty
所以我的代码看起来像这样:
import pygame
import sys
import os
'''
Objects
'''
class Enemy(pygame.sprite.Sprite):
'''
Spawn an enemy
'''
def __init__(self, x, y, img):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(os.path.join('images', img))
#self.image.convert_alpha()
#self.image.set_colorkey(ALPHA)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.counter = 0
def move(self):
'''
enemy movement
'''
distance = 20
speed = 8
if self.counter >= 0 and self.counter <= distance:
self.rect.x += speed
elif self.counter >= distance and self.counter <= distance * 2:
self.rect.x -= speed
else:
self.counter = 0
self.counter += 1
class Level:
def __init__(self):
self.enemy_list = pygame.sprite.Group() # create enemy group
def bad_1(self, lvl, eloc):
if lvl == 1:
enemy = Enemy(eloc[0],eloc[1],'yeti.png') # spawn enemy
self.enemy_list.add(enemy) # add enemy to group
if lvl == 2:
print("Level " + str(lvl) )
return self.enemy_list
def bad_2(self, lvl, eloc):
if lvl == 1:
enemy = Enemy(eloc[0],eloc[1],'spr.png') # spawn enemy
self.enemy_list.add(enemy) # add enemy to group
if lvl == 2:
print("Level " + str(lvl) )
return self.enemy_list
class Player(pygame.sprite.Sprite):
'''
Spawn a player
'''
def gravity(self):
self.movey += 3.2 # how fast player falls
if self.rect.y > worldy and self.movey >= 0:
self.movey = 0
self.rect.y = worldy-ty-ty-ty-ty-ty-ty
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.movex = 0
self.movey = 0
self.frame = 0
self.health = 10
self.frame = 0
self.images = []
for i in range(1, 5):
img = pygame.image.load(
os.path.join('images', 'hero' + str(i) + '.png')).convert()
img.convert_alpha()
img.set_colorkey(ALPHA)
self.images.append(img)
self.image = self.images[0]
self.rect = self.image.get_rect()
def control(self, x, y):
'''
control player movement
'''
self.movex += x
self.movey += y
def update(self):
'''
Update sprite position
'''
self.rect.x = self.rect.x + self.movex
self.rect.y = self.rect.y + self.movey
# moving left
if self.movex < 0:
self.frame += 1
if self.frame > 3 * ani:
self.frame = 0
self.image = self.images[self.frame // ani]
# collisions
enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
for enemy in enemy_hit_list:
self.health -= 1
print(self.health)
# moving right
if self.movex > 0:
self.frame += 1
if self.frame > 3 * ani:
self.frame = 0
self.image = self.images[(self.frame // ani)]
'''
Setup
'''
worldx = 560
worldy = 420
fps = 40 # frame rate
ani = 4 # animation cycles
clock = pygame.time.Clock()
pygame.init()
main = True
BLUE = (25, 25, 200)
BLACK = (23, 23, 23)
WHITE = (254, 254, 254)
ALPHA = (0, 255, 0)
world = pygame.display.set_mode([worldx, worldy])
backdrop = pygame.image.load(os.path.join('images', 'stage.png')).convert()
backdropbox = world.get_rect()
player = Player() # spawn player
player.rect.x = 0
player.rect.y = 0
player_list = pygame.sprite.Group()
player_list.add(player)
steps = 10 # how fast to move
l = Level()
eloc = [200,20]
enemy_list = l.bad_1(1, eloc)
eloc = [100,10]
enemy_list = l.bad_2(1, eloc)
'''
Main loop
'''
while main == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
main = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == ord('a'):
player.control(-steps, 0)
if event.key == pygame.K_RIGHT or event.key == ord('d'):
player.control(steps, 0)
if event.key == pygame.K_UP or event.key == ord('w'):
print('jump')
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == ord('a'):
player.control(steps, 0)
if event.key == pygame.K_RIGHT or event.key == ord('d'):
player.control(-steps, 0)
if event.key == ord('q'):
pygame.quit()
sys.exit()
main = False
# world.fill(BLACK)
world.blit(backdrop, backdropbox)
player.gravity() # check gravity
player.update()
player_list.draw(world) #refresh player position
enemy_list.draw(world)
for e in enemy_list:
e.move()
pygame.display.flip()
clock.tick(fps)
但是精灵不会(再次)停在屏幕的底部边缘,当代码在执行时自行中断时我收到以下错误:
Traceback (most recent call last):
File "game.py", line 188, in <module>
player.gravity() # check gravity
File "game.py", line 72, in gravity
self.rect.y = worldy-ty-ty-ty-ty-ty-ty
NameError: name 'ty' is not defined
如果我尝试减小或增大(取决于增大或减小多少)屏幕尺寸,其中显示:
worldx = 560
worldy = 420
我收到以下错误:
Traceback (most recent call last):
File "game.py", line 188, in <module>
player.gravity() # check gravity
File "game.py", line 72, in gravity
self.rect.y = worldy-ty
NameError: name 'ty' is not defined
这个问题我也遇到过但是对比了一下没看懂代码哪里出错了
原图来自这里https://opengameart.org/sites/default/files/opp2_sprites.zip但为了方便解释,我在imgur中分开了:
内容文件夹图片:
对于敌人(精灵)是yeti.png: https://imgur.com/GNNcU6z
因为背景是stage.png: https://imgur.com/YyiEJ0q
和球员形象:
spr.png: https://imgur.com/1fYXa7Y
在 https://opensource.com/article/19/11/simulate-gravity-python 上的原始代码是
ty = 64 #tile size
但是你的代码中没有它 - 它给出了你的错误。
但是你可以使用 rect.bottom
然后你可能不需要 ty
def gravity(self):
self.movey += 3.2 # how fast player falls
if self.rect.bottom > worldy and self.movey >= 0: # <-- uses bottom
self.movey = 0
self.rect.bottom = worldy # <-- uses bottom
顺便说一句:如果你要在游戏中添加平台,那么你可以在底部(底部边框下方)创建平台,然后它应该停止玩家。
顺便说一句:要在平台上停止它需要
# collisions
enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
for enemy in enemy_hit_list:
self.health -= 1
print(self.health)
plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)
for p in plat_hit_list:
#self.health -= 1
#print(self.health)
self.rect.bottom = p.rect.top
ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)
for g in ground_hit_list:
#self.health -= 1
#print(self.health)
self.rect.bottom = g.rect.top
最好也降低重力速度,因为在非常大的速度下它可能会跳到平台下方而不检查与平台的碰撞。
def gravity(self):
self.movey += 3.2 # how fast player falls
#print(self.rect.bottom, worldy)
# reduce speed so it will not jump out platfrom
if self.movey >= 15:
self.movey = 6
if self.rect.bottom > worldy and self.movey >= 0:
self.movey = 0
self.rect.bottom = worldy
#print(self.rect.bottom, worldy)
我正在尝试按照本教程进行操作 https://opensource.com/article/19/11/simulate-gravity-python 以允许我的 sprite 到达屏幕的底部边缘,仅此而已。但是按照教程代码到它说的地步:
...让你的重力函数看起来像这样:
def gravity(self):
self.movey += 3.2 # how fast player falls
if self.rect.y > worldy and self.movey >= 0:
self.movey = 0
self.rect.y = worldy-ty
即使玩家在使用重力时不会停在屏幕的底部边缘。
我尝试按照教程中的建议再添加一个 ty
... 一个简单的解决方法是在玩家精灵到达游戏世界的底部后,通过在其新的 Y 位置添加另一个 -ty 来使它反弹得更高:
def gravity(self):
self.movey += 3.2 # how fast player falls
if self.rect.y > worldy and self.movey >= 0:
self.movey = 0
self.rect.y = worldy-ty-ty
所以我的代码看起来像这样:
import pygame
import sys
import os
'''
Objects
'''
class Enemy(pygame.sprite.Sprite):
'''
Spawn an enemy
'''
def __init__(self, x, y, img):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(os.path.join('images', img))
#self.image.convert_alpha()
#self.image.set_colorkey(ALPHA)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.counter = 0
def move(self):
'''
enemy movement
'''
distance = 20
speed = 8
if self.counter >= 0 and self.counter <= distance:
self.rect.x += speed
elif self.counter >= distance and self.counter <= distance * 2:
self.rect.x -= speed
else:
self.counter = 0
self.counter += 1
class Level:
def __init__(self):
self.enemy_list = pygame.sprite.Group() # create enemy group
def bad_1(self, lvl, eloc):
if lvl == 1:
enemy = Enemy(eloc[0],eloc[1],'yeti.png') # spawn enemy
self.enemy_list.add(enemy) # add enemy to group
if lvl == 2:
print("Level " + str(lvl) )
return self.enemy_list
def bad_2(self, lvl, eloc):
if lvl == 1:
enemy = Enemy(eloc[0],eloc[1],'spr.png') # spawn enemy
self.enemy_list.add(enemy) # add enemy to group
if lvl == 2:
print("Level " + str(lvl) )
return self.enemy_list
class Player(pygame.sprite.Sprite):
'''
Spawn a player
'''
def gravity(self):
self.movey += 3.2 # how fast player falls
if self.rect.y > worldy and self.movey >= 0:
self.movey = 0
self.rect.y = worldy-ty-ty-ty-ty-ty-ty
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.movex = 0
self.movey = 0
self.frame = 0
self.health = 10
self.frame = 0
self.images = []
for i in range(1, 5):
img = pygame.image.load(
os.path.join('images', 'hero' + str(i) + '.png')).convert()
img.convert_alpha()
img.set_colorkey(ALPHA)
self.images.append(img)
self.image = self.images[0]
self.rect = self.image.get_rect()
def control(self, x, y):
'''
control player movement
'''
self.movex += x
self.movey += y
def update(self):
'''
Update sprite position
'''
self.rect.x = self.rect.x + self.movex
self.rect.y = self.rect.y + self.movey
# moving left
if self.movex < 0:
self.frame += 1
if self.frame > 3 * ani:
self.frame = 0
self.image = self.images[self.frame // ani]
# collisions
enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
for enemy in enemy_hit_list:
self.health -= 1
print(self.health)
# moving right
if self.movex > 0:
self.frame += 1
if self.frame > 3 * ani:
self.frame = 0
self.image = self.images[(self.frame // ani)]
'''
Setup
'''
worldx = 560
worldy = 420
fps = 40 # frame rate
ani = 4 # animation cycles
clock = pygame.time.Clock()
pygame.init()
main = True
BLUE = (25, 25, 200)
BLACK = (23, 23, 23)
WHITE = (254, 254, 254)
ALPHA = (0, 255, 0)
world = pygame.display.set_mode([worldx, worldy])
backdrop = pygame.image.load(os.path.join('images', 'stage.png')).convert()
backdropbox = world.get_rect()
player = Player() # spawn player
player.rect.x = 0
player.rect.y = 0
player_list = pygame.sprite.Group()
player_list.add(player)
steps = 10 # how fast to move
l = Level()
eloc = [200,20]
enemy_list = l.bad_1(1, eloc)
eloc = [100,10]
enemy_list = l.bad_2(1, eloc)
'''
Main loop
'''
while main == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
main = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == ord('a'):
player.control(-steps, 0)
if event.key == pygame.K_RIGHT or event.key == ord('d'):
player.control(steps, 0)
if event.key == pygame.K_UP or event.key == ord('w'):
print('jump')
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == ord('a'):
player.control(steps, 0)
if event.key == pygame.K_RIGHT or event.key == ord('d'):
player.control(-steps, 0)
if event.key == ord('q'):
pygame.quit()
sys.exit()
main = False
# world.fill(BLACK)
world.blit(backdrop, backdropbox)
player.gravity() # check gravity
player.update()
player_list.draw(world) #refresh player position
enemy_list.draw(world)
for e in enemy_list:
e.move()
pygame.display.flip()
clock.tick(fps)
但是精灵不会(再次)停在屏幕的底部边缘,当代码在执行时自行中断时我收到以下错误:
Traceback (most recent call last):
File "game.py", line 188, in <module>
player.gravity() # check gravity
File "game.py", line 72, in gravity
self.rect.y = worldy-ty-ty-ty-ty-ty-ty
NameError: name 'ty' is not defined
如果我尝试减小或增大(取决于增大或减小多少)屏幕尺寸,其中显示:
worldx = 560
worldy = 420
我收到以下错误:
Traceback (most recent call last):
File "game.py", line 188, in <module>
player.gravity() # check gravity
File "game.py", line 72, in gravity
self.rect.y = worldy-ty
NameError: name 'ty' is not defined
这个问题我也遇到过
原图来自这里https://opengameart.org/sites/default/files/opp2_sprites.zip但为了方便解释,我在imgur中分开了:
内容文件夹图片:
对于敌人(精灵)是yeti.png: https://imgur.com/GNNcU6z
因为背景是stage.png: https://imgur.com/YyiEJ0q
和球员形象:
spr.png: https://imgur.com/1fYXa7Y
在 https://opensource.com/article/19/11/simulate-gravity-python 上的原始代码是
ty = 64 #tile size
但是你的代码中没有它 - 它给出了你的错误。
但是你可以使用 rect.bottom
然后你可能不需要 ty
def gravity(self):
self.movey += 3.2 # how fast player falls
if self.rect.bottom > worldy and self.movey >= 0: # <-- uses bottom
self.movey = 0
self.rect.bottom = worldy # <-- uses bottom
顺便说一句:如果你要在游戏中添加平台,那么你可以在底部(底部边框下方)创建平台,然后它应该停止玩家。
顺便说一句:要在平台上停止它需要
# collisions
enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
for enemy in enemy_hit_list:
self.health -= 1
print(self.health)
plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)
for p in plat_hit_list:
#self.health -= 1
#print(self.health)
self.rect.bottom = p.rect.top
ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)
for g in ground_hit_list:
#self.health -= 1
#print(self.health)
self.rect.bottom = g.rect.top
最好也降低重力速度,因为在非常大的速度下它可能会跳到平台下方而不检查与平台的碰撞。
def gravity(self):
self.movey += 3.2 # how fast player falls
#print(self.rect.bottom, worldy)
# reduce speed so it will not jump out platfrom
if self.movey >= 15:
self.movey = 6
if self.rect.bottom > worldy and self.movey >= 0:
self.movey = 0
self.rect.bottom = worldy
#print(self.rect.bottom, worldy)