136 lines
4.8 KiB
Python
136 lines
4.8 KiB
Python
"""
|
|
Dzień 1, krok 2 — sprite i sterowanie z klawiatury.
|
|
|
|
Nowe pojęcia:
|
|
* sprite — obiekt gry, który ma pozycję, wygląd i prędkość
|
|
* SpriteList — pojemnik na sprite'y; rysuje i aktualizuje je wszystkie naraz
|
|
* change_x / change_y — prędkość sprite'a (o ile pikseli przesuwa się w klatce)
|
|
|
|
Uruchom:
|
|
python dzien1/02_sprite_ruch.py
|
|
|
|
Sterowanie: strzałki. Wyjście: Esc.
|
|
"""
|
|
|
|
import arcade
|
|
|
|
SZEROKOSC = 800
|
|
WYSOKOSC = 600
|
|
TYTUL = "Dzień 1 — ruch sprite'a"
|
|
|
|
PROMIEN_GRACZA = 25
|
|
PREDKOSC_GRACZA = 5 # w pikselach na klatkę (arcade przelicza to przez delta_time)
|
|
|
|
|
|
class MyGame(arcade.Window):
|
|
"""Okno gry — znowu dziedziczymy po arcade.Window."""
|
|
|
|
def __init__(self):
|
|
super().__init__(SZEROKOSC, WYSOKOSC, TYTUL)
|
|
self.background_color = arcade.color.DARK_SLATE_GRAY
|
|
|
|
# Atrybuty deklarujemy w __init__, nawet jeśli na razie są puste.
|
|
# Dzięki temu z jednego miejsca widać, jakie dane ma obiekt.
|
|
self.player_list = arcade.SpriteList()
|
|
self.player = None
|
|
|
|
self.setup()
|
|
|
|
def setup(self):
|
|
"""
|
|
Metoda pomocnicza — nie jest częścią arcade, sami ją wymyśliliśmy.
|
|
Ustawia grę w stan początkowy. Trzymamy to osobno od __init__, bo
|
|
później (np. po przegranej) będziemy chcieli zrestartować grę bez
|
|
tworzenia nowego okna — wystarczy zawołać setup() jeszcze raz.
|
|
"""
|
|
self.player_list = arcade.SpriteList()
|
|
|
|
# SpriteCircle to gotowy sprite w kształcie koła — klasa z biblioteki.
|
|
# Tworzymy jej instancję: SpriteCircle(promień, kolor).
|
|
self.player = arcade.SpriteCircle(PROMIEN_GRACZA, arcade.color.AMAZON)
|
|
|
|
# center_x / center_y to atrybuty każdego sprite'a — jego pozycja.
|
|
self.player.center_x = SZEROKOSC / 2
|
|
self.player.center_y = WYSOKOSC / 2
|
|
|
|
# Wkładamy sprite'a do listy. Od teraz wystarczy operować na liście.
|
|
self.player_list.append(self.player)
|
|
|
|
def on_draw(self):
|
|
self.clear()
|
|
|
|
# SpriteList sam rysuje wszystkie swoje sprite'y — jedno wywołanie.
|
|
self.player_list.draw()
|
|
|
|
arcade.draw_text(
|
|
"Strzałki — ruch, Esc — wyjście",
|
|
x=10,
|
|
y=10,
|
|
color=arcade.color.WHITE,
|
|
font_size=14,
|
|
)
|
|
|
|
def on_update(self, delta_time: float):
|
|
"""
|
|
UWAGA na API arcade 3.x:
|
|
SpriteList NIE MA metody on_update(). Listę odświeżamy metodą
|
|
update(delta_time), a ona woła update() na każdym sprite'cie.
|
|
|
|
Domyślne Sprite.update() dodaje change_x/change_y do pozycji — czyli
|
|
samo przesuwanie mamy za darmo. W dniu 2 nadpiszemy update() we
|
|
własnej klasie, żeby sprite robił coś więcej.
|
|
"""
|
|
self.player_list.update(delta_time)
|
|
|
|
# TODO 1: nie pozwól graczowi wyjechać poza okno.
|
|
# Każdy sprite ma atrybuty left, right, bottom, top (krawędzie).
|
|
# Przypisanie do nich przesuwa sprite'a, np.:
|
|
# if self.player.left < 0:
|
|
# self.player.left = 0
|
|
# Dopisz analogiczne warunki dla right (> SZEROKOSC),
|
|
# bottom (< 0) i top (> WYSOKOSC).
|
|
|
|
def on_key_press(self, symbol: int, modifiers: int):
|
|
"""
|
|
Wciśnięcie klawisza USTAWIA prędkość — nie przesuwa gracza od razu.
|
|
Samo przesuwanie dzieje się w on_update, klatka po klatce.
|
|
Dzięki temu ruch jest płynny, a nie skokowy.
|
|
"""
|
|
if symbol == arcade.key.LEFT:
|
|
self.player.change_x = -PREDKOSC_GRACZA
|
|
elif symbol == arcade.key.RIGHT:
|
|
self.player.change_x = PREDKOSC_GRACZA
|
|
elif symbol == arcade.key.UP:
|
|
self.player.change_y = PREDKOSC_GRACZA
|
|
elif symbol == arcade.key.DOWN:
|
|
self.player.change_y = -PREDKOSC_GRACZA
|
|
elif symbol == arcade.key.ESCAPE:
|
|
self.close()
|
|
|
|
# TODO 2: dodaj obsługę klawisza SPACE (arcade.key.SPACE).
|
|
# Wymyśl efekt i zapisz go w atrybucie obiektu, np.:
|
|
# - zmiana koloru gracza: self.player.color = arcade.color.RED
|
|
# - "dopalacz": ustaw self.szybki = True i w on_key_press mnóż
|
|
# PREDKOSC_GRACZA razy 2 (pamiętaj o wyłączeniu w on_key_release)
|
|
# - teleport na środek ekranu
|
|
# Ważne: stan trzymamy w self.<coś>, żeby inne metody też go widziały.
|
|
|
|
def on_key_release(self, symbol: int, modifiers: int):
|
|
"""
|
|
Puszczenie klawisza ZERUJE prędkość w danej osi.
|
|
Bez tej metody gracz po jednym naciśnięciu jechałby w nieskończoność.
|
|
"""
|
|
if symbol in (arcade.key.LEFT, arcade.key.RIGHT):
|
|
self.player.change_x = 0
|
|
elif symbol in (arcade.key.UP, arcade.key.DOWN):
|
|
self.player.change_y = 0
|
|
|
|
|
|
def main():
|
|
MyGame()
|
|
arcade.run()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|