""" Dzień 1, krok 1 — pierwsze okno. Cel: zobaczyć, że "klasa" to nic strasznego — to przepis na obiekt, który biblioteka arcade sama za nas uruchomi i sama będzie wołać jego metody. Uruchom: python dzien1/01_okno.py """ import arcade # Stałe piszemy WIELKIMI literami. To zwykłe zmienne globalne — po to, # żeby rozmiar okna zmieniać w jednym miejscu, a nie w pięciu. SZEROKOSC = 800 WYSOKOSC = 600 TYTUL = "Dzień 1 — moje pierwsze okno" # ---------------------------------------------------------------------------- # KLASA = przepis na obiekt. # # Zapis `class MyGame(arcade.Window)` znaczy: "MyGame jest rodzajem # arcade.Window". To DZIEDZICZENIE. Nasza klasa dostaje za darmo wszystko, # co potrafi okno z biblioteki: otwiera się, reaguje na mysz, na klawiaturę, # odświeża się 60 razy na sekundę. My dopisujemy tylko to, co ma być NASZE. # # arcade.Window nazywamy klasą BAZOWĄ (albo rodzicem/nadklasą), # a MyGame — klasą POCHODNĄ (albo dzieckiem/podklasą). # ---------------------------------------------------------------------------- class MyGame(arcade.Window): """Okno naszej gry.""" def __init__(self): """ KONSTRUKTOR — metoda wołana automatycznie w momencie tworzenia obiektu, czyli gdy niżej piszemy `MyGame()`. `self` to sam tworzony obiekt. Każda metoda w klasie dostaje go jako pierwszy argument — dzięki temu wie, na czyich danych pracuje. W wywołaniu `self` się NIE podaje: piszemy `okno.on_draw()`, a Python sam podstawia `okno` pod `self`. """ # super() to "mój rodzic", czyli arcade.Window. # Tu mówimy: "rodzicu, wykonaj swój konstruktor z takimi parametrami". # Bez tej linii okno w ogóle by się nie utworzyło — to rodzic zna # wszystkie szczegóły otwierania okna w systemie. super().__init__(SZEROKOSC, WYSOKOSC, TYTUL) # Atrybuty obiektu — zmienne, które "żyją" wewnątrz obiektu i są # widoczne we WSZYSTKICH metodach tej klasy (przez self.). # W kodzie proceduralnym trzymalibyśmy je w zmiennych globalnych. self.background_color = arcade.color.DARK_BLUE self.licznik_klatek = 0 def on_draw(self): """ NADPISANIE METODY: arcade.Window ma już metodę on_draw(), ale pustą. Definiując ją u siebie, podmieniamy tamtą wersję na własną. Tej metody NIGDY nie wołamy sami — arcade woła ją za nas przy każdej klatce (~60 razy na sekundę). To jest tzw. odwrócenie sterowania: my nie piszemy pętli głównej, my tylko wypełniamy gotowe miejsca. """ # W arcade 3.x czyścimy ekran przez self.clear(). # (W starych tutorialach do 2.x było arcade.start_render() — to inna # funkcja o zupełnie innym znaczeniu, nie używaj jej tutaj.) self.clear() arcade.draw_text( "Cześć! To jest obiekt klasy MyGame.", x=50, y=WYSOKOSC / 2, color=arcade.color.WHITE, font_size=22, ) arcade.draw_text( f"Klatka nr {self.licznik_klatek}", x=50, y=WYSOKOSC / 2 - 40, color=arcade.color.GOLD, font_size=16, ) # TODO 1: dorysuj koło na środku ekranu. # arcade.draw_circle_filled(środek_x, środek_y, promień, kolor) # np. arcade.draw_circle_filled(SZEROKOSC / 2, 120, 40, arcade.color.RED) # TODO 2: dorysuj prostokąt (np. "podłogę" na dole ekranu). # W arcade 3.x są dwie wygodne wersje: # arcade.draw_lrbt_rectangle_filled(left, right, bottom, top, kolor) # arcade.draw_lbwh_rectangle_filled(left, bottom, width, height, kolor) # Wybierz jedną i narysuj pas o wysokości 40 pikseli przy dolnej krawędzi. def on_update(self, delta_time: float): """ Druga metoda wołana automatycznie ~60 razy na sekundę — tu zmieniamy stan gry (a w on_draw tylko rysujemy to, co już wyliczone). delta_time to czas w sekundach, jaki minął od poprzedniej klatki (zwykle ok. 0.016 s). Przyda się w dniu 2, żeby ruch był równy niezależnie od szybkości komputera. """ self.licznik_klatek += 1 def on_key_press(self, symbol: int, modifiers: int): """Kolejna nadpisana metoda — arcade woła ją po wciśnięciu klawisza.""" if symbol == arcade.key.ESCAPE: self.close() def main(): # TU powstaje obiekt: MyGame() uruchamia __init__ i zwraca gotowe okno. # Zmienna `okno` to jedna konkretna INSTANCJA klasy MyGame. okno = MyGame() # arcade.run() startuje pętlę główną: w kółko woła on_update() i on_draw() # naszego obiektu, aż okno zostanie zamknięte. arcade.run() if __name__ == "__main__": main()