21. Sprites und Kollisionen

Unsere Spiele benötigen Unterstützung beim Umgang mit kollidierenden Objekten: Bälle, die von Schlägern abprallen, Laserstrahlen, die Aliens treffen, oder unser Lieblingscharakter, der eine Münze sammelt. Alle diese Beispiele erfordern eine Kollisionserkennung.

Die Arcade-Bibliothek unterstützt Sprites. Ein Sprite ist ein zweidimensionales Bild, das Teil der größeren grafischen Szene ist. In der Regel ist ein Sprite ein Objekt in der Szene, mit dem man wie mit einem Auto, einem Frosch oder einem kleinen Klempner interagiert.

../../_images/sprite.png

Ursprünglich verfügten Videospielkonsolen über integrierte Hardware-Unterstützung für Sprites. Jetzt wird diese spezielle Hardwareunterstützung nicht mehr benötigt, aber wir verwenden immer noch den Begriff „Sprite“. Die Geschichte der Sprites ist interessant, wenn Sie mehr darüber erfahren möchten.

21.1. Finden von Bildern für Sprites

Es gibt verschiedene Bildformate, die Computer verwenden:

  • .bmp - Bitmap. Dies ist ein unkomprimiertes Bild, das normalerweise drei Bytes verwendet, um jeden Punkt im Bild darzustellen. Diese Dateien können sehr groß sein. Da es so viele bessere Möglichkeiten gibt, wird dieses Format nicht oft verwendet. Es ist jedoch das am einfachsten zu verwendende Format.

  • .png - Tolles patentfreies Format für Strichzeichnungen und Cliparts. Nicht so toll für Fotos. Kann keine Animationen enthalten.

  • .gif - Tolles Format für Strichzeichnungen und Cliparts. Hat Probleme mit Patenten gehabt (jetzt abgelaufen). Kann Animationen enthalten.

  • .jpg - Tolles Dateiformat für Fotos. Fürchterlich für Clip-Art. Nicht für Sprites verwenden.

  • .svg - Dateiformat zum Speichern von Vektorgrafiken, die auf jede Auflösung skaliert werden können. Nicht kompatibel mit der „Arcade“-Bibliothek.

Wenn du Googles „Erweiterte Bildsuche“ (advanced image search) verwendest, kannst du Bilder in „Symbolgröße“ und im PNG- oder GIF-Dateiformat finden.

Es gibt auch eine großartige Quelle für Bilder von kenney.nl. Er hat eine Menge kostenloser und billiger Spielebild-Assets. Von dieser Seite kommen die folgenden Bilder, die wir in unseren Beispielen verwenden werden:

../../_images/character.png

character.png

../../_images/coin_01.png

coin_01.png

21.1.1. Speicherort für Bilder

Wo solltest du sie speichern? Wenn du deinen Sprite mit dem folgenden Code lädst, sucht der Rechner im selben Verzeichnis wie deine Python-Datei nach dem Bild character.png. Speichere das Bild an einem anderen Ort und es wird nicht gefunden.

21.1.2. Referenzieren von Bildern

Wenn du dein eigenes Spiel erstellst, das du veröffentlichst, musst du:

  • Deine eigenen Bilder erstellen

  • jemanden einstellen, der deine Bilder erstellt,

  • Bilder mit einer Lizenz kaufen, um sie in deinem eigenen Spiel zu verwenden oder

  • Bilder suchen, die gemeinfrei sind oder für die öffentliche Verwendung lizenziert sind

Wenn du nur ein Spiel für den Kurs erstellst, das nicht öffentlich verwendet wird, hinterlasse kurz vor dem Laden des Bildes einen Kommentar bei der Quelle. Ich werde das gleich zeigen.

Achtung

Gebe nicht „Google“ als Quelle an. Das entspricht „In der Bibliothek“ als Quelle in einer Hausarbeit. Suche die Quelle des Bildes, auf das Google verweist.

