Menu
CoddyTech

Hitung Mundur untuk Mulai

Termasuk bagian Aturan Game dalam perjalanan Pygame di Coddy. Pelajaran 14 dari 29.

Menekan Enter langsung membuat pemain berhadapan dengan batu-batu yang berjatuhan. Hitung mundur, 3, 2, 1, memberi mereka waktu untuk bersiap. Ini adalah satu state lagi, "countdown", yang menggambar game tanpa menggerakkannya, dengan sebuah angka di bagian atas.

Angka tersebut berasal dari waktu sejak hitung mundur dimulai:

left = 3 - (pygame.time.get_ticks() - countdown_start) // 1000

Pada detik pertama, // menghasilkan 0, jadi left bernilai 3; lalu 2, lalu 1. Saat nilainya mencapai 0, permainan dimulai:

def countdown_frame():
    global state
    left = 3 - (pygame.time.get_ticks() - countdown_start) // 1000
    draw_game()
    if left > 0:
        number = big_font.render(str(left), True, WHITE)
        screen.blit(number, number.get_rect(center=(240, 170)))
    else:
        state = "play"

Enter dan R sama-sama memulai hitung mundur, jadi sebuah fungsi kecil menetapkan state dan mengingat waktu mulainya:

def start_countdown():
    global state, countdown_start
    state = "countdown"
    countdown_start = pygame.time.get_ticks()
challenge icon

Tantangan

Sedang
  1. Tulis start_countdown() dan countdown_frame() seperti yang ditunjukkan, lalu panggil countdown_frame() saat state bernilai "countdown".
  2. Menekan Enter di menu dan R di layar game over akan memanggil start_countdown() alih-alih mengatur "play".
  3. Hitung mundur menampilkan 3, 2, dan 1 masing-masing selama satu detik, di tengah pada (240, 170).

Coba sendiri

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)
POINT = pygame.USEREVENT + 1
SPAWN = pygame.USEREVENT + 2


def reset():
    global player, rocks, score, lives, hit_time, wave, to_spawn
    player = pygame.Rect(220, 300, 40, 40)
    rocks = []
    wave = 1
    to_spawn = 3
    score = 0
    lives = 3
    hit_time = -2000
    pygame.time.set_timer(POINT, 1000)
    pygame.time.set_timer(SPAWN, 800)


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))
    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)
    for rock in rocks:
        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)
    wave_text = font.render(f"Wave {wave}", True, WHITE)
    screen.blit(wave_text, wave_text.get_rect(midtop=(240, 10)))
    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, hit_time, rocks, wave, to_spawn
    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())

    for rock in rocks:
        rock.y += 4
    rocks = [rock for rock in rocks if rock.top <= 360]
    if to_spawn == 0 and not rocks:
        wave += 1
        to_spawn = wave + 2
    now = pygame.time.get_ticks()
    for rock in rocks:
        if rock.colliderect(player) and now - hit_time > 1000:
            hit_time = now
            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 == POINT and state == "play":
            score += 1
        if event.type == SPAWN and state == "play" and to_spawn > 0:
            rocks.append(pygame.Rect(random.randint(0, 456), -24, 24, 24))
            to_spawn -= 1
        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()
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Aturan Game

Latihan sendiri: Playground Pygame