Autor: Pete Metcalfe
Chociaż istnieje szereg wieloplatformowych narzędzi programistycznych, często stanowią one wyzwanie dla nowych programistów. Ren'Py [1] to platforma do tworzenia powieści graficznych, która istnieje od ponad 10 lat i ma tę zaletę, że można jej się bardzo łatwo nauczyć, tworząc przy okazji grę bądź aplikację.
Zaletą Ren'Py jest to, że nie potrzebujemy żadnego wcześniejszego doświadczenia w programowaniu. Ren'Py używa prostego „języka ekranowego”, który umożliwia dodawanie tła, obrazów, okien dialogowych znaków i menu. W przypadku bardziej złożonych wymagań możemy wspomagać się kodem w Pythonie.
Zestaw do tworzenia oprogramowania (SDK) Ren'Py działa w systemach Linux, macOS i Windows, natomiast wygenerowane aplikacje można uruchamiać w systemach Android, iOS, Linux, macOS i Windows oraz w przeglądarkach obsługujących HTML5 (Rysunek 1).

Rysunek 1: Platformy obsługiwane przez Ren'Py.
W niniejszym artykule przedstawimy działanie Ren'Py na trzech przykładach. Pierwszy z nich to początek powieści graficznej. Drugi to przewodnik turystyczny z graficznym menu, w ostatnim zaś przykładzie wykorzystamy Pythona do stworzenia panelu administracyjnego wyświetlającego dynamiczne wartości i wykresy.
Pierwsze kroki
Jeśli chcemy poeksperymentować z Ren'Py na Raspberry Pi lub systemie Ubuntu/Debian, możemy zainstalować lekką wersję, pisząc:
sudo apt-get install renpy
Jednak Wersja Ren'Py zainstalowana za pomocą Apta nie ma żadnych samouczków ani dodatkowych funkcji kompilacji, warto więc zainstalować program, korzystając z informacji, które można znaleźć na witrynie projektu [2].
W interfejsie użytkownika Ren'Py możemy utworzyć nowe projekty wraz ze wszystkimi wymaganymi plikami i różnymi opcjami budowania (Rysunek 2). Całą logikę aplikacji zawiera plik tekstowy script.rpy.
Powieść graficzna
Powieść graficzna jest czymś w rodzaju komiksu o wielu ścieżkach fabuły, które czytelnik może wybrać sam. Pierwszym krokiem jest zdefiniowanie postaci i obrazów tła. Tworzenie rysunków postaci od podstaw może być bardzo pracochłonne; na szczęście istnieją darmowe rozwiązania, które mogą nam pomóc.
Jednym z nich jest Character Creator [3]: to strona internetowa, której możesz użyć do wygenerowania męskiej lub żeńskiej głowy, tułowia, a nawet całego ciała. Obsługuje również mimikę twarzy (Rysunek 3). Pliki obrazów postaci i wszystkie obrazy tła są przechowywane w katalogu game/images projektu.
Następnym krokiem jest użycie standardowego edytora tekstu i dodanie kodu języka ekranowego do pliku script.rpy. Na Rysunku 4 i Listingu 1 widzimy kod wymagany do wyświetlenia tła z postacią i dialogiem. Wiersze 3 i 4 definiują dwie postacie: cop (policjant) i me (ja). Definicji tych użyjemy do wyświetlania tekstu dialogu. Ren'Py przeskakuje między segmentami kodu za pomocą etykiet. Cała aplikacja zaczyna się od etykiety start (wiersz 10).

Rysunek 2: Interfejs Ren'Py.

Rysunek 3: Kreator postaci generuje emocje postaci.
Listing 1: Powieść graficzna
01 # darkstreet - script.rpy
02
03 define cop = Character("Cop")
04 define me = Character("Me")
05
06 image darkstreet = im.Scale("darkstreet.jpg",config.screen_width,config.screen_height)
07
08 # Początek gry
09
10 label start:
11
12 # Wyświetlenie tła
13 show darkstreet
14
15 show cop_head at truecenter
16
17 # Wyświetlenie dialogu
18
19 cop "Hej, zatrzymaj się!\n
20 Dlaczego masz krew na rękach?"
21
22 hide cop_head
23 show me_crying_head at truecenter
24
25 me "To nie ja... Nie wiem, co się stało..."
26
27
28 return
Obrazy w katalogu game/images można łatwo wyświetlić za pomocą:
show image_name at position
W tym przykładzie obrazek cop_head.png jest wyświetlany na samym środku ekranu (wiersz 15) za pomocą:
show cop_head at truecenter
Obrazy można również modyfikować, obracać, przesuwać lub dostosowywać. W wierszu 6 tło (darkstreet.jpg) jest dopasowywane do rozmiaru ekranu. Okno dialogowe jest wyświetlane poprzez odwołanie się do postaci, a następnie – tekstu, który ma zostać wyświetlony (wiersze 19–20).