21.2. Grundlegende Sprites und Kollisionen

Lass uns ein Beispielprogramm durchgehen, das Sprites verwendet. In diesem Beispiel wird gezeigt, wie man einen Bildschirm mit Sprites, die Münzen darstellen, erstellt und diese mithilfe eines Sprites sammeln, bei dem es sich um ein mit der Maus gesteuertes handelt (siehe Abbildung unten). Das Programm gibt an, wie viele Münzen gesammelt wurden. Der Code für dieses Beispiel befindet sich unter:

http://arcade.academy/examples/sprite_collect_coins.html

In diesem Kapitel werden wir dieses Beispiel durchgehen.

../../_images/collect_coins.gif

Beispiel-Sprite-Spiel

21.2.1. Rahmen für die Anwendung

Die ersten paar Zeilen unseres Programms fangen an wie andere Spiele, die wir implementiert haben. Wir importieren einige Bibliotheken. Stellen ein paar Konstanten für die Größe des Bildschirms und ein paar neue Konstanten, mit denen wir unsere Grafiken skalieren, ein.

Das folgende Beispiel sollte nichts Neues enthalten, es erstellt lediglich ein Fenster und legt eine Hintergrundfarbe fest. Wir werden in Kürze die neuen Sachen hinzufügen.

Anfang des Sprite-Beispiels
 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
""" Sprite Sample Program """

import random
import arcade

# --- Constants ---
SPRITE_SCALING_PLAYER = 0.5
SPRITE_SCALING_COIN = 0.2
COIN_COUNT = 50

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600


class MyGame(arcade.Window):
    """ Our custom Window Class"""

    def __init__(self):
        """ Initializer """
        # Call the parent class initializer
        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprite Example")

    def on_draw(self):
        arcade.start_render()


def main():
    """ Main method """
    window = MyGame()
    arcade.run()


if __name__ == "__main__":
    main()

21.2.2. Der Konstruktor

Was kommt als nächstes? Wir müssen unsere Attribute zu der Klasse MyGame hinzufügen. Wir fügen unsere Attribute zu der Methode __init__ hinzu. Hier ist unser Code mit dem erweiterten __init__:

Erweitertes __init__
 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
""" Sprite Sample Program """

import random
import arcade

# --- Constants ---
SPRITE_SCALING_PLAYER = 0.5
SPRITE_SCALING_COIN = 0.2
COIN_COUNT = 50

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600


class MyGame(arcade.Window):
    """ Our custom Window Class"""

    def __init__(self):
        """ Initializer """
        # Call the parent class initializer
        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprite Example")

        # Variables that will hold sprite lists.
        self.player_list = None
        self.coin_list = None

        # Set up the player info
        self.player_sprite = None
        self.score = 0

        # Don't show the mouse cursor
        self.set_mouse_visible(False)

        arcade.set_background_color(arcade.color.AMAZON)

    def on_draw(self):
        arcade.start_render()


def main():
    """ Main method """
    window = MyGame()
    arcade.run()


if __name__ == "__main__":
    main()

Die Variablen, die wir erstellen:

  • player_list: Bei der Arbeit mit Sprites werden diese normalerweise in Listen abgelegt. Andere Spiele-Engines nennen diese Listen Sprite-Gruppen oder Sprite-Ebenen. Unser Spiel hat eine Liste für die Spielfigur und eine Liste für die Münzen. Auch wenn es nur ein Sprite gibt, sollten wir es dennoch in eine Liste aufnehmen, da SpriteList viel Code enthält, um das Zeichnen zu optimieren.

  • coin_list: Dies ist eine Liste aller Münzen. Wir werden prüfen, ob die Spielfigur ein Sprite in dieser Liste berührt.

  • player_sprite: Dies zeigt auf das Sprite unserer Spielfigur. Es ist das Sprite, das wir bewegen werden.

  • score: Dies zeichnet unsere Punktzahl auf.

