24. Verwenden von Sprites zum Schießen¶
Wie bekommen wir Sprites, die wir schießen können?

Münzen abschießen¶
24.1. Einstieg¶
Kehren wir zunächst zu einem Programm für den Einstieg zurück.
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 110 111 112 | import random
import arcade
SPRITE_SCALING_PLAYER = 0.5
SPRITE_SCALING_COIN = 0.2
SPRITE_SCALING_LASER = 0.8
COIN_COUNT = 50
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
BULLET_SPEED = 5
class MyGame(arcade.Window):
""" Main application class. """
def __init__(self):
""" Initializer """
# Call the parent class initializer
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprites and Bullets Demo")
# 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()
# Set up the player
self.score = 0
# 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 = 70
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)
# Set the background color
arcade.set_background_color(arcade.color.AMAZON)
def on_draw(self):
"""
Render the screen.
"""
# This command has to happen before we start drawing
arcade.start_render()
# Draw all the sprites.
self.coin_list.draw()
self.player_list.draw()
# Render the text
arcade.draw_text(f"Score: {self.score}", 10, 20, arcade.color.WHITE, 14)
def on_mouse_motion(self, x, y, dx, dy):
"""
Called whenever the mouse moves.
"""
self.player_sprite.center_x = x
self.player_sprite.center_y = y
def on_mouse_press(self, x, y, button, modifiers):
"""
Called whenever the mouse button is clicked.
"""
pass
def update(self, delta_time):
""" Movement and game logic """
# Call update on all sprites
self.coin_list.update()
def main():
window = MyGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()
|
Wenn du dieses Programm ausführst, sollte sich die Spielfigur auf dem Bildschirm bewegen und es sollte Münzen geben. Aber sonst passiert noch nicht viel.
Als nächstes brauchen wir ein ‚Schuss‘-Bild:

