Menu
CoddyTech

בטוח אחרי פגיעה

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

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

במשחקים רבים יש פרק זמן קצר של חסינות לאחר פגיעה. כדי לדעת כמה זמן עבר, בדוק את השעון. pygame.time.get_ticks() הוא מספר אלפיות השנייה שחלפו מאז pygame.init(). זכור את רגע הפגיעה והחסר ממנו:

now = pygame.time.get_ticks()
if rock.colliderect(player) and now - hit_time > 1000:
    hit_time = now
    lives -= 1

התחל את hit_time בערך -2000 בתוך reset(), כדי שהפגיעה הראשונה תמיד תיחשב.

הצג את זמן החסינות באמצעות הבהוב. הביטוי get_ticks() // 100 % 2 מחזיר 0 במשך עשירית שנייה, ואז 1, ואז שוב 0, ולכן ציור השחקן רק כשהערך הוא 0 גורם לו להבהב:

safe = pygame.time.get_ticks() - hit_time < 1000
if not safe or pygame.time.get_ticks() // 100 % 2 == 0:
    pygame.draw.rect(screen, (255, 196, 0), player)
challenge icon

אתגר

בינוני
  1. ב־reset(), הגדירו את hit_time = -2000 (הוסיפו אותו לשורת global).
  2. פגיעה גורעת חיים רק כאשר עברו יותר מ־1000 ms מאז hit_time; לאחר מכן הגדירו את hit_time לזמן הנוכחי.
  3. במשך 1000 ms לאחר פגיעה, ציירו את השחקן רק כאשר pygame.time.get_ticks() // 100 % 2 == 0.

נסו בעצמכם

import random
import pygame

pygame.init()
screen = pygame.display.set_mode((480, 360))
pygame.display.set_caption("Meteor Dodge")
clock = pygame.time.Clock()
heart = pygame.image.load("assets/images/heart.png").convert_alpha()
heart_empty = pygame.image.load("assets/images/heart_empty.png").convert_alpha()
font = pygame.font.Font("assets/fonts/pixel.ttf", 24)
big_font = pygame.font.Font("assets/fonts/pixel.ttf", 48)
WHITE = (240, 240, 240)
PLATE = (60, 60, 90)


def reset():
    global player, rock, score, lives
    player = pygame.Rect(220, 300, 40, 40)
    rock = pygame.Rect(random.randint(0, 456), -24, 24, 24)
    score = 0
    lives = 3


def draw_menu():
    screen.fill((30, 30, 46))
    title = big_font.render("Meteor Dodge", True, WHITE)
    title_rect = title.get_rect(center=(240, 140))
    pygame.draw.rect(screen, PLATE, title_rect.inflate(24, 12))
    screen.blit(title, title_rect)
    hint = font.render("Press Enter to play", True, WHITE)
    screen.blit(hint, hint.get_rect(center=(240, 200)))


def draw_game():
    screen.fill((30, 30, 46))
    pygame.draw.rect(screen, (255, 196, 0), player)
    pygame.draw.rect(screen, (235, 80, 80), rock)
    score_text = font.render(f"{score:05}", True, WHITE)
    score_rect = score_text.get_rect(topright=(470, 10))
    pygame.draw.rect(screen, PLATE, score_rect.inflate(12, 8))
    screen.blit(score_text, score_rect)
    for i in range(3):
        if i < lives:
            screen.blit(heart, (10 + i * 40, 10))
        else:
            screen.blit(heart_empty, (10 + i * 40, 10))


def play_frame():
    global score, lives, state
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        player.x -= 6
    if keys[pygame.K_RIGHT]:
        player.x += 6
    player.clamp_ip(screen.get_rect())

    rock.y += 4
    if rock.top > 360:
        rock.y = -24
        rock.x = random.randint(0, 456)
        score += 1
    if rock.colliderect(player):
        lives -= 1
        if lives == 0:
            state = "over"
    draw_game()


def draw_over():
    draw_game()
    message = big_font.render("Game over", True, WHITE)
    screen.blit(message, message.get_rect(center=(240, 160)))
    hint = font.render("Press R to play again", True, WHITE)
    screen.blit(hint, hint.get_rect(center=(240, 200)))


reset()
state = "menu"

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RETURN and state == "menu":
                state = "play"
            elif event.key == pygame.K_r and state == "over":
                reset()
                state = "play"

    if state == "menu":
        draw_menu()
    elif state == "play":
        play_frame()
    else:
        draw_over()
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

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

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