Wir verwenden die Methode set_mouse_visible der Elternklasse Window, um die Maus unsichtbar zu machen. Zuletzt stellen wir die Hintergrundfarbe ein.

21.2.3. Die setup-Funktion

Als nächstes erstellen wir eine setup-Methode. Dadurch werden unsere Sprites erstellt und unser Spiel eingerichtet. Wir machen das in einer anderen Methode als __init__, so dass wir, wenn wir das Spiel jemals neu starten wollen, einfach setup erneut aufrufen können.

Die Methode setup wird nicht automatisch aufgerufen. Beachte daher, dass wir im folgenden Beispiel den Code hinzugefügt haben, der die Funktion setup gegen Ende aufruft: window.setup ().

Sprite-Beispiel mit Spielfigur
 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
""" Sprite Sample Program """

import random
import arcade

# --- Constants ---
SPRITE_SCALING_PLAYER = 0.5
SPRITE_SCALING_COIN = 0.2
COIN_COUNT = 50

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600


class MyGame(arcade.Window):
    """ Our custom Window Class"""

    def __init__(self):
        """ Initializer """
        # Call the parent class initializer
        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprite Example")

        # Variables that will hold sprite lists
        self.player_list = None
        self.coin_list = None

        # Set up the player info
        self.player_sprite = None
        self.score = 0

        # Don't show the mouse cursor
        self.set_mouse_visible(False)

        arcade.set_background_color(arcade.color.AMAZON)

    def setup(self):
        """ Set up the game and initialize the variables. """

        # Sprite lists
        self.player_list = arcade.SpriteList()
        self.coin_list = arcade.SpriteList()

        # Score
        self.score = 0

        # Set up the player
        # Character image from kenney.nl
        self.player_sprite = arcade.Sprite("character.png", SPRITE_SCALING_PLAYER)
        self.player_sprite.center_x = 50
        self.player_sprite.center_y = 50
        self.player_list.append(self.player_sprite)

    def on_draw(self):
        arcade.start_render()

        # Draw the sprite lists here. Typically sprites are divided into
        # different groups. Other game engines might call these "sprite layers"
        # or "sprite groups." Sprites that don't move should be drawn in their
        # own group for the best performance, as Arcade can tell the graphics
        # card to just redraw them at the same spot.
        # Try to avoid drawing sprites on their own, use a SpriteList
        # because there are many performance improvements in that code.
        self.coin_list.draw()
        self.player_list.draw()


def main():
    """ Main method """
    window = MyGame()
    window.setup()
    arcade.run()


if __name__ == "__main__":
    main()

Wie funktioniert der Code oben?

Zuerst brauchen wir einige Listen, um unsere Sprites aufzunehmen. Wir könnten eine Liste wie diese verwenden:

coin_list = []

Aber warte! coin_list ist eine Objektvariable, die Teil unserer Klasse ist. Wir müssen self. voranstellen.

self.coin_list = []

Die Arcade-Bibliothek verfügt jedoch über eine Klasse, die speziell für den Umgang mit Sprite-Listen vorgesehen ist. Diese Klasse heißt SpriteList. Weitere Informationen findest du in der SpriteList-Dokumentation. Anstatt also eine leere Liste mit [] zu erstellen, erstellen wir ein neues Exemplar der Klasse SpriteList:

self.coin_list = SpriteList()

Nur, dass das nicht funktioniert. Warum? SpriteList befindet sich in der Arcade-Bibliothek. Wir müssen natürlich vor alle Verweise auf Dinge in der Arcade-Bibliothek arcade. schreiben, also haben wir jetzt:

self.coin_list = arcade.SpriteList()

Wir brauchen eine separate Liste nur für Münzen. Diese Liste wird die Spielfigur nicht enthalten. Wir müssen auch unsere Punktzahl auf 0 zurücksetzen.

self.coin_list = arcade.SpriteList()

self.score = 0

