Zum Inhalt springen
BetaEN
Lektion 4 von 4Spiele programmieren

Spiele programmieren · Lektion 4 · 60 Minuten

Projekt: Ballduell

Das lernst du

  • Einen Ball mit Geschwindigkeit in x- und y-Richtung bewegen
  • Den Ball an Wänden und Schlägern abprallen lassen
  • Einen einfachen Computer-Gegner programmieren

Zwei Schläger, ein Ball

Beim Ballduell steht links und rechts je ein Schläger. Dazwischen fliegt ein Ball hin und her. Wer ihn durchlässt, gibt dem anderen einen Punkt. Du spielst rechts, links spielt der Computer.

Ein Ball mit Tempo

Bisher lief alles nur in eine Richtung. Jetzt bekommt der Ball zwei Geschwindigkeiten: dx für links-rechts und dy für oben-unten. In jedem Bild kommt beides dazu. Ein negatives dy heißt: nach oben.

from codelix import spiel

spiel.fenster(400, 300)
ball = {"x": 50, "y": 250, "dx": 3, "dy": -2}


def schritt():
    ball["x"] = ball["x"] + ball["dx"]
    ball["y"] = ball["y"] + ball["dy"]
    spiel.kreis(ball["x"], ball["y"], 8, "orange")


spiel.starten(schritt)

Der Ball fliegt schräg nach oben rechts – und dann aus dem Bild.

Abprallen

Prallt ein Ball an einer Wand ab, dreht sich eine Richtung um. An der Decke wird aus dy = -2 dann dy = 2. Das schreibst du so: ball["dy"] = -ball["dy"].

from codelix import spiel

spiel.fenster(400, 300)
ball = {"x": 50, "y": 150, "dx": 4, "dy": 3, "r": 10}


def schritt():
    ball["x"] = ball["x"] + ball["dx"]
    ball["y"] = ball["y"] + ball["dy"]
    if ball["x"] - ball["r"] < 0 or ball["x"] + ball["r"] > 400:
        ball["dx"] = -ball["dx"]
    if ball["y"] - ball["r"] < 0 or ball["y"] + ball["r"] > 300:
        ball["dy"] = -ball["dy"]
    spiel.kreis(ball["x"], ball["y"], ball["r"], "orange")


spiel.starten(schritt)

Achtung, Klebefalle: Ist der Ball nach dem Umdrehen noch ein Stück in der Wand, dreht er im nächsten Bild wieder um. Dann zittert er an der Wand entlang. Deshalb prüfst du in der Aufgabe auch die Richtung: Oben dreht er nur um, wenn er gerade nach oben fliegt.

Der Computer-Gegner

Wie spielt ein Computer? Ganz einfach: Liegt der Ball tiefer als die Mitte seines Schlägers, fährt er nach unten. Sonst nach oben. Weil er nur 3 Pixel pro Bild schafft, ist er schlagbar:

schlaeger = {"y": 120, "h": 60}
ball_y = 200

for bild in range(5):
    mitte = schlaeger["y"] + schlaeger["h"] / 2
    if mitte < ball_y:
        schlaeger["y"] = schlaeger["y"] + 3
    elif mitte > ball_y:
        schlaeger["y"] = schlaeger["y"] - 3
    print(f"Bild {bild}: Schläger bei y = {schlaeger['y']}")

In der Aufgabe ist alles drumherum schon fertig: die Steuerung, der Gegner und die Punkte. Es fehlen nur die Funktionen für den Ball. Danach kannst du spielen – mit ↑ und ↓ oder mit den Knöpfen unter dem Spielfeld.

Weiterbauen: Zu zweit spielen: Steuere den linken Schläger mit spiel.taste("w") und spiel.taste("s") statt mit dem Computer. Lass den Ball nach jedem Treffer ein bisschen schneller werden. Oder beende das Spiel mit spiel.ende(), sobald jemand 5 Punkte hat.

Deine Aufgabe

Jetzt bist du dran

Schreib die zwei Funktionen, die das Ballduell zum Laufen bringen. 1. ball_bewegen(ball, hoehe): Bewege den Ball um dx und dy. Stößt er danach oben (y - r < 0) oder unten (y + r > hoehe) an, dreh dy um – aber nur, wenn er sich gerade auf diese Wand zubewegt. 2. abprallen(ball, schlaeger): Berührt der Ball den Schläger, dreh dx um und gib True zurück, sonst False. Der Ball zählt dabei wie ein Quadrat von x - r bis x + r und von y - r bis y + r.

from codelix import spiel

