当验证玩家的状态(跑步,跳跃,空转)时,跳跃会覆盖它们,因为y轴速度(代码包含矢量)虽然没有移动(我认为)但不会停止。
跳转验证码:
if self.vel.y != 0:
self.jumping = True
else:
self.jumping = False
空转验证码:
if self.vel.x == 0 and self.vel.y == 0:
self.jumping = False
self.running = False
运行验证码:
keys = pg.key.get_pressed()
if keys[pg.K_a] or keys[pg.K_d] and not self.jumping:
self.running = True
else:
self.running = False
还有其他方法可以验证玩家是否在跳跃吗?
当删除此代码时,没有更多的跳跃动画,但是空闲工作正常,在删除代码之前,空闲根本不起作用,但运行有或没有代码。 我已经尝试过指向重要的位,然后它们都会通过。
我正在使用此代码为播放器制作动画,动画代码完美无缺。
以下是Player
类和Wall
类的所有代码:
sprites.py
import pygame as pg
from settings import *
import os
vec = pg.math.Vector2
game_folder = os.path.dirname(__file__)
img_folder = os.path.join(game_folder, 'img')
animation_folder = os.path.join(img_folder, 'animations')
class Sprite_sheet:
def __init__(self, filename):
self.sprite_sheet = pg.image.load(os.path.join(animation_folder, filename)).convert()
def get_image(self, x, y, width, height):
image = pg.Surface((width, height))
image.blit(self.sprite_sheet, (0,0), (x, y, width, height))
return image
def collide_hit_rect(one, two):
return one.hit_rect.colliderect(two.rect)
def collide_with_walls(sprite, group, dir):
if dir == 'x':
hits = pg.sprite.spritecollide(sprite, group, False, collide_hit_rect)
if hits:
if hits[0].rect.centerx > sprite.hit_rect.centerx:
sprite.pos.x = hits[0].rect.left - sprite.hit_rect.width / 2
if hits[0].rect.centerx < sprite.hit_rect.centerx:
sprite.pos.x = hits[0].rect.right + sprite.hit_rect.width / 2
sprite.vel.x = 0
sprite.hit_rect.centerx = sprite.pos.x
if dir == 'y':
hits = pg.sprite.spritecollide(sprite, group, False, collide_hit_rect)
if hits:
if hits[0].rect.centery > sprite.hit_rect.centery:
sprite.pos.y = hits[0].rect.top - sprite.hit_rect.height / 2
if hits[0].rect.centery < sprite.hit_rect.centery:
sprite.pos.y = hits[0].rect.bottom + sprite.hit_rect.height / 2
sprite.vel.y = 0
sprite.hit_rect.centery = sprite.pos.y
class Player(pg.sprite.Sprite):
def __init__(self, game, x, y):
self.groups = game.all_sprites
pg.sprite.Sprite.__init__(self, self.groups)
self.game = game
self.load_images()
self.image = self.standing_frames_r[0]
self.rect = self.image.get_rect()
self.x = x * TILESIZE
self.y = y * TILESIZE
self.rect.center = (x, y)
self.hit_rect = PLAYER_HIT_RECT
self.hit_rect.center = self.rect.center
self.vel = vec(0, 0)
self.pos = vec(x, y)
self.jumping = False
self.running = False
self.current_frame = 0
self.last_update = 0
self.idle_right = True
self.idle_left = False
self.falling_right = True
self.falling_left = False
def load_images(self):
#idle right
self.spritesheet_idle = Sprite_sheet('idle.png')
self.standing_frames_r = [self.spritesheet_idle.get_image(0, 0, 19, 34),
self.spritesheet_idle.get_image(19, 0, 19, 34),
self.spritesheet_idle.get_image(38, 0, 19, 34),
self.spritesheet_idle.get_image(57, 0, 19, 34),
self.spritesheet_idle.get_image(76, 0, 19, 34),
self.spritesheet_idle.get_image(95, 0, 19, 34),
self.spritesheet_idle.get_image(114, 0, 19, 34),
self.spritesheet_idle.get_image(133, 0, 19, 34),
self.spritesheet_idle.get_image(152, 0, 19, 34),
self.spritesheet_idle.get_image(171, 0, 19, 34),
self.spritesheet_idle.get_image(190, 0, 19, 34),
self.spritesheet_idle.get_image(209, 0, 19, 34)]
for frame in self.standing_frames_r:
frame.set_colorkey(BLACK)
# idle left
self.standing_frames_l = []
for frame in self.standing_frames_r:
self.standing_frames_l.append(pg.transform.flip(frame, True, False))
frame.set_colorkey(BLACK)
# walk right
self.spritesheet_walk = Sprite_sheet('walk.png')
self.walk_frames_r = [self.spritesheet_walk.get_image(0, 0, 21, 33),
self.spritesheet_walk.get_image(21, 0, 21, 33),
self.spritesheet_walk.get_image(42, 0, 21, 33),
self.spritesheet_walk.get_image(63, 0, 21, 33),
self.spritesheet_walk.get_image(84, 0, 21, 33),
self.spritesheet_walk.get_image(105, 0, 21, 33),
self.spritesheet_walk.get_image(126, 0, 21, 33),
self.spritesheet_walk.get_image(147, 0, 21, 33)]
for frame in self.walk_frames_r:
frame.set_colorkey(BLACK)
# walk left
self.walk_frames_l = []
for frame in self.walk_frames_r:
self.walk_frames_l.append(pg.transform.flip(frame, True, False))
frame.set_colorkey(BLACK)
# falling right
self.spritesheet_falling = Sprite_sheet('falling.png')
self.falling_frames_r = [self.spritesheet_falling.get_image(0, 0, 20, 35),
self.spritesheet_falling.get_image(20, 0, 20, 35)]
for frame in self.falling_frames_r:
frame.set_colorkey(BLACK)
# falling left
self.falling_frames_l = []
for frame in self.falling_frames_r:
self.falling_frames_l.append(pg.transform.flip(frame, True, False))
def jump(self):
self.hit_rect.y += 1
hits = pg.sprite.spritecollide(self, self.game.walls, False, collide_hit_rect)
self.hit_rect.y -= 1
if hits:
self.vel.y = -6
def animate(self):
# determining the direction
if self.vel.x > 0:
self.idle_right = True
self.idle_left = False
self.falling_right = True
self.falling_left = False
if self.vel.x < 0:
self.idle_right = False
self.idle_left = True
self.falling_right = False
self.falling_left = True
now = pg.time.get_ticks()
keys = pg.key.get_pressed()
# Testing for the states
if self.vel.y != 0:
self.jumping = True
self.running = False
elif keys[pg.K_a] or keys[pg.K_d]:
self.running = True
self.jumping = False
elif self.vel.y == 0:
self.jumping = False
else:
self.jumping = False
self.running = False
# Animating (changing the image)
if self.jumping:
if now - self.last_update > 150:
self.last_update = now
self.current_frame = (self.current_frame + 1) % len(self.falling_frames_r)
bottom = self.rect.bottom
if self.falling_right:
self.image = self.falling_frames_r[self.current_frame]
elif self.falling_left:
self.image = self.falling_frames_l[self.current_frame]
self.rect.bottom = bottom
if not self.jumping and not self.running:
if now - self.last_update > 200:
bottom = self.rect.bottom
self.last_update = now
self.current_frame = (self.current_frame + 1) % len(self.standing_frames_r)
if self.idle_left:
self.image = self.standing_frames_l[self.current_frame]
elif self.idle_right:
self.image = self.standing_frames_r[self.current_frame]
self.rect.bottom = bottom
if self.running:
if now - self.last_update > 100:
self.last_update = now
self.current_frame = (self.current_frame + 1) % len(self.walk_frames_r)
bottom = self.rect.bottom
if self.vel.x > 0:
self.image = self.walk_frames_r[self.current_frame]
else:
self.image = self.walk_frames_l[self.current_frame]
self.rect.bottom = bottom
def update(self):
self.animate()
self.acc = vec(0, PLAYER_GRAV)
keys = pg.key.get_pressed()
if keys[pg.K_a]:
self.acc.x = -PLAYER_ACC
if keys[pg.K_d]:
self.acc.x = PLAYER_ACC
if keys[pg.K_SPACE]:
self.jump()
self.acc.x += self.vel.x * PLAYER_FRICTION
self.vel += self.acc
self.pos += self.vel + 0.5 * self.acc
self.hit_rect.centerx = self.pos.x
collide_with_walls(self, self.game.walls, 'x')
self.hit_rect.centery = self.pos.y
collide_with_walls(self, self.game.walls, 'y')
self.rect.center = self.hit_rect.center
class Wall(pg.sprite.Sprite):
def __init__(self, game, x, y):
self.groups = game.all_sprites, game.walls
pg.sprite.Sprite.__init__(self, self.groups)
self.game = game
self.image = pg.Surface((TILESIZE, TILESIZE))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.x = x
self.y = y
self.rect.x = x * TILESIZE
self.rect.y = y * TILESIZE
感谢您的帮助:)
答案 0 :(得分:1)
我修复了您的代码,以便回答您的问题并解决您的问题。跳跃验证现在有效,这就是你的问题所在。但我认为代码的其他部分需要修复,但我会留给你。
我对代码所做的更改:
摆脱self.hit_rect
的所有用途。我不知道为什么你需要这个以及它为什么被使用。在所有情况下,我只是将其更改为self.rect
。据我所知,你真的只需要一个rect
。
我在collide_with_walls
函数中注释掉了一些代码。我还删除了与hit_rect
相关的代码行。每当根据return True
中是否有任何精灵时,我也会使用return False
或hits
这个函数。这样做是为了允许稍后在update
方法中使用代码。
现在根据玩家是否与墙壁发生碰撞来设置self.vel.y
变量。我通过加速来评论大部分代码,以简化一些事情。我添加了一些,但你会把剩下的留给你。
在update
方法中,hit_rect
不再使用。
这是固定代码:
<强> sprites.py 强>
import pygame as pg
from settings import *
import os
vec = pg.math.Vector2
game_folder = os.path.dirname(__file__)
img_folder = os.path.join(game_folder, 'img')
animation_folder = os.path.join(img_folder, 'animations')
class Sprite_sheet:
def __init__(self, filename):
self.sprite_sheet = pg.image.load(os.path.join(animation_folder, filename)).convert()
def get_image(self, x, y, width, height):
image = pg.Surface((width, height))
image.blit(self.sprite_sheet, (0,0), (x, y, width, height))
return image
def collide_hit_rect(one, two):
return one.rect.colliderect(two.rect)
def collide_with_walls(sprite, group, dir):
if dir == 'x':
hits = pg.sprite.spritecollide(sprite, group, False, collide_hit_rect )
if hits:
# if hits[0].rect.centerx > sprite.rect.centerx:
# sprite.pos.x = hits[0].rect.left - sprite.rect.width / 2
# if hits[0].rect.centerx < sprite.rect.centerx:
# sprite.pos.x = hits[0].rect.right + sprite.rect.width / 2
sprite.vel.x = 0
return True
if dir == 'y':
hits = pg.sprite.spritecollide(sprite, group, False, collide_hit_rect)
if hits:
# if hits[0].rect.centery > sprite.rect.centery:
# sprite.pos.y = hits[0].rect.top - sprite.rect.height / 2
# if hits[0].rect.centery < sprite.rect.centery:
# sprite.pos.y = hits[0].rect.bottom + sprite.rect.height / 2
sprite.vel.y = 0
return True
if hits == []:
return False
elif hits != []:
return True
class Player(pg.sprite.Sprite):
def __init__(self, game, x, y):
self.groups = game.all_sprites
pg.sprite.Sprite.__init__(self, self.groups)
self.game = game
self.load_images()
self.image = self.standing_frames_r[0]
self.rect = self.image.get_rect()
self.x = x * TILESIZE
self.y = y * TILESIZE
self.rect.center = (x, y)
self.vel = vec(0, 0)
self.pos = vec(x, y)
self.jumping = False
self.running = False
self.current_frame = 0
self.last_update = 0
self.idle_right = True
self.idle_left = False
self.falling_right = True
self.falling_left = False
# hit_rect
def load_images(self):
#idle right
self.spritesheet_idle = Sprite_sheet('idle.png')
self.standing_frames_r = [self.spritesheet_idle.get_image(0, 0, 19, 34),
self.spritesheet_idle.get_image(19, 0, 19, 34),
self.spritesheet_idle.get_image(38, 0, 19, 34),
self.spritesheet_idle.get_image(57, 0, 19, 34),
self.spritesheet_idle.get_image(76, 0, 19, 34),
self.spritesheet_idle.get_image(95, 0, 19, 34),
self.spritesheet_idle.get_image(114, 0, 19, 34),
self.spritesheet_idle.get_image(133, 0, 19, 34),
self.spritesheet_idle.get_image(152, 0, 19, 34),
self.spritesheet_idle.get_image(171, 0, 19, 34),
self.spritesheet_idle.get_image(190, 0, 19, 34),
self.spritesheet_idle.get_image(209, 0, 19, 34)]
for frame in self.standing_frames_r:
frame.set_colorkey(BLACK)
# idle left
self.standing_frames_l = []
for frame in self.standing_frames_r:
self.standing_frames_l.append(pg.transform.flip(frame, True, False))
frame.set_colorkey(BLACK)
# walk right
self.spritesheet_walk = Sprite_sheet('walk.png')
self.walk_frames_r = [self.spritesheet_walk.get_image(0, 0, 21, 33),
self.spritesheet_walk.get_image(21, 0, 21, 33),
self.spritesheet_walk.get_image(42, 0, 21, 33),
self.spritesheet_walk.get_image(63, 0, 21, 33),
self.spritesheet_walk.get_image(84, 0, 21, 33),
self.spritesheet_walk.get_image(105, 0, 21, 33),
self.spritesheet_walk.get_image(126, 0, 21, 33),
self.spritesheet_walk.get_image(147, 0, 21, 33)]
for frame in self.walk_frames_r:
frame.set_colorkey(BLACK)
# walk left
self.walk_frames_l = []
for frame in self.walk_frames_r:
self.walk_frames_l.append(pg.transform.flip(frame, True, False))
frame.set_colorkey(BLACK)
# falling right
self.spritesheet_falling = Sprite_sheet('falling.png')
self.falling_frames_r = [self.spritesheet_falling.get_image(0, 0, 20, 35),
self.spritesheet_falling.get_image(20, 0, 20, 35)]
for frame in self.falling_frames_r:
frame.set_colorkey(BLACK)
# falling left
self.falling_frames_l = []
for frame in self.falling_frames_r:
self.falling_frames_l.append(pg.transform.flip(frame, True, False))
def jump(self):
self.rect.y += 1
hits = pg.sprite.spritecollide(self, self.game.walls, False, collide_hit_rect)
self.rect.y -= 1
if hits:
print("Jump")
self.vel.y = -30
def animate(self):
# determining the direction
if self.vel.x > 0:
self.idle_right = True
self.idle_left = False
self.falling_right = True
self.falling_left = False
if self.vel.x < 0:
self.idle_right = False
self.idle_left = True
self.falling_right = False
self.falling_left = True
now = pg.time.get_ticks()
keys = pg.key.get_pressed()
# Testing for the states
if self.vel.y != 0:
self.jumping = True
self.running = False
elif keys[pg.K_a] or keys[pg.K_d]:
self.running = True
self.jumping = False
elif self.vel.y == 0:
self.jumping = False
else:
self.jumping = False
self.running = False
print(self.jumping)
# Animating (changing the image)
if self.jumping:
if now - self.last_update > 150:
self.last_update = now
self.current_frame = (self.current_frame + 1) % len(self.falling_frames_r)
bottom = self.rect.bottom
if self.falling_right:
self.image = self.falling_frames_r[self.current_frame]
elif self.falling_left:
self.image = self.falling_frames_l[self.current_frame]
self.rect.bottom = bottom
if not self.jumping and not self.running:
if now - self.last_update > 200:
bottom = self.rect.bottom
self.last_update = now
self.current_frame = (self.current_frame + 1) % len(self.standing_frames_r)
if self.idle_left:
self.image = self.standing_frames_l[self.current_frame]
elif self.idle_right:
self.image = self.standing_frames_r[self.current_frame]
self.rect.bottom = bottom
if self.running:
if now - self.last_update > 100:
self.last_update = now
self.current_frame = (self.current_frame + 1) % len(self.walk_frames_r)
bottom = self.rect.bottom
if self.vel.x > 0:
self.image = self.walk_frames_r[self.current_frame]
else:
self.image = self.walk_frames_l[self.current_frame]
self.rect.bottom = bottom
def update(self):
self.animate()
self.acc = vec(0, PLAYER_GRAV)
keys = pg.key.get_pressed()
if keys[pg.K_a]:
self.acc.x = -PLAYER_ACC
if keys[pg.K_d]:
self.acc.x = PLAYER_ACC
self.acc.x += self.vel.x * PLAYER_FRICTION
if collide_with_walls(self, self.game.walls, 'y'):
# print("Colliding")
self.vel.y = 0
self.acc.y = 0
else:
# print("Falling")
self.vel.y = 2
if keys[pg.K_SPACE]:
self.jump()
if self.vel.y > 0:
self.vel.y += PLAYER_GRAV
self.pos += self.vel + 0.5 * self.acc
self.rect.centerx = self.pos.x
self.rect.centery = self.pos.y
class Wall(pg.sprite.Sprite):
def __init__(self, game, x, y):
self.groups = game.all_sprites, game.walls
pg.sprite.Sprite.__init__(self, self.groups)
self.game = game
self.image = pg.Surface((TILESIZE, TILESIZE))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.x = x
self.y = y
self.rect.x = x * TILESIZE
self.rect.y = y * TILESIZE
我希望这个答案可以帮助您,如果您在下面发表评论时遇到任何其他问题!
答案 1 :(得分:0)
您可以在一个地方合并州检查代码以防止竞争条件吗?
if self.vel.y != 0:
self.jumping = True
self.running = False
elif keys[pg.K_a] or keys[pg.K_d]:
# perhaps modify self.vel.x here?
self.running = True
self.jumping = False
else: # must be idle here
self.running = False
self.jumping = False