Jetzt müssen wir unsere Sprites erstellen. Der Name der Klasse, die Sprites repräsentiert, heißt Sprite. Weitere Informationen finden Sie in der Sprite-Dokumentation. Der Sprite-Konstruktor akzeptiert zwei Parameter: Ein Pfad zu dem Bild, das wir verwenden werden, und wie groß es skaliert werden soll.

Gebe bitte die Quelle des Bilds direkt vor dem Laden an. Wenn du ein eigenes Bild gezeichnet hast, gib dies bitte ebenfalls an.

# Character image from kenney.nl
self.player_sprite = arcade.Sprite("character.png", SPRITE_SCALING_PLAYER)

Wie zeichnen wir alle unsere Sprites? Wirklich einfach. Rufe einfach die Methode draw auf, die für uns in der Klasse SpriteList existiert. Wir müssen dies nur für jede unserer Sprite-Listen tun.

def on_draw(self):

        arcade.start_render()

        # Draw all the sprite lists.
        self.coin_list.draw()
        self.player_list.draw()

Warte! Wir haben nicht viele Sprites. Es gibt keine Münzen und wir haben nur die Spielfigur. Fügen wir unserem Programm eine for-Schleife hinzu und erstellen einige Münzen:

Sprite-Beispiel mit Spieler und Münzen
 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
""" Sprite Sample Program """

import random
import arcade

# --- Constants ---
SPRITE_SCALING_PLAYER = 0.5
SPRITE_SCALING_COIN = 0.2
COIN_COUNT = 50

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600


class MyGame(arcade.Window):
    """ Our custom Window Class"""

    def __init__(self):
        """ Initializer """
        # Call the parent class initializer
        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprite Example")

        # Variables that will hold sprite lists
        self.coin_list = None
        self.player_list = None

        # Set up the player info
        self.player_sprite = None
        self.score = 0

        # Don't show the mouse cursor
        self.set_mouse_visible(False)

        arcade.set_background_color(arcade.color.AMAZON)

    def setup(self):
        """ Set up the game and initialize the variables. """

        # Sprite lists
        self.player_list = arcade.SpriteList()
        self.coin_list = arcade.SpriteList()

        # Score
        self.score = 0

        # Set up the player
        # Character image from kenney.nl
        self.player_sprite = arcade.Sprite("character.png", SPRITE_SCALING_PLAYER)
        self.player_sprite.center_x = 50
        self.player_sprite.center_y = 50
        self.player_list.append(self.player_sprite)

        # Create the coins
        for i in range(COIN_COUNT):

            # Create the coin instance
            # Coin image from kenney.nl
            coin = arcade.Sprite("coin_01.png", SPRITE_SCALING_COIN)

            # Position the coin
            coin.center_x = random.randrange(SCREEN_WIDTH)
            coin.center_y = random.randrange(SCREEN_HEIGHT)

            # Add the coin to the lists
            self.coin_list.append(coin)

    def on_draw(self):
        """ Draw everything """
        arcade.start_render()

        # Draw the sprite lists here. Typically sprites are divided into
        # different groups. Other game engines might call these "sprite layers"
        # or "sprite groups." Sprites that don't move should be drawn in their
        # own group for the best performance, as Arcade can tell the graphics
        # card to just redraw them at the same spot.
        # Try to avoid drawing sprites on their own, and not in a layer.
        # There are many performance improvements to drawing in a layer.
        self.coin_list.draw()
        self.player_list.draw()


def main():
    """ Main method """
    window = MyGame()
    window.setup()
    arcade.run()


if __name__ == "__main__":
    main()

21.2.4. Zeichnen des Spielstands

Lass uns nicht nur die Sprites zeichnen, sondern auch den Spielstand auf dem Bildschirm anzeigen:

# Put the text on the screen.
output = "Score: " + str(self.score)
arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14)

