גוש שמסייר
חלק מהיחידה עולמות במסלול ה-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.directionany(...) מחזירה True כשקיר אחד לפחות עובר את הבדיקה. הסיבוב מבטל את הצעד ומשנה את הכיוון. ה־Rect של המפלצת הרירית מתאים לגוף שלה, 30 על 26, קטן מתמונת 48 הפיקסלים, שמצוירת כך שמרכזה התחתון נמצא במרכז התחתון של ה־Rect.
אתגר
קשהב־Blob.update, אחרי השלב:
- הגדירו את
aheadלערךself.rect.rightכשנעים ימינה, אחרת לערךself.rect.left - 1. - בדקו אם הכתם חופף לאחד הקירות, ואם אחד הקירות מכיל את הנקודה
(ahead, self.rect.bottom). - אם הוא פגע בקיר או שאין קרקע מלפנים, בטלו את הצעד והפכו את הכיוון של
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()
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה עולמות
תרגלו בעצמכם: Pygame אונליין