====== 5. Animationsschleife ======
Will man eine Bewegung simulieren, so verwendet man häufig das Prinzip eines "Game-Loop". Dies ist eine Schleife, die immer und immer wieder durchgeführt wird. Dabei wird die "Spielwelt" in jedem Durchgang der Schleife gelöscht (''clear'') und neu gezeichnet. Zwischen jedem Durchlauf der Schleife werden auch alle Positionen der vorhandenen Objekte etc. neu berechnet. Häufig werden Positionen der Objekte in globalen Variablen gespeichert.
Hier ein Mini-Beispiel: Ein Kreis soll sich von links nach rechts bewegen. Die Position des Kreises stellen wir mit den globalen Variablen ''x'' und ''y'' dar. Bei jedem Durchlauf wird 40 Millisekunden gewartet, das Bild gelöscht und der x-Wert vergrössert.
from gturtle import *
# x und y-Position
x = -200
y = 0
running = True # solange dies True ist, wird Animation laufen
# wenn Maus gedrückt wird, soll Programm abbrechen
def onMouseHit(x,y):
global running
running = False
makeTurtle(mouseHit=onMouseHit)
hideTurtle()
setPenColor("red")
while running:
clear()
setPos(x,y)
dot(40)
delay(40)
x = x + 4
=== Aufgabe 1 ===
Ändere das Beispiel, sodass sich der Punkt von links unten nach rechts oben bewegt.
=== Aufgabe 2 ===
Ändere das Beispiel, sodass der Punkt an den Rändern zurückprallt. Tipp: setze eine Variable auf +4 und addiere dann die Variable. Wenn der Rand erreicht wird, muss du nur die Variable auf -4 setzen...
== Lösung ==
from gturtle import *
# x und y-Position
x = -400
y = 0
running = True # solange dies True ist, wird Animation laufen
dx = 8
dy = 8
# wenn Maus gedrückt wird, soll Programm abbrechen
def onMouseHit(x,y):
global running
print("Jupp")
running = False
makeTurtle(mouseHit=onMouseHit)
hideTurtle()
setPenColor("red")
while running:
clear()
setPos(x,y)
dot(40)
delay(40)
x = x + dx
y = y + dy
if x > 400:
dx = -8
if x < -400:
dx = 8
if y > 300:
dy = -5
if y < -300:
dy = 5
=== Aufgabe 3 ===
Ändere das Beispiel, sodass sich der Punkt in einem Kreis mit Radius 300 im Gegenuhrzeigersinn bewegt. Denke dabei an den Einheitskreis aus der Mathematik, in welchem wir Sinus und Cosinus definiert haben. (Tipp: Punkt P(300Cos(x); 300Sin(x))
== Lösung ==
from gturtle import *
import math # Mathe-Bibliothek laden für sin, cos
alpha = 0 # Startwinkel
running = True # solange dies True ist, wird Animation laufen
# wenn Maus gedrückt wird, soll Programm abbrechen
def onMouseHit(x,y):
global running
running = False
makeTurtle(mouseHit=onMouseHit)
hideTurtle()
setPenColor("red")
enableRepaint(False) # selbst angeben wann neu gezeichnet wird (mit repaint())
while running: #Game-Loop
clear() # Bildschirm löschen
x = 250*math.cos(alpha) #x- und y-Wert setzen
y = 250*math.sin(alpha)
setPos(x,y)
dot(40)
repaint() #neu zeichnen (manuell um flackern zu verhindern)
delay(40)
alpha = alpha + 0.02
=== Aufgabe 4 ===
Ändere das Beispiel, sodass man mit den Cursortasten den Punkt bewegen kann.
== Lösung ==
from gturtle import *
import math # Mathe-Bibliothek laden für sin, cos
x = 0 # x- und y-Position
y = 0
dx = 0 #Änderung in x und y-Richtung
dy = 0
running = True # solange dies True ist, wird Animation laufen
# wenn Maus gedrückt wird, soll Programm abbrechen
def onMouseHit(x,y):
global running
running = False
def onKeyPressed(keycode):
global dx
global dy
if keycode == 37:
dy = 0
dx = -5
if keycode == 38:
dx = 0
dy = 5
if keycode == 39:
dx = 5
dy = 0
if keycode == 40:
dx = 0
dy = -5
makeTurtle(mouseHit=onMouseHit, keyPressed=onKeyPressed)
hideTurtle()
setPenColor("red")
enableRepaint(False) # selbst angeben wann neu gezeichnet wird (mit repaint())
while running: #Game-Loop
clear() # Bildschirm löschen
x = x + dx
y = y + dy
setPos(x,y)
dot(40)
repaint() #neu zeichnen (manuell um flackern zu verhindern)
delay(40)
=== Aufgabe 5 ===
Ändere das Beispiel, so dass man mit den Cursortasten die Geschwindigkeit des Punktes in eine beliebige Richtung verändern kann. Tipp: Wenn die Tasten gedrückt werden, so änderst du eine Variable VelocityX bzw. VelocityY. Je grösser diese Variablen sind, desto mehr addiert/subtrahiert man dann bei der Position x bzw. y.
== Lösung ==
from gturtle import *
x = 0 # x- und y-Position
y = 0
dx = 0 #Änderung in x und y-Richtung
dy = 0
running = True # solange dies True ist, wird Animation laufen
# wenn Maus gedrückt wird, soll Programm abbrechen
def onMouseHit(x,y):
global running
running = False
def onKeyPressed(keycode):
global dx
global dy
if keycode == 37:
dx = dx - 1
print(dx)
if keycode == 38:
dy = dy + 1
if keycode == 39:
dx = dx + 1
if keycode == 40:
dy = dy - 1
makeTurtle(mouseHit=onMouseHit, keyPressed=onKeyPressed)
hideTurtle()
setPenColor("red")
enableRepaint(False) # selbst angeben wann neu gezeichnet wird (mit repaint())
while running: #Game-Loop
delay(40)
clear() # Bildschirm löschen
x = x + dx
y = y + dy
print(x,y)
setPos(x,y)
dot(40)
repaint() #neu zeichnen (manuell um flackern zu verhindern)
=== Aufgabe 6 ===
Jetzt versuchen wir ein kleines Spiel zu programmieren und zwar ein ähnliches Spiel wie [[https://www.youtube.com/watch?v=p2l04VawHe8|Superball auf SAT 1]].
- Nimm die Lösung von Aufgabe 4 als Vorlage
- Versuche das Beispiel so zu ändern, dass der Spieler-Ball unten dargestellt wird und dass man ihn nur nach rechts/links bewegen kann
- Füge einen "Gegnerball" hinzu, der von ganz oben nach unten fällt
- Versuche dein Beispiel so zu erweitern, dass der Ball wieder oben startet, wenn er unten rausfällt (idealerweise an einer zufälligen x-Position)
- Versuche die Kollision zu testen (wenn der y-Wert des Gegnerballs in einem Bestimmten Bereich ist, kann man testen, ob die x-Werte der beiden Bälle zu nahe sind...)
==== Grundgerüst für ein Spiel ====
Es folgt ein Grundgerüst für ein Spiel.
from gturtle import *
import math # Mathe-Bibliothek laden für sin, cos
from random import randint # die randint-Funktion aus de random-Bibliothek laden
#===============================================================================
# Hier wird die Spiele-Welt definiert (Position, Geschw. der Objekte etc.
running = True # solange dies True ist, wird Animation laufen
#===============================================================================
def onKeyPressed(keycode):
global dx
global dy
global running
if keycode == 37:
dy = 0
dx = -5
if keycode == 38:
dx = 0
dy = 5
if keycode == 39:
dx = 5
dy = 0
if keycode == 40:
dx = 0
dy = -5
if keycode == 27: # Esc-Button
running = False
makeTurtle(keyPressed=onKeyPressed)
hideTurtle()
setPenColor("red")
enableRepaint(False) # selbst angeben, wann neu gezeichnet wird (mit repaint())
def calculateNewPositions():
pass
def detectCollisions():
pass
def drawWorld():
pass
#===============================================================================
# Game-Loop
#===============================================================================
while running: #Game-Loop
clear() # Bildschirm löschen
calculateNewPositions() # neue Position bestimmen
detectCollisions() # Kollisionen prüfen
drawWorld() # Welt neu zeichnen
repaint() #neu zeichnen (manuell um flackern zu verhindern)
delay(40)