Anstatt mit `` „Score:“ + str (self.score) `` den Spielstand auszugeben ist es möglich die Ausgabe zu formatieren, wenn Sie Python 3.6 oder höher verwenden. Wir werden später mehr über die Formatierung von Ausgaben sprechen, aber dieser Code würde so aussehen:

# Put the text on the screen.
output = f"Score: {self.score}"
arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14)

Es gibt drei Standards zum Formatieren von Zeichenfolgen in Python, sodass das gesamte Thema etwas verwirrend ist.

21.2.5. Die on_mouse_motion-Methode

Das Bewegen des Spielfigur-Sprites mit der Maus ist einfach. Alle Sprites haben Objektvariablen center_x und center_y. Ändere diese Werte einfach in die X- und Y-Position der Maus, um das Sprite zu verschieben.

def on_mouse_motion(self, x, y, dx, dy):

    self.player_sprite.center_x = x
    self.player_sprite.center_y = y

Jetzt sieht unser gesamtes Programm so aus:

Sprite-Beispiel mit Mausbewegung und Spielstand
 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
92
93
""" Sprite Sample Program """

import random
import arcade

# --- Constants ---
SPRITE_SCALING_PLAYER = 0.5
SPRITE_SCALING_COIN = 0.2
COIN_COUNT = 50

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600


class MyGame(arcade.Window):
    """ Our custom Window Class"""

    def __init__(self):
        """ Initializer """
        # Call the parent class initializer
        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprite Example")

        # Variables that will hold sprite lists
        self.player_list = None
        self.coin_list = None

        # Set up the player info
        self.player_sprite = None
        self.score = 0

        # Don't show the mouse cursor
        self.set_mouse_visible(False)

        arcade.set_background_color(arcade.color.AMAZON)

    def setup(self):
        """ Set up the game and initialize the variables. """

        # Sprite lists
        self.player_list = arcade.SpriteList()
        self.coin_list = arcade.SpriteList()

        # Score
        self.score = 0

        # Set up the player
        # Character image from kenney.nl
        self.player_sprite = arcade.Sprite("character.png", SPRITE_SCALING_PLAYER)
        self.player_sprite.center_x = 50
        self.player_sprite.center_y = 50
        self.player_list.append(self.player_sprite)

        # Create the coins
        for i in range(COIN_COUNT):

            # Create the coin instance
            # Coin image from kenney.nl
            coin = arcade.Sprite("coin_01.png", SPRITE_SCALING_COIN)

            # Position the coin
            coin.center_x = random.randrange(SCREEN_WIDTH)
            coin.center_y = random.randrange(SCREEN_HEIGHT)

            # Add the coin to the lists
            self.coin_list.append(coin)

    def on_draw(self):
        """ Draw everything """
        arcade.start_render()
        self.coin_list.draw()
        self.player_list.draw()

        # Put the text on the screen.
        output = f"Score: {self.score}"
        arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14)

    def on_mouse_motion(self, x, y, dx, dy):
        """ Handle Mouse Motion """

        # Move the center of the player sprite to match the mouse x, y
        self.player_sprite.center_x = x
        self.player_sprite.center_y = y


def main():
    """ Main method """
    window = MyGame()
    window.setup()
    arcade.run()


if __name__ == "__main__":
    main()

21.2.6. Die update-Methode

Unsere update-Methode muss drei Dinge tun:

  1. Aktualisieren jedes Sprite

  2. Überprüfen, ob die Spielfigur Münzen berührt

  3. Entfernen aller Münzen, die mit dem Spieler kollidieren, und aktualisieren des Spielstands.

Jedes Sprite hat eine eigene update-Methode. Auf diese Weise können Sprites ihre Abbildung bewegen und animieren. Derzeit verfügt unser Sprite nicht über diese Methode. Aber wir werden sie bald implementieren. Anstatt die update-Methode jedes Sprites, das wir haben, aufzurufen, gibt es in jeder Sprite-Liste eine update-Methode, die update für jedes Sprite in der Liste aufruft. Wenn Sie also update mit unserer coin_list aufrufen, werden alle Münzsprites aktualisiert.

