25. Sprites und Wände¶
25.1. Konfiguration¶
Viele Spiele mit Sprites haben oft „Wände“, durch die sich die Spielfigur nicht bewegen kann. Sie lassen sich eher unkompliziert erstellen.
Lass uns zunächst mit ein paar Bildern anfangen. Unsere Spielfigur und eine Kiste, die als Sperrmauer fungiert. Beide Bilder stammen von kenney.nl.

images/character.png¶

images/boxCrate_double.png¶
Beginne mit einem Einstiegsprogramm:
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 | """ Sprite Sample Program """
import arcade
# --- Constants ---
SPRITE_SCALING_BOX = 0.5
SPRITE_SCALING_PLAYER = 0.5
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
MOVEMENT_SPEED = 5
class MyGame(arcade.Window):
""" This class represents the main window of the game. """
def __init__(self):
""" Initializer """
# Call the parent class initializer
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprites With Walls Example")
def setup(self):
# Set the background color
arcade.set_background_color(arcade.color.AMAZON)
def on_draw(self):
arcade.start_render()
def main():
window = MyGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()
|
Erstellen wir in der __init__
-Methode einige Attribute für unsere Sprites:
# Sprite lists
self.player_list = None
self.wall_list = None
# Set up the player
self.player_sprite = None
# This variable holds our simple "physics engine"
self.physics_engine = None
In der setup
Methode erstellen wir unsere Sprite-Listen:
# Sprite lists
self.player_list = arcade.SpriteList()
self.wall_list = arcade.SpriteList()
Setze danach die Punktzahl zurück und erstelle die Spielfigur:
# Reset the score
self.score = 0
# Create the player
self.player_sprite = arcade.Sprite("images/character.png", SPRITE_SCALING_PLAYER)
self.player_sprite.center_x = 50
self.player_sprite.center_y = 64
self.player_list.append(self.player_sprite)
Dann zeichne alles in unserer Methode on_draw
:
def on_draw(self):
arcade.start_render()
self.wall_list.draw()
self.player_list.draw()
Führe das Programm aus und stelle sicher, dass es funktioniert.

25.2. Wände individuell platzieren¶
In unserer setup
Methode können wir einzelne Boxen positionieren, die als „Wände“ verwendet werden:
# Manually create and position a box at 300, 200
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = 300
wall.center_y = 200
self.wall_list.append(wall)
# Manually create and position a box at 364, 200
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = 364
wall.center_y = 200
self.wall_list.append(wall)
Probiere es einfach aus. Es sollte so aussehen:

Vollständiges Listing unten:
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 | """ Sprite Sample Program """
import arcade
# --- Constants ---
SPRITE_SCALING_BOX = 0.5
SPRITE_SCALING_PLAYER = 0.5
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
MOVEMENT_SPEED = 5
class MyGame(arcade.Window):
""" This class represents the main window of the game. """
def __init__(self):
""" Initializer """
# Call the parent class initializer
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprite Example")
# Sprite lists
self.player_list = None
self.wall_list = None
# Set up the player
self.player_sprite = None
def setup(self):
# Set the background color
arcade.set_background_color(arcade.color.AMAZON)
# Sprite lists
self.player_list = arcade.SpriteList()
self.wall_list = arcade.SpriteList()
# Reset the score
self.score = 0
# Create the player
self.player_sprite = arcade.Sprite("images/character.png", SPRITE_SCALING_PLAYER)
self.player_sprite.center_x = 50
self.player_sprite.center_y = 64
self.player_list.append(self.player_sprite)
# Manually create and position a box at 300, 200
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = 300
wall.center_y = 200
self.wall_list.append(wall)
# Manually create and position a box at 364, 200
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = 364
wall.center_y = 200
self.wall_list.append(wall)
def on_draw(self):
arcade.start_render()
self.wall_list.draw()
self.player_list.draw()
def main():
""" Main method """
window = MyGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()
|
25.3. Wände mit Hilfe einer Schleife platzieren¶
In unserer setup
-Methode können wir eine Reihe von Box-Sprites mit einer for
-Schleife erstellen. Im folgenden Code ist unser y-Wert immer 350, und wir ändern den x-Wert von 173 in 650. Wir setzen alle 64 Pixel ein Kästchen, da jedes Kästchen 64 Pixel breit ist.
# Place boxes inside a loop
for x in range(173, 650, 64):
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = x
wall.center_y = 350
self.wall_list.append(wall)