Rysunek 4: Początek powieści graficznej.

Rysunek 5: Druga postać w powieści graficznej.
Rysunek 5 przedstawia kolejną fazę historii. Ukrywamy policjanta za pomocą instrukcji hide (wiersz 22), a zamiast tego wyświetlamy obrazek z płaczącą dziewczyną (me_crying_head) (wiersz 25). Użycie instrukcji hide i show umożliwia prezentację różnych postaci i tła.
Koniec wątku w aplikacji kończy się instrukcją return (wiersz 28).
Przewodnik turystyczny
Większość aplikacji i gier wymaga menu, które umożliwiają wybór różnych opcji, często zagnieżdżonych. Menu Ren'Py tworzy się za pomocą instrukcji menu:. Każda pozycja menu jest zdefiniowana za pomocą tekstu przycisku i instrukcji jump, która jest podobna do starej instrukcji GOTO, którą być może starsi Czytelnicy „Linux Magazine” pamiętają z BASIC-a. Każda instrukcja jump ma odpowiednią etykietę, do której następuje skok.
Rysunek 6 przedstawia początek przewodnika turystycznego po półwyspie Bruce [4]. Na początku programu wywoływane jest menu. Każda pozycja menu przeskakuje do określonej sekcji kodu z etykietą. W podsekcji (np. na plaży) wyświetlane jest nowe tło i tekst. Kiedy użytkownik przeczyta te informacje, instrukcja jump start przeniesie go z powrotem do menu głównego.
W przypadku mniejszych aplikacji (Rysunek 7) podmenu, logikę wyświetlania i kod Pythona można umieścić bezpośrednio w logice menu.
Dynamiczne ekrany
Ren'Py obsługuje niestandardowe układy ekranu, na których mogą znajdować się etykiety, tekst, przyciski i wykresy słupkowe. W powieści graficznej niestandardowy ekran może być małym polem u góry aplikacji, które pokazuje elementy, takie jak zapasy, pieniądze lub procent ukończenia danego etapu czy całej gry.
W następnym przykładzie użyjemy kodu Pythona, aby odczytać dane dotyczące naszego sprzętu i przedstawić je na dużym, niestandardowym ekranie.
Do wyświetlenia aktualnych informacji o sprzęcie najłatwiej jest użyć linuksowego polecenia sensors [5]:
$ sensors
dell_smm-virtual-0
Adapter: Virtual device
Processor Fan: 2721 RPM
CPU: +46.0 C
Ambient: +39.0 C
...
Dodając trochę kodu Basha/Awka, możmy wyodrębnić wartości temperatury procesora i otoczenia:
$ sensors | grep CPU | awk '{ printf "%d\n" , $2}'
46
$ sensors | grep Ambient | awk '{ printf "%d\n" , $2}'
39
Python wywołuje skrypty Basha za pomocą metody subprocess.check_output, która jest częścią biblioteki subprocess (Listing 2).
Listing 3 przedstawia kod aplikacji przedstawiającej statystyki procesora (Rysunek 8). Instrukcja screen cpu_data() tworzy interfejs użytkownika (wiersz 3), który może zawierać zarówno bloki kodu Pythona, jak i wyświetlane elementy.
Blok Pythona (wiersze 5–9) zaczyna się od instrukcji python:, natomiast kolejne wiersze są wcięte zgodnie ze standardem Pythona. Zmienne temperatury procesora i temperatury otoczenia (wiersze 8–9) tworzy się za pomocą wywołania subprocess.check_output() i instrukcji sensors.
Na tym ekranie do grupowania elementów używamy ramki (frame:, wiersz 11). Pojemniki pionowe (vbox:) i poziome (hbox:) wspomagają grupowanie. Zmienne Pythona są umieszczane w napisach wyjściowych za pomocą nawiasów kwadratowych (wiersze 16–18). Poziomy pasek (wiersz 23) pokazuje temperaturę otoczenia (atemp) w zakresie 0–60.
Aplikacja rozpoczyna się od label start: (wiersz 32), wyświetlając ekran cpu_data (wiersz 35). Wbudowana instrukcja pause (wiersz 40) wstrzymuje wykonywanie na dwie sekundy w pętli while. Logika ekranu jest odświeżana po każdej iteracji renpy.pause().

