W tym krótkim poście opiszę jakich technologii korzystam przy Avocado i co zmotywowało mnie do ich użycia.
Język
Zdecydowałem się na użycie C++ z kilku powodów:
- Jest to język z którym mam najwięcej doświadczenia i wydaje mi się że pozwoli mi to na najszybszą zmianę pomysłu w działający kod. Myślałem nad wyborem jednej z nowszych alternatyw, m. in. Go albo Rust, ale obawiałem się że więcej czasu spędziłbym nad szukaniem rozwiązań do problemów, które w C++ są dla mnie oczywiste i spotkałem się z nimi przy poprzednich projektach (AnotherNES) niż nad pisaniem właściwego kodu.
- Duża ilość bibliotek - nie muszę martwić się o to, że biblioteka do obsługi danej funkcjonalności nie jest przeportowana lub zawiera błędy uniemożliwiające mi pracę nad projektem. W przypadku gdy nie będę chciał wynajdować koła od nowa mogę sięgnąć po gotowe rouzwiązanie.
- Wieloplatformowość - ten sam kod po niewielkich zmianach mogę skompilować na Linuksie, OS X, Androidzie, Raspberry Pi czy nawet do JavaScriptu (co pokazałem na moim poprzednim projekcie). C/C++ to chyba jedyne języki które mogę uruchomić na dowolnej architekturze nie tracąc na wydajności.
- Natywność - emulacja to taka dziedzina gdzie niskopoziomowość przy zarządzaniu pamięcią i procesorem jest koniecznością, a mechanizmy takie jak GC czy brak dostępu do surowej pamięci działa wyłącznie na naszą niekorzyść - dlatego odrzuciłem języki interpretowane i kompilowane w locie. Zostaje więc jedynie C, C++ i nowy Rust.
- Narzędzia - Visual Studio to jedno z najlepszych środowisk jakie miałem przyjemność używać (do póki nie poznałem środowisk firmy JetBrains). Szczególnie dopracowanym jest narzędziem jest tutaj debugger, z którym spędzam dużo czasu i bardzo usprawnia pracę. Poza światem Windowsa mamy LLVM + szereg narzędzi służących do analizy statycznej kodu, automatycznego formatowania składni czy badania programu pod kątem wycieków pamięci i innych popularnych błędów.
Biblioteki
SDL2 - używałem jej wiele razy, znam jej wady i zalety. Wersja 2.0 przyniosła wiele usprawnień jak obsługa wielu okien, sprzętowe renderowanie obrazu, unifikacja kontrolerów do gier (zmapowanie dowolnego kontrolera na schemat padu Xbox 360 który stał się swego rodzaju standardem na PC) i bezproblemowa obsługa OpenGL w nowszych wersjach. Najważniejszym argumentem który spowodował to że wybrałem ją zamiast SFML lub innej biblioteki jest (podobnie jak w przypadku C++) wieloplatformowość.
OpenGL 3.2 - specyfikacja w tej wersji zrywa kompatybilność wsteczną z tzw. fixed pipeline na rzecz shaderów. W poprzednich wersjach takie rzeczy jak światło, cienie czy tekstury były ustawiane z kodu, ale obecne karty graficzne (a konkretnie ich sterowniki) symulują te funkcjonalności w sprytnie zaszytych shaderach. Shadery dają ogromne możliwości przy tworzeniu grafiki komputerowej co może się przydać gdy będę chciał usprawniać grafikę generowaną przez konsolę. Dodatkowo wersja 3.2 jest bardzo zbliżona do OpenGl ES 2.0, który dominuje na urządzeniach niebędącymi komputerami osobistymi co znowu usprawnia proces portowania na inne platformy. Z Direct3D zrezygnowałem z powodu ograniczenia do jednej platformy.
Ciekawą technologią jest Vulkan, ale on dopiero raczkuje i jego celem nie jest zastąpienie OpenGl, a wypełnienie luki tam gdzie inne biblioteki powodują zbyt duży narzut wydajnościowy.
ImGUI - prosta biblioteka do tworzenia GUI posiadająca spore możliwości. Bardzo łatwo integruje się z bibliotekami 3d, jest szybka i banalna w użyciu. Jej implementacja zajmuje się całym boilerplate, my tylko definiujemy w locie jakie widgety chcemy wyświetlić i jak mamy zareagować na eventy. Pozwala na szybkie prototypowanie i tworzenie bardziej skomplikowanych narzędzi jak edytor pamięci, debugger i inne. W związku z tym, że generuje obraz w formie przyjaznej bibliotekom 3d nie ogranicza ją dana platforma.
Przy zgłaszaniu projektu na Daj się poznać wspomniałem też o HTML, CSS i JS. Potraktowałem to jako eksperyment, gdzie chciałbym powyższe technologie użyć jako zaawansowany interfejs do debugowania i manipulacji emulatorem. Serwerem byłby sam emulator który udostępniałby dane w czasie rzeczywistym z użyciem WebSocketów. Możliwości są duże - przykładowo wizualizacja aktualnie przesyłanych danych do GPU jak tekstury, modele i renderowanie ich z użyciem three.js.
Zapraszam do śledzenia na Twitterze oraz do komentowania.