Menu
CoddyTech

גוש שמסייר

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

שתי מפלצות ריריות הולכות ימינה וממשיכות אל האוויר. אויב בסיור הולך הלוך ושוב: הוא מסתובב כשהוא נתקל בקיר או מגיע לקצה הקרקע שעליה הוא הולך. המחלקה Blob שומרת את direction שלה: 1 לימין ו־-1 לשמאל.

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

if self.direction > 0:
    ahead = self.rect.right
else:
    ahead = self.rect.left - 1
hit_wall = any(self.rect.colliderect(wall) for wall in walls)
ground_ahead = any(wall.collidepoint(ahead, self.rect.bottom) for wall in walls)
if hit_wall or not ground_ahead:
    self.rect.x -= self.direction
    self.direction = -self.direction

any(...) מחזירה True כשקיר אחד לפחות עובר את הבדיקה. הסיבוב מבטל את הצעד ומשנה את הכיוון. ה־Rect של המפלצת הרירית מתאים לגוף שלה, 30 על 26, קטן מתמונת 48 הפיקסלים, שמצוירת כך שמרכזה התחתון נמצא במרכז התחתון של ה־Rect.

challenge icon

אתגר

קשה

ב־Blob.update, אחרי השלב:

  1. הגדירו את ahead לערך self.rect.right כשנעים ימינה, אחרת לערך self.rect.left - 1.
  2. בדקו אם הכתם חופף לאחד הקירות, ואם אחד הקירות מכיל את הנקודה (ahead, self.rect.bottom).
  3. אם הוא פגע בקיר או שאין קרקע מלפנים, בטלו את הצעד והפכו את הכיוון של self.direction.

נסו בעצמכם

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("Patrol")
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()
blob_img = pygame.image.load("assets/images/blob.png").convert_alpha()


class Blob(pygame.sprite.Sprite):
    def __init__(self, midbottom):
        super().__init__()
        self.image = blob_img
        self.rect = pygame.Rect(0, 0, 30, 26)
        self.rect.midbottom = midbottom
        self.direction = 1

    def update(self):
        self.rect.x += self.direction

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)

blobs = pygame.sprite.Group(Blob((432, 144)), Blob((432, 324)))
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
    for wall in walls:
        if player.colliderect(wall):
            if dx > 0:
                player.right = wall.left
            elif dx < 0:
                player.left = wall.right

    vel_y = min(vel_y + GRAVITY, MAX_FALL)
    player.y += vel_y
    on_ground = False
    for wall in walls:
        if player.colliderect(wall):
            if vel_y > 0:
                player.bottom = wall.top
                on_ground = True
            elif vel_y < 0:
                player.top = wall.bottom
            vel_y = 0

    blobs.update()

    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)
    for blob in blobs:
        screen.blit(blob.image, blob.image.get_rect(midbottom=blob.rect.midbottom))
    screen.blit(player_img, player)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

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

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