spiel.fenster(400, 300)
ball = {"x": 200, "y": 150, "dx": 4, "dy": 3, "r": 8}
links = {"x": 10, "y": 120, "b": 10, "h": 60}
rechts = {"x": 380, "y": 120, "b": 10, "h": 60}
stand = {"links": 0, "rechts": 0}


def ball_bewegen(ball, hoehe):
    pass


def abprallen(ball, schlaeger):
    return False


def schritt():
    # Du steuerst rechts mit ↑ und ↓, der Computer steuert links
    if spiel.taste("oben") and rechts["y"] > 0:
        rechts["y"] = rechts["y"] - 6
    if spiel.taste("unten") and rechts["y"] < 240:
        rechts["y"] = rechts["y"] + 6
    if links["y"] + 30 < ball["y"]:
        links["y"] = links["y"] + 3
    elif links["y"] + 30 > ball["y"]:
        links["y"] = links["y"] - 3

    ball_bewegen(ball, 300)
    if ball["dx"] < 0:
        abprallen(ball, links)
    else:
        abprallen(ball, rechts)

    if ball["x"] < 0 or ball["x"] > 400:
        if ball["x"] < 0:
            stand["rechts"] = stand["rechts"] + 1
        else:
            stand["links"] = stand["links"] + 1
        ball["x"], ball["y"] = 200, 150

    spiel.linie(200, 0, 200, 300, "#334", 2)
    spiel.rechteck(links["x"], links["y"], links["b"], links["h"], "white")
    spiel.rechteck(rechts["x"], rechts["y"], rechts["b"], rechts["h"], "cyan")
    spiel.kreis(ball["x"], ball["y"], ball["r"], "orange")
    spiel.text(160, 10, f"{stand['links']} : {stand['rechts']}", "white", 24)


spiel.starten(schritt)

Ohne Hinweise gelöst gibt es einen ⭐ auf deiner Fortschrittsseite.

Lösung anzeigen

Versuch es erst selbst – aus Fehlern lernt man am meisten. Hier ist eine mögliche Lösung:

from codelix import spiel

spiel.fenster(400, 300)
ball = {"x": 200, "y": 150, "dx": 4, "dy": 3, "r": 8}
links = {"x": 10, "y": 120, "b": 10, "h": 60}
rechts = {"x": 380, "y": 120, "b": 10, "h": 60}
stand = {"links": 0, "rechts": 0}


def ball_bewegen(ball, hoehe):
    ball["x"] = ball["x"] + ball["dx"]
    ball["y"] = ball["y"] + ball["dy"]
    if ball["y"] - ball["r"] < 0 and ball["dy"] < 0:
        ball["dy"] = -ball["dy"]
    if ball["y"] + ball["r"] > hoehe and ball["dy"] > 0:
        ball["dy"] = -ball["dy"]


def abprallen(ball, schlaeger):
    r = ball["r"]
    if (ball["x"] - r < schlaeger["x"] + schlaeger["b"] and ball["x"] + r > schlaeger["x"]
            and ball["y"] - r < schlaeger["y"] + schlaeger["h"] and ball["y"] + r > schlaeger["y"]):
        ball["dx"] = -ball["dx"]
        return True
    return False


def schritt():
    # Du steuerst rechts mit ↑ und ↓, der Computer steuert links
    if spiel.taste("oben") and rechts["y"] > 0:
        rechts["y"] = rechts["y"] - 6
    if spiel.taste("unten") and rechts["y"] < 240:
        rechts["y"] = rechts["y"] + 6
    if links["y"] + 30 < ball["y"]:
        links["y"] = links["y"] + 3
    elif links["y"] + 30 > ball["y"]:
        links["y"] = links["y"] - 3

    ball_bewegen(ball, 300)
    if ball["dx"] < 0:
        abprallen(ball, links)
    else:
        abprallen(ball, rechts)

    if ball["x"] < 0 or ball["x"] > 400:
        if ball["x"] < 0:
            stand["rechts"] = stand["rechts"] + 1
        else:
            stand["links"] = stand["links"] + 1
        ball["x"], ball["y"] = 200, 150

    spiel.linie(200, 0, 200, 300, "#334", 2)
    spiel.rechteck(links["x"], links["y"], links["b"], links["h"], "white")
    spiel.rechteck(rechts["x"], rechts["y"], rechts["b"], rechts["h"], "cyan")
    spiel.kreis(ball["x"], ball["y"], ball["r"], "orange")
    spiel.text(160, 10, f"{stand['links']} : {stand['rechts']}", "white", 24)


spiel.starten(schritt)