Menu
CoddyTech

ציר אחד בכל פעם

חלק מהיחידה עולמות במסלול ה-Pygame של Coddy. שיעור 19 מתוך 35.

קוד ההתנגשות שלך מזיז ומתקן את x, ואז מזיז ומתקן את y. קוד הפתיחה הזה מזיז את שניהם ומתקן פעם אחת. הרץ אותו והתקדם ימינה: השחקן נזרק לאחור לאורך הרצפה.

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

כשעומדים על הקרקע, כוח הכבידה מזיז את השחקן פיקסל אחד למטה, אל תוך הקרקע, בכל פריים. כשנעים ימינה באותו פריים, השחקן חופף לאריח הקרקע שמתחתיו, והקוד לא יכול לדעת מה הסיבה. הוא רואה dx > 0 ומציב את הצד הימני של השחקן לצד השמאלי של האריח: לאחור, לאורך הרצפה.

חפיפה אחת, שתי תנועות, ואין דרך לדעת איזו תנועה גרמה לה. כשעובדים על ציר אחד בכל פעם, לכל חפיפה יש סיבה אחת. אחרי התנועה על ציר x השחקן עדיין לא בתוך הקרקע, ולכן רק קירות אמיתיים עוצרים אותו. אחרי התנועה על ציר y, החפיפה יכולה לנבוע רק מתנועה לאורך ציר y.

challenge icon

אתגר

בינוני
  1. פצלו את התנועה: player.x += dx ולולאה על walls שמתקנת רק את ציר x.
  2. לאחר מכן, כוח הכבידה, player.y += vel_y, on_ground = False ולולאה שנייה שמתקנת רק את ציר y.

נסו בעצמכם

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()

כל השיעורים ביחידה עולמות

תרגלו בעצמכם: Pygame אונליין