Rysunek 6: Przewodnik turystyczny z menu.

Rysunek 7: Podmenu i logika w opcjach menu.

Rysunek 8: Ekran z danymi dotyczącymi procesora.
Listing 2: Przykład działania subprocess.check_output
$ python
Python 2.7.15+ (default, Oct 7 2019, 17:39:04)
[GCC 7.4.0] on linux2
>>> import subprocess
>>> subprocess.check_output("sensors | grep CPU | awk '{ printf \"%d\" , $2}'", shell=True)
'46'
>>>
>>> subprocess.check_output("sensors | grep Ambient | awk '{ printf \"%d\" , $2}'", shell=True)
'39'
Listing 3: Ekran z dynamicznymi danymi dotyczącymi temperatury procesora
01 # script.rpy - ekran Ren'Py wyświetlający informacje z czujnika procesora
02
03 screen cpu_data():
04
05 python: # pobieramy zmienne czujnika za pomocą Pythona
06 now = datetime.now()
07 nowtime = now.strftime("%H:%M:%S")
08 ctemp = subprocess.check_output("sensors | grep CPU | awk '{ printf \"%d\" , $2}'", shell=True)
09 atemp = subprocess.check_output("sensors | grep Ambient | awk '{ printf \"%d\" , $2}'", shell=True)
10
11 frame: # tworzymy ramkę z tekstem, wartościami i paskiem
12 has vbox
13 label "CPU Stats" text_size 120
14
15 vbox:
16 text "Time : [nowtime]" size 80
17 text "Ambient temp: [atemp] C \n" size 80
18 text " CPU temp : [ctemp] C " size 60
19 hbox:
20 vbox:
21 text "0 " size 40
22 vbox:
23 bar value atemp range 60 xalign 50 yalign 50 xmaximum 600 ymaximum 50 left_bar "#FF0000"
24 vbox:
25 text " 60 " size 40
26
27 init python:
28 # Definiujemy biblioteki i dowolne zmienne systemowe
29 import subprocess
30 from datetime import datetime
31
32 label start:
33
34 # zaczynamy od ekranu z pogodą
35 show screen cpu_data()
36
37 define cycle = "True"
38 # cykl co 2 sekundy
39 while cycle == "True" :
40 $ renpy.pause(2)
41
42 return
Budowanie aplikacji
Ren'Py IDE posiada przycisk Uruchom projekt, który umożliwia testowanie aplikacji w natywnym środowisku systemu operacyjnego. Opcja Build umożliwia tworzenie pakietów dla wielu różnych systemów (Rysunek 9).
Kompilacja HTML5 jest wciąż w fazie beta; wydaje się, że działa dobrze w przypadku standardowych aplikacji, takich jak powieści wizualne, jednak testy pokazały, że ma problemy z niektórymi wywołaniami modułów Pythona. Kompilacja HTML5 tworzy oddzielną strukturę katalogów dla aplikacji Ren'Py, którą należy odwzorować w konfiguracji serwera WWW.

Rysunek 9: Opcje kompilacji Ren'Py.

Rysunek 10: Aplikacja internetowa oparta na Ren'Py.
Jeśli chcemy przeprowadzić proste testy, wystarczy uruchomić samodzielny serwer WWW (Rysunek 10) w katalogu z plikami HTML projektu:
# Uruchamiamy prosty serwer WWW na porcie 8042
python3 -m http.server 8042
Podsumowanie
Jeśli chcemy stworzyć proste, wieloplatformowe aplikacje do prezentacji wizualnych, Ren'Py jest całkiem przyzwoitym rozwiązaniem: aplikacje tworzy się w prosty i intuicyjny sposób. Zauważyliśmy jedynie, że pierwsze uruchomienie na Androidzie trwało dłużej, niż można by oczekiwać, jednak efekt był zadowalający.
Ren'Py sprawdzi się w zastosowaniach, w których wystarczą nam dynamiczne paski i tekst. Jeśli jednak potrzebujemy dodać do interfejsu bardziej zaawansowane komponenty, takie jak np. różnego rodzaju wykresy, prawdopodobniej lepiej będzie użyć innego rozwiązania.
Info
[1] Ren'Py: https://www.renpy.org
[2] Najnowsza wersja Ren'Py: https://www.renpy.org/latest.html
[3] Character Creator: https://charactercreator.org
[4] Półwysep Bruce w Ontario: https://visitbrucepeninsula.ca
[5] Dokumentacja do lm_sensors (sensors): https://wiki.archlinux.org/title/lm_sensors