Un axe à la fois
Fait partie de la section Les mondes du Journey Pygame de Coddy. Leçon 19 sur 35.
Votre code de collision déplace le joueur et corrige sa position sur l’axe x, puis le déplace et corrige sa position sur l’axe y. Ce code de départ déplace le joueur sur les deux axes et ne corrige sa position qu’une seule fois. Exécutez-le et avancez vers la droite : le joueur recule brusquement le long du sol.
player.x += dx
vel_y = min(vel_y + GRAVITY, MAX_FALL)
player.y += vel_y
on_ground = False
for wall in walls:
if player.colliderect(wall):
if dx > 0:
player.right = wall.left
elif dx < 0:
player.left = wall.right
if vel_y > 0:
player.bottom = wall.top
on_ground = True
elif vel_y < 0:
player.top = wall.bottom
vel_y = 0Debout sur le sol, la gravité déplace le joueur d’un pixel vers le bas, dans le sol, à chaque image. En avançant vers la droite pendant la même image, le joueur chevauche la tuile de sol située en dessous, et le code ne peut pas savoir pourquoi. Il voit dx > 0 et place le côté droit du joueur au niveau du côté gauche de cette tuile : vers l’arrière, le long du sol.
Un chevauchement, deux déplacements, impossible de savoir lequel l’a provoqué. En ne traitant qu’un seul axe à la fois, chaque chevauchement a une seule cause. Après le déplacement sur l’axe x, le joueur n’est pas encore dans le sol ; seuls les vrais murs l’arrêtent donc. Après le déplacement sur l’axe y, le chevauchement ne peut venir que d’un déplacement sur l’axe y.
Défi
Moyen- Sépare le mouvement :
player.x += dxet une boucle surwallsqui ne corrige que x. - Ensuite, la gravité,
player.y += vel_y,on_ground = Falseet une deuxième boucle qui ne corrige que y.
Essayez vous-même
import pygame
TILE = 36
SPEED = 4
GRAVITY = 1
JUMP = -15
MAX_FALL = 12
LEVEL = [
"................",
"................",
"................",
"....P.....###...",
"................",
"................",
"...####.........",
"............#...",
"#.......#...#..#",
"################",
]
pygame.init()
screen = pygame.display.set_mode((576, 360))
pygame.display.set_caption("One Axis at a Time")
clock = pygame.time.Clock()
background = pygame.image.load("assets/backgrounds/clouds.png").convert_alpha()
block_img = pygame.image.load("assets/images/block.png").convert_alpha()
player_img = pygame.image.load("assets/images/player.png").convert_alpha()
walls = []
for row, line in enumerate(LEVEL):
for col, char in enumerate(line):
if char == "#":
walls.append(pygame.Rect(col * TILE, row * TILE, TILE, TILE))
elif char == "P":
start = (col * TILE + TILE // 2, row * TILE + TILE)
player = player_img.get_rect(midbottom=start)
vel_y = 0
on_ground = False
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN and event.key in (pygame.K_SPACE, pygame.K_UP):
if on_ground:
vel_y = JUMP
elif event.type == pygame.KEYUP and event.key in (pygame.K_SPACE, pygame.K_UP):
if vel_y < -4:
vel_y = -4
keys = pygame.key.get_pressed()
dx = 0
if keys[pygame.K_LEFT]:
dx -= SPEED
if keys[pygame.K_RIGHT]:
dx += SPEED
player.x += dx
vel_y = min(vel_y + GRAVITY, MAX_FALL)
player.y += vel_y
on_ground = False
for wall in walls:
if player.colliderect(wall):
if dx > 0:
player.right = wall.left
elif dx < 0:
player.left = wall.right
if vel_y > 0:
player.bottom = wall.top
on_ground = True
elif vel_y < 0:
player.top = wall.bottom
vel_y = 0
for y in range(0, 360, 72):
for x in range(0, 576, 72):
screen.blit(background, (x, y))
for wall in walls:
screen.blit(block_img, wall)
screen.blit(player_img, player)
pygame.display.flip()
clock.tick(60)
pygame.quit()
Toutes les leçons de Les mondes
1Des cartes à partir de texte
Un niveau en texteLignes et colonnesDes lettres qui ont un sensOù commence le joueurUn écran à la fois4Collisions avec les plateformes
Murs à gauche et à droiteAtterrir sur les plateformesSe cogner la têteTomber hors du niveauUn axe à la foisEntraînez-vous par vous-même : Playground Pygame