self.coin_list.update()

Wie erkennen wir, welche Münzen die Spielfigur berührt? Wir nennen die Methode check_for_collision_with_list. Ruf sie mit unserer Spielfigur und mit einer Liste aller Münzen auf. Diese Funktion gibt eine Liste aller kollidierenden Sprites zurück. Wenn keine Sprites kollidieren, ist die Liste leer.

# Generate a list of all sprites that collided with the player.
coins_hit_list = arcade.check_for_collision_with_list(self.player_sprite, self.coin_list)

Was machen wir mit dieser hit_list, die wir zurückbekommen? Wir iterieren durch sie. Für jeden Sprite-Treffer wird der Spielstand um eine Münze erhöht.

We also need to get rid of the sprite. The sprite class has a method called remove_from_sprite_lists. This method will remove the sprite from existence.

# Loop through each colliding sprite, remove it, and add to the score.
for coin in coins_hit_list:
    coin.remove_from_sprite_lists()
    self.score += 1

Hier ist die gesamte update-Methode zusammengefasst:

Sprite-Beispiel mit update-Methode
  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
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
""" Sprite Sample Program """

import random
import arcade

# --- Constants ---
SPRITE_SCALING_PLAYER = 0.5
SPRITE_SCALING_COIN = 0.2
COIN_COUNT = 50

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600


class MyGame(arcade.Window):
    """ Our custom Window Class"""

    def __init__(self):
        """ Initializer """
        # Call the parent class initializer
        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprite Example")

        # Variables that will hold sprite lists
        self.player_list = None
        self.coin_list = None

        # Set up the player info
        self.player_sprite = None
        self.score = 0

        # Don't show the mouse cursor
        self.set_mouse_visible(False)

        arcade.set_background_color(arcade.color.AMAZON)

    def setup(self):
        """ Set up the game and initialize the variables. """

        # Sprite lists
        self.player_list = arcade.SpriteList()
        self.coin_list = arcade.SpriteList()

        # Score
        self.score = 0

        # Set up the player
        # Character image from kenney.nl
        self.player_sprite = arcade.Sprite("character.png", SPRITE_SCALING_PLAYER)
        self.player_sprite.center_x = 50
        self.player_sprite.center_y = 50
        self.player_list.append(self.player_sprite)

        # Create the coins
        for i in range(COIN_COUNT):

            # Create the coin instance
            # Coin image from kenney.nl
            coin = arcade.Sprite("coin_01.png", SPRITE_SCALING_COIN)

            # Position the coin
            coin.center_x = random.randrange(SCREEN_WIDTH)
            coin.center_y = random.randrange(SCREEN_HEIGHT)

            # Add the coin to the lists
            self.coin_list.append(coin)

    def on_draw(self):
        """ Draw everything """
        arcade.start_render()
        self.coin_list.draw()
        self.player_list.draw()

        # Put the text on the screen.
        output = f"Score: {self.score}"
        arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14)

    def on_mouse_motion(self, x, y, dx, dy):
        """ Handle Mouse Motion """

        # Move the center of the player sprite to match the mouse x, y
        self.player_sprite.center_x = x
        self.player_sprite.center_y = y

    def update(self, delta_time):
        """ Movement and game logic """

        # Call update on all sprites (The sprites don't do much in this
        # example though.)
        self.coin_list.update()

        # Generate a list of all sprites that collided with the player.
        coins_hit_list = arcade.check_for_collision_with_list(self.player_sprite,
                                                              self.coin_list)

        # Loop through each colliding sprite, remove it, and add to the score.
        for coin in coins_hit_list:
            coin.remove_from_sprite_lists()
            self.score += 1


def main():
    """ Main method """
    window = MyGame()
    window.setup()
    arcade.run()


if __name__ == "__main__":
    main()