25.4. Wände mit einer Liste platzieren¶
Man kann sogar eine Liste mit Koordinaten erstellen und diese Liste dann einfach durchlaufen und Wände erstellen:
# --- Place walls with a list
coordinate_list = [[400, 500],
[470, 500],
[400, 570],
[470, 570]]
# Loop through coordinates
for coordinate in coordinate_list:
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = coordinate[0]
wall.center_y = coordinate[1]
self.wall_list.append(wall)

Vollständiges Listing unten:
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 | """ Sprite Sample Program """
import arcade
# --- Constants ---
SPRITE_SCALING_BOX = 0.5
SPRITE_SCALING_PLAYER = 0.5
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
MOVEMENT_SPEED = 5
class MyGame(arcade.Window):
""" This class represents the main window of the game. """
def __init__(self):
""" Initializer """
# Call the parent class initializer
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprite Example")
# Sprite lists
self.player_list = None
self.wall_list = None
# Set up the player
self.player_sprite = None
def setup(self):
# Set the background color
arcade.set_background_color(arcade.color.AMAZON)
# Sprite lists
self.player_list = arcade.SpriteList()
self.wall_list = arcade.SpriteList()
# Reset the score
self.score = 0
# Create the player
self.player_sprite = arcade.Sprite("images/character.png", SPRITE_SCALING_PLAYER)
self.player_sprite.center_x = 50
self.player_sprite.center_y = 64
self.player_list.append(self.player_sprite)
# --- Manually place walls
# Manually create and position a box at 300, 200
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = 300
wall.center_y = 200
self.wall_list.append(wall)
# Manually create and position a box at 364, 200
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = 364
wall.center_y = 200
self.wall_list.append(wall)
# --- Place boxes inside a loop
for x in range(173, 650, 64):
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = x
wall.center_y = 350
self.wall_list.append(wall)
# --- Place walls with a list
coordinate_list = [[400, 500],
[470, 500],
[400, 570],
[470, 570]]
# Loop through coordinates
for coordinate in coordinate_list:
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = coordinate[0]
wall.center_y = coordinate[1]
self.wall_list.append(wall)
def on_draw(self):
arcade.start_render()
self.player_list.draw()
self.wall_list.draw()
def main():
""" Main method """
window = MyGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()
|
25.5. Physik-Engine¶
Zuerst müssen wir die Tastatur mit der Spielfigur verknüpfen:
def on_key_press(self, key, modifiers):
"""Called whenever a key is pressed. """
if key == arcade.key.UP:
self.player_sprite.change_y = MOVEMENT_SPEED
elif key == arcade.key.DOWN:
self.player_sprite.change_y = -MOVEMENT_SPEED
elif key == arcade.key.LEFT:
self.player_sprite.change_x = -MOVEMENT_SPEED
elif key == arcade.key.RIGHT:
self.player_sprite.change_x = MOVEMENT_SPEED
def on_key_release(self, key, modifiers):
"""Called when the user releases a key. """
if key == arcade.key.UP or key == arcade.key.DOWN:
self.player_sprite.change_y = 0
elif key == arcade.key.LEFT or key == arcade.key.RIGHT:
self.player_sprite.change_x = 0
Jetzt müssen wir eine Möglichkeit hinzufügen, die Spielfigur daran zu hindern, in die Wände hinein zu rennen.
Die Arcade-Bibliothek verfügt über eine integrierte „Physik-Engine“. Eine Physik-Engine verwaltet die Interaktionen zwischen den virtuellen physischen Objekten im Spiel. Zum Beispiel kann eine Physik-Engine aus mehreren Bällen bestehen, die aufeinander treffen, eine Spielfigur, die einen Hügel hinunterrutscht, oder einem Auto, das auf der Straße eine Kurve fährt.
Physik-Engines haben beeindruckende Fortschritte erzielt, was sie simulieren können. Für unser Spiel werden wir die Dinge einfach halten und sicherstellen, dass unsere Spielfigur nicht durch Wände gehen kann.
Wir werden ein Attribut für unsere Physik-Engine in __init__
erstellen:
# This variable holds our simple "physics engine"
self.physics_engine = None
Wir können die eigentliche Physik-Engine in unserer setup
-Methode mit folgendem Code erstellen:
self.physics_engine = arcade.PhysicsEngineSimple(self.player_sprite, self.wall_list)
Dies identifiziert die Spielfigur (player_sprite
) und eine Liste von Sprites (wall_list
), die die Spielfigur nicht passieren darf.
Vorher haben wir alle Sprites mit der Anweisung self.all_sprites_list.update()
aktualisiert. Mit der Physik-Engine aktualisieren wir stattdessen die Sprites mithilfe des update
der Physik-Engine:
def update(self, delta_time):
self.physics_engine.update()
Die einfache Physik-Engine folgt dem folgenden Algorithmus:
Bewege die Spielfigur in x-Richtung entsprechend dem
change_x
-Wert der Spielfigur.Überprüfe mit der Wandliste, ob Kollisionen mit der Spielfigur vorliegen.
Wenn die Spielfigur kollidiert:
Wenn sich die Spielfigur nach rechts bewegt, setze die rechte Kante der Spielfigur auf die linke Kante der Wand.
Wenn sich die Spielfigur nach links bewegt, setze die linke Kante der Spielfigur auf die rechte Kante der Wand.
Wenn sich die Spielfigur nicht nach links oder rechts bewegt, gebe die Nachricht aus, dass wir verwirrt sind, wie wir auf etwas treffen können, wenn wir uns nicht bewegen.
Dann machen wir dasselbe, nur mit den y-Koordinaten.
Du kannst dir den Physics Engine Source Code auf GitHub ansehen.
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 | """ Sprite Sample Program """
import arcade
# --- Constants ---
SPRITE_SCALING_BOX = 0.5
SPRITE_SCALING_PLAYER = 0.5
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
MOVEMENT_SPEED = 5
class MyGame(arcade.Window):
""" This class represents the main window of the game. """
def __init__(self):
""" Initializer """
# Call the parent class initializer
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprite Example")
# Sprite lists
self.player_list = None
self.wall_list = None
# Set up the player
self.player_sprite = None
# This variable holds our simple "physics engine"
self.physics_engine = None
def setup(self):
# Set the background color
arcade.set_background_color(arcade.color.AMAZON)
# Sprite lists
self.player_list = arcade.SpriteList()
self.wall_list = arcade.SpriteList()
# Reset the score
self.score = 0
# Create the player
self.player_sprite = arcade.Sprite("images/character.png", SPRITE_SCALING_PLAYER)
self.player_sprite.center_x = 50
self.player_sprite.center_y = 64
self.player_list.append(self.player_sprite)
# --- Manually place walls
# Manually create and position a box at 300, 200
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = 300
wall.center_y = 200
self.wall_list.append(wall)
# Manually create and position a box at 364, 200
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = 364
wall.center_y = 200
self.wall_list.append(wall)
# --- Place boxes inside a loop
for x in range(173, 650, 64):
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = x
wall.center_y = 350
self.wall_list.append(wall)
# --- Place walls with a list
coordinate_list = [[400, 500],
[470, 500],
[400, 570],
[470, 570]]
# Loop through coordinates
for coordinate in coordinate_list:
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = coordinate[0]
wall.center_y = coordinate[1]
self.wall_list.append(wall)
# Create the physics engine. Give it a reference to the player, and
# the walls we can't run into.
self.physics_engine = arcade.PhysicsEngineSimple(self.player_sprite, self.wall_list)
def on_draw(self):
arcade.start_render()
self.wall_list.draw()
self.player_list.draw()
def update(self, delta_time):
self.physics_engine.update()
def on_key_press(self, key, modifiers):
"""Called whenever a key is pressed. """
if key == arcade.key.UP:
self.player_sprite.change_y = MOVEMENT_SPEED
elif key == arcade.key.DOWN:
self.player_sprite.change_y = -MOVEMENT_SPEED
elif key == arcade.key.LEFT:
self.player_sprite.change_x = -MOVEMENT_SPEED
elif key == arcade.key.RIGHT:
self.player_sprite.change_x = MOVEMENT_SPEED
def on_key_release(self, key, modifiers):
"""Called when the user releases a key. """
if key == arcade.key.UP or key == arcade.key.DOWN:
self.player_sprite.change_y = 0
elif key == arcade.key.LEFT or key == arcade.key.RIGHT:
self.player_sprite.change_x = 0
def main():
""" Main method """
window = MyGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()
|
25.6. Verwenden eines Bildausschnitts zum Scrollen¶
Was ist, wenn ein Bildschirm nicht ausreicht, um Ihr Wandlabyrinth zu enthalten? Wir können eine Welt erstellen, die größer ist als nur unser Fenster. Wir tun dies, indem wir den View Port (Bildausschnitt) anpassen. Normalerweise ist die Koordinate (0, 0) die untere linke Ecke unseres Bildschirms. Das können wir ändern! Wir könnten eine ganze Welt von (0, 0) bis (3000, 3000) haben und einen kleineren Ausschnitt von 800 x 640, in dem wir herum scrollen.
Der Befehl zur Verwendung des Bildausschnitts lautet set_viewport
. Dieser Befehl benötigt vier Argumente. Die ersten beiden sind die linken und unteren Grenzen des Fensters. Standardmäßig sind diese Null. Aus diesem Grund befindet sich (0, 0) unten links auf dem Bildschirm. Die nächsten beiden Befehle sind die oberen und rechten Koordinaten des Bildschirms. Standardmäßig sind dies die Bildschirmbreite und -höhe minus eins. Ein 800 Pixel breites Fenster hätte also x-Koordinaten von 0 bis 799.
Eine Anweisung wie die folgende verschiebt die gesamte „Ansicht“ des Fensters um 200 Pixel nach rechts:
# Specify viewport size by (left, right, bottom, top)
arcade.set_viewport(200, 200 + SCREEN_WIDTH - 1, 0, SCREEN_HEIGHT - 1)
Bei einem 800 Pixel breiten Fenster würden wir also die x-Koordinaten 200 - 999 anstelle von 0 - 799 anzeigen.
Anstatt die Verschiebung um 200 Pixel fest zu codieren, müssen wir eine Variable verwenden und Regeln festlegen, wann die Ansicht verschoben werden soll. In unserem nächsten Beispiel erstellen wir zwei neue Objektvariablen in unserer Anwendungsklasse, die die linken und unteren Koordinaten für unseren Bildausschnitt enthalten. Wir werden sie standardmäßig auf Null setzen.
self.view_left = 0
self.view_bottom = 0
We are also going to create two new constants. We don’t want the player to reach the edge of the screen before we start scrolling. Because then the player would have no idea where she is going. In our example we will set a „margin“ of 150 pixels. When the player is 150 pixels from the edge of the screen, we’ll move the view port so she can see at least 150 pixels around her.
VIEWPORT_MARGIN = 150
Als nächstes müssen wir in unserer update
-Methode sehen, ob der Benutzer zu nahe am Bildschirmrand ist, und wir müssen die Grenzen aktualisieren.
# Keep track of if we changed the boundary. We don't want to call the
# set_viewport command if we didn't change the view port.
changed = False
# Scroll left
left_boundary = self.view_left + VIEWPORT_MARGIN
if self.player_sprite.left < left_boundary:
self.view_left -= left_boundary - self.player_sprite.left
changed = True
# Scroll right
right_boundary = self.view_left + SCREEN_WIDTH - VIEWPORT_MARGIN
if self.player_sprite.right > right_boundary:
self.view_left += self.player_sprite.right - right_boundary
changed = True
# Scroll up
top_boundary = self.view_bottom + SCREEN_HEIGHT - VIEWPORT_MARGIN
if self.player_sprite.top > top_boundary:
self.view_bottom += self.player_sprite.top - top_boundary
changed = True
# Scroll down
bottom_boundary = self.view_bottom + VIEWPORT_MARGIN
if self.player_sprite.bottom < bottom_boundary:
self.view_bottom -= bottom_boundary - self.player_sprite.bottom
changed = True
# Make sure our boundaries are integer values. While the view port does
# support floating point numbers, for this application we want every pixel
# in the view port to map directly onto a pixel on the screen. We don't want
# any rounding errors.
self.view_left = int(self.view_left)
self.view_bottom = int(self.view_bottom)
# If we changed the boundary values, update the view port to match
if changed:
arcade.set_viewport(self.view_left,
SCREEN_WIDTH + self.view_left - 1,
self.view_bottom,
SCREEN_HEIGHT + self.view_bottom - 1)
Das vollständige Beispiel findest du unten:
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 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | """ Sprite Sample Program """
import arcade
# --- Constants ---
SPRITE_SCALING_BOX = 0.5
SPRITE_SCALING_PLAYER = 0.5
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
MOVEMENT_SPEED = 5
VIEWPORT_MARGIN = 150
class MyGame(arcade.Window):
""" This class represents the main window of the game. """
def __init__(self):
""" Initializer """
# Call the parent class initializer
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprite Example")
# Sprite lists
self.player_list = None
self.wall_list = None
# Set up the player
self.player_sprite = None
# This variable holds our simple "physics engine"
self.physics_engine = None
# Manage the view port
self.view_left = 0
self.view_bottom = 0
def setup(self):
# Set the background color
arcade.set_background_color(arcade.color.AMAZON)
# Reset the view port
self.view_left = 0
self.view_bottom = 0
# Sprite lists
self.player_list = arcade.SpriteList()
self.wall_list = arcade.SpriteList()
# Reset the score
self.score = 0
# Create the player
self.player_sprite = arcade.Sprite("images/character.png", SPRITE_SCALING_PLAYER)
self.player_sprite.center_x = 50
self.player_sprite.center_y = 64
self.player_list.append(self.player_sprite)
# --- Manually place walls
# Manually create and position a box at 300, 200
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = 300
wall.center_y = 200
self.wall_list.append(wall)
# Manually create and position a box at 364, 200
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = 364
wall.center_y = 200
self.wall_list.append(wall)
# --- Place boxes inside a loop
for x in range(173, 650, 64):
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = x
wall.center_y = 350
self.wall_list.append(wall)
# --- Place walls with a list
coordinate_list = [[400, 500],
[470, 500],
[400, 570],
[470, 570]]
# Loop through coordinates
for coordinate in coordinate_list:
wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING_BOX)
wall.center_x = coordinate[0]
wall.center_y = coordinate[1]
self.wall_list.append(wall)
# Create the physics engine. Give it a reference to the player, and
# the walls we can't run into.
self.physics_engine = arcade.PhysicsEngineSimple(self.player_sprite, self.wall_list)
def on_draw(self):
arcade.start_render()
self.wall_list.draw()
self.player_list.draw()
def update(self, delta_time):
self.physics_engine.update()
# --- Manage Scrolling ---
# Keep track of if we changed the boundary. We don't want to call the
# set_viewport command if we didn't change the view port.
changed = False
# Scroll left
left_boundary = self.view_left + VIEWPORT_MARGIN
if self.player_sprite.left < left_boundary:
self.view_left -= left_boundary - self.player_sprite.left
changed = True
# Scroll right
right_boundary = self.view_left + SCREEN_WIDTH - VIEWPORT_MARGIN
if self.player_sprite.right > right_boundary:
self.view_left += self.player_sprite.right - right_boundary
changed = True
# Scroll up
top_boundary = self.view_bottom + SCREEN_HEIGHT - VIEWPORT_MARGIN
if self.player_sprite.top > top_boundary:
self.view_bottom += self.player_sprite.top - top_boundary
changed = True
# Scroll down
bottom_boundary = self.view_bottom + VIEWPORT_MARGIN
if self.player_sprite.bottom < bottom_boundary:
self.view_bottom -= bottom_boundary - self.player_sprite.bottom
changed = True
# Make sure our boundaries are integer values. While the view port does
# support floating point numbers, for this application we want every pixel
# in the view port to map directly onto a pixel on the screen. We don't want
# any rounding errors.
self.view_left = int(self.view_left)
self.view_bottom = int(self.view_bottom)
# If we changed the boundary values, update the view port to match
if changed:
arcade.set_viewport(self.view_left,
SCREEN_WIDTH + self.view_left - 1,
self.view_bottom,
SCREEN_HEIGHT + self.view_bottom - 1)
def on_key_press(self, key, modifiers):
""" Called whenever a key is pressed. """
if key == arcade.key.UP:
self.player_sprite.change_y = MOVEMENT_SPEED
elif key == arcade.key.DOWN:
self.player_sprite.change_y = -MOVEMENT_SPEED
elif key == arcade.key.LEFT:
self.player_sprite.change_x = -MOVEMENT_SPEED
elif key == arcade.key.RIGHT:
self.player_sprite.change_x = MOVEMENT_SPEED
def on_key_release(self, key, modifiers):
"""Called when the user releases a key. """
if key == arcade.key.UP or key == arcade.key.DOWN:
self.player_sprite.change_y = 0
elif key == arcade.key.LEFT or key == arcade.key.RIGHT:
self.player_sprite.change_x = 0
def main():
""" Main method """
window = MyGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()
|