18. Verwenden der Klasse Window
¶
Wir können eine Klasse verwenden, um unser Programm repräsentieren. Die Arcade-Bibliothek verfügt über eine integrierte Klasse, die ein Fenster auf dem Bildschirm darstellt. Wir können unsere eigene Kindklasse erstellen und Funktionen überschreiben, um Folgendes zu erreichen:
Starten und Initialisierung
Zeichnen der Elemente auf unserem Bildschirm
Animieren/Aktualisieren der Positionen von Elementen auf unserem Bildschirm
Auf Tastatureingaben reagieren
Auf die Mausaktionen reagieren
Eine der besten Möglichkeiten, das Programmieren zu lernen, ist das Betrachten von Beispielcode. In diesem Kapitel findest du einige Beispiele, anhand derer du Folgendes lernen kannst:
Fenster mit einem objektorientierten Ansatz öffnen
Objekte animieren
Objekte mit der Maus bewegen
Objekte mit der Tastatur verschieben
Objekte mit dem Joystick bewegen
18.1. Erstellen eines Fensters mit einer Klasse¶
Bisher haben wir die Funktion open_window
verwendet, um ein Fenster zu öffnen. Hier ist der Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 | import arcade
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
def main():
arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing Example")
arcade.run()
main()
|
Wir können auch ein Exemplar der Klasse Window
erstellen, um ein Fenster zu öffnen. Der Programmcode ist ziemlich einfach:
1 2 3 4 5 6 7 8 9 10 11 12 13 | import arcade
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
def main():
window = arcade.Window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing Example")
arcade.run()
main()
|
Funktionsaufrufe und Aufrufe zum Erstellen eines Objekts sehen sehr ähnlich aus. Der verräterische Hinweis darauf, dass wir im zweiten Beispiel eine Instanz eines Objekts erstellen, ist die Tatsache, dass Window
groß geschrieben wird.
18.2. Erweitern der Klasse Window
¶
Die Window
-Klasse von Arcade verfügt über eine Reihe integrierter Methoden, die bei Bedarf automatisch aufgerufen werden: Methoden zum Zeichnen, zum Reagieren auf Tastatur, Maus und mehr. Du kannst alle Methoden in der Window Class Documentation nachschlagen. Standardmäßig tun diese Methoden jedoch nichts. Das müssen wir ändern.
Wie wir im vorherigen Kapitel kennengelernt haben, können wir die Funktionalität einer Klasse erweitern, indem wir eine Kindklasse erstellen. Daher können wir die Klasse Window
erweitern, indem wir eine Kindklasse davon erstellen. Ich werde meine Kindklasse MyGame
nennen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import arcade
class MyGame(arcade.Window):
def __init__(self, width, height, title):
# Call the parent class's init function
super().__init__(width, height, title)
def main():
window = MyGame(640, 480, "Drawing Example")
arcade.run()
main()
|
18.3. Zeichnen mit der Klasse Window
¶
Um mit der Klasse Window
zu zeichnen, müssen wir unsere eigene Methode on_draw
erstellen. Diese überschreibt die Standardmethode on_draw
, die in die Klasse Window
eingebaut ist. Wir werden unseren Code zum Zeichnen dort einfügen.
Die Methode on_draw
wird ungefähr 60 mal pro Sekunde aufgerufen. Wir werden diese Tatsache nutzen, wenn wir die Bilder animieren.
Wir müssen auch die Hintergrundfarbe einstellen. Da wir das nur einmal machen müssen, setzen wir sie in der __init__
-Methode. Es ergibt keinen Sinn, den Hintergrund 60 Mal pro Sekunde einzustellen, wenn er sich nicht ändert.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import arcade
class MyGame(arcade.Window):
def __init__(self, width, height, title):
# Call the parent class's init function
super().__init__(width, height, title)
# Set the background color
arcade.set_background_color(arcade.color.ASH_GREY)
def on_draw(self):
""" Called whenever we need to draw the window. """
arcade.start_render()
arcade.draw_circle_filled(50, 50, 15, arcade.color.AUBURN)
def main():
window = MyGame(640, 480, "Drawing Example")
arcade.run()
main()
|
Das Ergebnis dieses Programms sieht so aus:

18.4. Animieren¶
Durch Überschreiben der update
-Methode können wir unsere Ballposition aktualisieren und unsere Szene animieren:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | import arcade
class MyGame(arcade.Window):
def __init__(self, width, height, title):
# Call the parent class's init function
super().__init__(width, height, title)
# Set the background color
arcade.set_background_color(arcade.color.ASH_GREY)
# Attributes to store where our ball is
self.ball_x = 50
self.ball_y = 50
def on_draw(self):
""" Called whenever we need to draw the window. """
arcade.start_render()
arcade.draw_circle_filled(self.ball_x, self.ball_y, 15, arcade.color.AUBURN)
def update(self, delta_time):
""" Called to update our objects. Happens approximately 60 times per second."""
self.ball_x += 1
self.ball_y += 1
def main():
window = MyGame(640, 480, "Drawing Example")
arcade.run()
main()
|
18.4.1. Kapselung unseres Animationsobjekts¶
Es braucht nicht viel Vorstellungskraft, um zu begreifen, dass das Hinzufügen weiterer Parameter zum Ball, das Abprallen des Balls oder sogar das Anzeigen mehrerer Bälle auf dem Bildschirm unsere Klasse MyApplication
sehr komplex machen würde.
Wenn es nur eine Möglichkeit gäbe, all das Ball
-Zeug zusammenzufassen. Warte! Es gibt sie! Verwende Klassen!
Hier ist ein komplexeres Beispiel, aber die gesamte Logik für den Ball wurde in eine neue Klasse Ball
verschoben.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | import arcade
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
class Ball:
""" This class manages a ball bouncing on the screen. """
def __init__(self, position_x, position_y, change_x, change_y, radius, color):
""" Constructor. """
# Take the parameters of the init function above, and create instance variables out of them.
self.position_x = position_x
self.position_y = position_y
self.change_x = change_x
self.change_y = change_y
self.radius = radius
self.color = color
def draw(self):
""" Draw the balls with the instance variables we have. """
arcade.draw_circle_filled(self.position_x, self.position_y, self.radius, self.color)
def update(self):
""" Code to control the ball's movement. """
# Move the ball
self.position_y += self.change_y
self.position_x += self.change_x
# See if the ball hit the edge of the screen. If so, change direction
if self.position_x < self.radius:
self.change_x *= -1
if self.position_x > SCREEN_WIDTH - self.radius:
self.change_x *= -1
if self.position_y < self.radius:
self.change_y *= -1
if self.position_y > SCREEN_HEIGHT - self.radius:
self.change_y *= -1
class MyGame(arcade.Window):
""" My window class. """
def __init__(self, width, height, title):
""" Constructor. """
# Call the parent class's init function
super().__init__(width, height, title)
arcade.set_background_color(arcade.color.ASH_GREY)
# Create our ball
self.ball = Ball(50, 50, 3, 3, 15, arcade.color.AUBURN)
def on_draw(self):
""" Called whenever we need to draw the window. """
arcade.start_render()
self.ball.draw()
def update(self, delta_time):
""" Called to update our objects. Happens approximately 60 times per second."""
self.ball.update()
def main():
window = MyGame(640, 480, "Drawing Example")
arcade.run()
main()
|
Hier ist es in Aktion:

18.4.2. Eine Liste animieren¶
Wäre es nicht schön, mehrere Objekte zu animieren? Wie verfolgen wir mehrere Objekte? Mit einer Liste! In diesem Beispiel werden drei Bälle gleichzeitig animiert.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | import arcade
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
class Ball:
""" This class manages a ball bouncing on the screen. """
def __init__(self, position_x, position_y, change_x, change_y, radius, color):
""" Constructor. """
# Take the parameters of the init function above, and create instance variables out of them.
self.position_x = position_x
self.position_y = position_y
self.change_x = change_x
self.change_y = change_y
self.radius = radius
self.color = color
def draw(self):
""" Draw the balls with the instance variables we have. """
arcade.draw_circle_filled(self.position_x, self.position_y, self.radius, self.color)
def update(self):
""" Code to control the ball's movement. """
# Move the ball
self.position_y += self.change_y
self.position_x += self.change_x
# See if the ball hit the edge of the screen. If so, change direction
if self.position_x < self.radius:
self.change_x *= -1
if self.position_x > SCREEN_WIDTH - self.radius:
self.change_x *= -1
if self.position_y < self.radius:
self.change_y *= -1
if self.position_y > SCREEN_HEIGHT - self.radius:
self.change_y *= -1
class MyGame(arcade.Window):
def __init__(self, width, height, title):
# Call the parent class's init function
super().__init__(width, height, title)
arcade.set_background_color(arcade.color.ASH_GREY)
# Create a list for the balls
self.ball_list = []
# Add three balls to the list
ball = Ball(50, 50, 3, 3, 15, arcade.color.AUBURN)
self.ball_list.append(ball)
ball = Ball(100, 150, 2, 3, 15, arcade.color.PURPLE_MOUNTAIN_MAJESTY)
self.ball_list.append(ball)
ball = Ball(150, 250, -3, -1, 15, arcade.color.FOREST_GREEN)
self.ball_list.append(ball)
def on_draw(self):
""" Called whenever we need to draw the window. """
arcade.start_render()
# Use a "for" loop to pull each ball from the list, then call the draw
# method on that ball.
for ball in self.ball_list:
ball.draw()
def update(self, delta_time):
""" Called to update our objects. Happens approximately 60 times per second."""
# Use a "for" loop to pull each ball from the list, then call the update
# method on that ball.
for ball in self.ball_list:
ball.update()
def main():
window = MyGame(640, 480, "Drawing Example")
arcade.run()
main()
|
