LÄR DIG PYTHON

Skapa ett eget spel i Python med Pygame

Nu använder vi grunderna för att bygga ett spel med Pygame. Styr spelaren med piltangenterna, ta dig genom hålen i de fallande väggarna och försök slå ditt rekord.

Exemplet använder funktioner för att dela upp logiken. Pygame skapar bland annat objekt för fönster, klocka och text. Du kan senare bygga vidare med egna klasser för spelare och väggar.

Förberedelser

Installera Pygame i din Python-miljö från terminalen:

python -m pip install pygame

På vissa system heter kommandot python3. Spelet körs som en vanlig Python-fil på datorn och kräver ett grafiskt skrivbord. Det ritas med rektanglar, så du behöver inte leta efter några extra bildfiler.

1. Skapa spelplanen och en game-loop

Ett spel behöver läsa händelser, uppdatera tillståndet och rita nästa bild om och om igen. Följande minimala program öppnar ett fönster och stänger det korrekt när du klickar på krysset.

import pygame

pygame.init()
screen = pygame.display.set_mode((640, 512))
clock = pygame.time.Clock()
running = True

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    screen.fill((242, 246, 239))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

clock.tick(60) begränsar loopen till högst ungefär 60 bilder per sekund. I det kompletta spelet använder vi även den uppmätta tiden mellan bilder, dt, så att hastigheten uttrycks i pixlar per sekund.

2. Läs piltangenterna och flytta spelaren

pygame.key.get_pressed() berättar vilka tangenter som hålls nere. Rörelsen måste begränsas så att hela spelaren ligger inom fönstret, även vid kanterna. Funktionen move_player sköter både det och att diagonal rörelse inte blir snabbare.

3. Skapa en fallande vägg med ett hål

Spelplanen är tio block bred och varje block är 64 pixlar. Slumpa hålets startkolumn från 0 till och med 8, och hoppa över den kolumnen och nästa när väggen byggs. Då finns alltid ett hål på två block.

Öka väggens y-position med wall_speed * dt. När den lämnat spelplanen börjar en ny vägg ovanför fönstret och poängen ökar.

4. Kontrollera hela spelarens kollision

Det räcker inte att testa spelarens övre vänstra hörn. Funktionen overlaps jämför hela spelarens rektangel med varje väggblock. Om ytorna överlappar tar omgången slut. Spelarens kanter kan ligga precis intill ett block utan att ytorna överlappar.

5. Starta om en omgång

Variabeln playing avgör om spelet pågår eller visar startmenyn. Enter återställer position, poäng, hastighet och vägg. Escape eller fönstrets kryss avslutar programmet.

Hela spelet

Spara koden som fallande-vaggar.py och kör den:

python fallande-vaggar.py

Ladda ner hela Python-filen

Visa hela spelets kod
"""Undvik fallande väggar. Installera pygame och kör filen med Python 3."""

import math
import random

WIDTH, HEIGHT = 640, 512
BLOCK_SIZE = 64
PLAYER_SIZE = 32
PLAYER_SPEED = 260


def move_player(x, y, dx, dy, dt):
    """Flytta spelaren och håll hela spelaren innanför spelplanen."""
    length = math.hypot(dx, dy)
    if length > 1:
        dx, dy = dx / length, dy / length
    x = max(0, min(WIDTH - PLAYER_SIZE, x + dx * PLAYER_SPEED * dt))
    y = max(0, min(HEIGHT - PLAYER_SIZE, y + dy * PLAYER_SPEED * dt))
    return x, y


def wall_blocks(y, gap_start):
    """Ett hål på två block, med startindex från 0 till och med 8."""
    return [
        (column * BLOCK_SIZE, y, BLOCK_SIZE, BLOCK_SIZE)
        for column in range(10)
        if column not in (gap_start, gap_start + 1)
    ]


def overlaps(first, second):
    """True när två rektanglar överlappar med en positiv area."""
    x1, y1, w1, h1 = first
    x2, y2, w2, h2 = second
    return x1 < x2 + w2 and x1 + w1 > x2 and y1 < y2 + h2 and y1 + h1 > y2


def main():
    import pygame

    pygame.init()
    try:
        screen = pygame.display.set_mode((WIDTH, HEIGHT))
        pygame.display.set_caption("Fallande väggar – Programmera Python")
        clock = pygame.time.Clock()
        font = pygame.font.Font(None, 28)
        player_x, player_y = 304.0, 440.0
        wall_y = -float(BLOCK_SIZE)
        gap_start = random.randint(0, 8)
        wall_speed = 120
        score = 0
        playing = False
        running = True

        while running:
            # Begränsa bildfrekvens och undvik stora hopp efter en paus.
            dt = min(clock.tick(60) / 1000, 0.05)

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        running = False
                    elif event.key == pygame.K_RETURN and not playing:
                        player_x, player_y = 304.0, 440.0
                        wall_y = -float(BLOCK_SIZE)
                        gap_start = random.randint(0, 8)
                        wall_speed = 120
                        score = 0
                        playing = True
            if not running:
                break

            if playing:
                keys = pygame.key.get_pressed()
                dx = int(keys[pygame.K_RIGHT]) - int(keys[pygame.K_LEFT])
                dy = int(keys[pygame.K_DOWN]) - int(keys[pygame.K_UP])
                player_x, player_y = move_player(player_x, player_y, dx, dy, dt)
                wall_y += wall_speed * dt
                player = (player_x, player_y, PLAYER_SIZE, PLAYER_SIZE)

                if any(overlaps(player, block) for block in wall_blocks(wall_y, gap_start)):
                    playing = False
                elif wall_y > HEIGHT:
                    score += 1
                    wall_y = -float(BLOCK_SIZE)
                    gap_start = random.randint(0, 8)
                    wall_speed = min(wall_speed + 8, 300)

            screen.fill((242, 246, 239))
            for block in wall_blocks(wall_y, gap_start):
                pygame.draw.rect(screen, (36, 91, 76), block)
            pygame.draw.rect(screen, (215, 165, 47), (player_x, player_y, PLAYER_SIZE, PLAYER_SIZE))
            score_text = font.render(f"Klarade väggar: {score}", True, (34, 49, 44))
            screen.blit(score_text, (16, 12))
            if not playing:
                message = font.render("Enter: nytt spel | Esc: avsluta", True, (34, 49, 44))
                screen.blit(message, (170, 230))
            pygame.display.flip()
    finally:
        pygame.quit()


if __name__ == "__main__":
    main()

Bygg vidare själv

  • Ändra spelarens storlek och jämför svårighetsgraden.
  • Lägg till en andra vägg.
  • Skapa egna klasser för spelaren och väggen.
  • Byt rektanglarna mot bilder när logiken fungerar.