laserBlue01.png¶
Lade dieses Bild (ursprünglich von Kenney.nl) herunter und vergewissere dich, dass es sich im selben Ordner wie dein Code befindet.
24.2. Die Spielfigur unten behalten¶
Im Moment kann sich die Spielfigur überall auf dem Bildschirm bewegen. Wir wollen das Sprite am unteren Bildschirmrand fixieren.
Entferne dazu einfach die Codezeile, um die Spielfigur auf der y-Achse zu bewegen. Die Spielfigur behält den gleichen y-Wert bei, den wir in der Methode setup
gesetzt haben.
def on_mouse_motion(self, x, y, dx, dy):
"""
Called whenever the mouse moves.
"""
self.player_sprite.center_x = x
# REMOVE THIS LINE: self.player_sprite.center_y = y
24.3. Die Münzen nach oben bewegen¶
Wir wollen, dass sich alle Münzen über der Spielfigur befinden. Wir können also die Startpositionen so einstellen, dass sie einen Startpunkt von 150 anstelle von 0 haben. Dadurch bleiben sie über der Spielfigur.
# 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(150, SCREEN_HEIGHT)
# Add the coin to the lists
self.coin_list.append(coin)
24.4. Liste mit Schüssen einrichten¶
Wir müssen eine Liste erstellen, um die Schüsse/Kugeln zu verwalten. Es gibt vier Stellen, an denen wir diesen bullet_list
Code hinzufügen müssen:
Erstellen der Variable
bullet_list
(Zeile 26)Erstellen eines Exemplar von
SpriteList
(Zeile 44)Zeichnen der Schussliste (Zeile 83)
Aktualisieren der Schussliste (Zeile 105)
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 110 111 112 113 114 115 | import random
import arcade
SPRITE_SCALING_PLAYER = 0.5
SPRITE_SCALING_COIN = 0.2
SPRITE_SCALING_LASER = 0.8
COIN_COUNT = 50
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
BULLET_SPEED = 5
class MyGame(arcade.Window):
""" Main application class. """
def __init__(self):
""" Initializer """
# Call the parent class initializer
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprites and Bullets Demo")
# Variables that will hold sprite lists
self.player_list = None
self.coin_list = None
self.bullet_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()
self.bullet_list = arcade.SpriteList()
# Set up the player
self.score = 0
# 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 = 70
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(150, SCREEN_HEIGHT)
# Add the coin to the lists
self.coin_list.append(coin)
# Set the background color
arcade.set_background_color(arcade.color.AMAZON)
def on_draw(self):
"""
Render the screen.
"""
# This command has to happen before we start drawing
arcade.start_render()
# Draw all the sprites.
self.coin_list.draw()
self.player_list.draw()
self.bullet_list.draw()
# Render the text
arcade.draw_text(f"Score: {self.score}", 10, 20, arcade.color.WHITE, 14)
def on_mouse_motion(self, x, y, dx, dy):
"""
Called whenever the mouse moves.
"""
self.player_sprite.center_x = x
def on_mouse_press(self, x, y, button, modifiers):
"""
Called whenever the mouse button is clicked.
"""
pass
def update(self, delta_time):
""" Movement and game logic """
# Call update on all sprites
self.coin_list.update()
self.bullet_list.update()
def main():
window = MyGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()
|
24.5. Schüsse erstellen¶
Wir müssen Schüsse erstellen, wenn der Benutzer die Maustaste drückt. Wir können eine on_mouse_press
-Methode hinzufügen, um etwas zu tun, wenn der Benutzer die Maustaste drückt:
def on_mouse_press(self, x, y, button, modifiers):
# Create a bullet
bullet = arcade.Sprite("laserBlue01.png", SPRITE_SCALING_LASER)
# Add the bullet to the appropriate list
self.bullet_list.append(bullet)
Dadurch wird ein Schuss erstellt, der Schuss befindet sich jedoch standardmäßig in der unteren linken Ecke. Man kann ihn kaum sehen.
Wir können dem Schuss eine Position zuweisen:
def on_mouse_press(self, x, y, button, modifiers):
# Create a bullet
bullet = arcade.Sprite("laserBlue01.png", SPRITE_SCALING_LASER)
bullet.center_x = x
bullet.center_y = y
# Add the bullet to the appropriate list
self.bullet_list.append(bullet)
Aber das wollen wir auch nicht. Der obige Code platziert den Laser dort, wo wir mit der Maus klicken. Wir wollen, dass der Laser dort ist, wo sich die Spielfigur befindet. Das ist einfach:
def on_mouse_press(self, x, y, button, modifiers):
# Create a bullet
bullet = arcade.Sprite("laserBlue01.png", SPRITE_SCALING_LASER)
bullet.center_x = self.player_sprite.center_x
bullet.center_y = self.player_sprite.center_y
# Add the bullet to the appropriate list
self.bullet_list.append(bullet)
We can even start the bullet a bit ABOVE the player:
def on_mouse_press(self, x, y, button, modifiers):
# Create a bullet
bullet = arcade.Sprite("laserBlue01.png", SPRITE_SCALING_LASER)
bullet.center_x = self.player_sprite.center_x
bullet.center_y = self.player_sprite.center_y + 30
# Add the bullet to the appropriate list
self.bullet_list.append(bullet)
Wir können den Schuss mit der Konstante BULLET_SPEED
nach oben bewegen, die wir oben im Programm auf 5 setzen:
def on_mouse_press(self, x, y, button, modifiers):
# Create a bullet
bullet = arcade.Sprite("laserBlue01.png", SPRITE_SCALING_LASER)
bullet.center_x = self.player_sprite.center_x
bullet.center_y = self.player_sprite.center_y + 30
bullet.change_y = BULLET_SPEED
# Add the bullet to the appropriate list
self.bullet_list.append(bullet)
Wir können den Schuss so drehen, dass er nicht seitwärts gerichtet ist. Verwende dazu das Attribut angle
der Klasse Sprite
:
def on_mouse_press(self, x, y, button, modifiers):
# Create a bullet
bullet = arcade.Sprite("laserBlue01.png", SPRITE_SCALING_LASER)
bullet.center_x = self.player_sprite.center_x
bullet.center_y = self.player_sprite.center_y + 30
bullet.change_y = BULLET_SPEED
bullet.angle = 90
# Add the bullet to the appropriate list
self.bullet_list.append(bullet)
24.6. Schuss-Kollisionen¶
Wie bringen wir die Schüsse dazu, mit den Münzen zusammen zu stoßen? Wir fügen unserer update
-Methode Folgendes hinzu:
# Loop through each bullet
for bullet in self.bullet_list:
# Check this bullet to see if it hit a coin
hit_list = arcade.check_for_collision_with_list(bullet, self.coin_list)
# If it did, get rid of the bullet
if len(hit_list) > 0:
bullet.remove_from_sprite_lists()
# For every coin we hit, add to the score and remove the coin
for coin in hit_list:
coin.remove_from_sprite_lists()
self.score += 1
# If the bullet flies off-screen, remove it.
if bullet.bottom > SCREEN_HEIGHT:
bullet.remove_from_sprite_lists()
Wir iterieren mit einer for
-Schleife über jeden Schuss. Dabei prüfen wir, ob der Schuss eine der Münzen trifft. Wenn ja, werden wir die Münze los. Wir werden in diesem Fall auch den Schuss los.
Wir überprüfen auch, ob der Schuss oben am Bildschirm landet. Wenn das der Fall ist, entfernen wir den Schuss. Dies kann man leicht vergessen. Wenn man es aber vergisst, verlangsamt sich der Rechner, da er Tausende von Schüssen verfolgt, die vor langer Zeit den uns interessierenden Bereich verlassen haben.
Hier ist das vollständige Beispiel:
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 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | import random
import arcade
SPRITE_SCALING_PLAYER = 0.5
SPRITE_SCALING_COIN = 0.2
SPRITE_SCALING_LASER = 0.8
COIN_COUNT = 50
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
BULLET_SPEED = 5
class MyGame(arcade.Window):
""" Main application class. """
def __init__(self):
""" Initializer """
# Call the parent class initializer
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprites and Bullets Demo")
# Variables that will hold sprite lists
self.player_list = None
self.coin_list = None
self.bullet_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()
self.bullet_list = arcade.SpriteList()
# Set up the player
self.score = 0
# 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 = 70
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(120, SCREEN_HEIGHT)
# Add the coin to the lists
self.coin_list.append(coin)
# Set the background color
arcade.set_background_color(arcade.color.AMAZON)
def on_draw(self):
"""
Render the screen.
"""
# This command has to happen before we start drawing
arcade.start_render()
# Draw all the sprites.
self.coin_list.draw()
self.bullet_list.draw()
self.player_list.draw()
# Render the text
arcade.draw_text(f"Score: {self.score}", 10, 20, arcade.color.WHITE, 14)
def on_mouse_motion(self, x, y, dx, dy):
"""
Called whenever the mouse moves.
"""
self.player_sprite.center_x = x
def on_mouse_press(self, x, y, button, modifiers):
"""
Called whenever the mouse button is clicked.
"""
# Create a bullet
bullet = arcade.Sprite("laserBlue01.png", SPRITE_SCALING_LASER)
# The image points to the right, and we want it to point up. So
# rotate it.
bullet.angle = 90
# Position the bullet
bullet.center_x = self.player_sprite.center_x
bullet.bottom = self.player_sprite.top
# Add the bullet to the appropriate lists
self.bullet_list.append(bullet)
def update(self, delta_time):
""" Movement and game logic """
# Call update on all sprites
self.coin_list.update()
self.bullet_list.update()
# Loop through each bullet
for bullet in self.bullet_list:
# Check this bullet to see if it hit a coin
hit_list = arcade.check_for_collision_with_list(bullet, self.coin_list)
# If it did, get rid of the bullet
if len(hit_list) > 0:
bullet.remove_from_sprite_lists()
# For every coin we hit, add to the score and remove the coin
for coin in hit_list:
coin.remove_from_sprite_lists()
self.score += 1
# If the bullet flies off-screen, remove it.
if bullet.bottom > SCREEN_HEIGHT:
bullet.remove_from_sprite_lists()
def main():
window = MyGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()
|
24.7. Andere Beispiele¶
Hier sind einige andere Beispiele aus Arcade Academy und seiner Liste mit Beispielen: