Gra JavaScript - HTML5 Canvas vs MVC

0

Witam po raz pierwszy na 4programmers.net/Forum.

Piszę grę dwuwymiarową z użyciem JS i elementu Canvas. Stworzenie gry samej w sobie nie sprawia jednak żadnych trudności, zamęt wprowadza wzorzec MVC, którego muszę użyć. W książce A. MacCaw'a "JavaScript. Aplikacje WWW" autor opisuje go:

"MVC to wzorzec projektowy, który dzieli aplikację na trzy części: dane (Model), warstwę prezentacji (widok, czyli View) oraz warstwę interakcji z użytkownikiem (kontroler, czyli Controller). Inaczej mówiąc, przepływ zdarzeń przedstawia się następująco: 1. Użytkownik wykonuje jakąś czynność w aplikacji. => 2. Wyzwalana jest procedura obsługi zdarzenia kontrolera. => 3. Kontroler pozyskuje dane z modelu i przekazuje je do widoku. => 4. W widoku dane są przedstawione użytkownikowi." s.19
. Z tym się zgadzam. Model...
"Model nie wie nic na temat widoków ani kontrolerów - powinien on zawierać wyłącznie dane oraz logikę bezpośrednio związaną z tymi danymi. Jakikolwiek kod źródłowy, który nie jest z tym modelem związany - procedury obsługi zdarzeń, szablony widoków czy logika - powinien być wyraźnie oddzielony od modelu. Z ewidentną oznaką pogwałcenia reguł wzorca MVC mamy do czynienia wówczas, gdy w modelu napotyka się kod widoków. Modele powinny być całkowicie oddzielone od reszty aplikacji." s.19.
Widok...
"Podobnie jak modele, również widoki należy wyraźnie oddzielić od reszty aplikacji. Widoki nie powinny mieć żadnej styczności z kontrolerami i modelami, lecz powinny być całkowicie niezależne. Przenikanie się widoków i logiki jest pierwszym objawem nadciągającej katastrofy. Nie oznacz to jednak, że wzorzec MVC nie dopuszcza żadnej logiki prezentacji". Logika nie może być jednak definiowana wewnątrz widoków. Logika prezentacji musi znajdować się w tak zwanych bibliotekach pomocniczych (ang. helper), czyli w skryptach pełniących rolę niewielkich narzędzi przeznaczonych wyłącznie do obsługi widoków." s.20.
Kontroler...
"Kontrolery są spoiwem łączącym modele i widoki. Kontrolery przyjmują zdarzenia i dane wejściowe pochodzące z widoków, przetwarzają je (nierzadko z zastosowaniem modeli) i odpowiednio zmieniają widoki. W trakcie ładowania strony kontroler dodaje do widoków procesy nasłuchiwania zdarzeń, które mają za zadanie na przykład identyfikować fakt przesłania formularza albo kliknięcia przycisku. Potem, gdy użytkownik wykonuje z aplikacji jakieś działania, zachodzące zdarzenia wyzwalają czynności wewnątrz kontrolerów." s.21.

Według powyższych cytatów sposób jawnej komunikacji wygląda następująco: M <= C => V. Można by też zaproponować że Kontroler tworzy Model i Widok i zna udostępniony przez nie interfejs. W sytuacji, gdy zachodzi jakieś zdarzenie Kontroler powiadamia model o zmianie danych i po ich zmianie musi uaktualnić widok. W jaki sposób model poinformuje kontroler, że wykonał już zadanie? Można wrzucić do modelu pustą funkcję, która będzie uruchamiana po wykonaniu czynności. A to co w niej będzie uruchamiane musi ustawić wcześniej kontroler za pomocą funkcji ustawiającej modelu. Podobnie można zrobić z widokiem. A co jeśli model będzie zawierał dane cyfrowe planszy gry w postaci dwuwymiarowej tablicy wypełnionej znakami. Widok aby narysować planszę musi najpierw pobrać dane z modelu, następnie przetworzyć zamienić je na obrazki i wyświetlić. I tu znowu problem. Widok nie powinien zawierać skomplikowanej logiki wyświetlania. Ale można by zrobić dodatkowe narzędzia pomocnicze, które się tym zajmą. To jakoś można pociągnąć. Ale co z tymi danymi? Jak widok ma je pobrać z modelu skoro nie wie o jego istnieniu. Nie wie również o istnieniu kontrolera czyli nie zna interfejsu, który udostępniają. Spoko to też można minąć, jeśli dane "wepchnie" mu kontroler. Ale co z obrazkami. Widok podmienia dane cyfrowe na obrazki i wyświetla. Ale obrazki to też dane gry, czyli powinny być w modelu. Tylko, że każdy obrazek ma nazwę. A skąd widok ma znać ich nazwę skoro należą one do modelu? i tu zaczynają się pytania. Co zrobić z tymi obrazkami? Jak wykonać widok aby mógł je przetworzyć nie znając danych cyfrowych, obrazków i sposobu mapowania? Gdzie powinna zawierać się logika (tzw. inteligencja) gry? w modelu? czy kontrolerze? a może tu i tu? W książce Eric'a Rowell'a "HTML5 Canvas Receptury" autor przedstawia kod gry opartej na modelu MVC. "Canvas Hero" - "http://www.html5canvastutorials.com/cookbook/ch8/index.html", która w gruncie rzeczy nie wydaje mi się zgodna z założeniami pierwszego autora. Proszę o pomysły i opinie. Dziękuję serdecznie i pozdrawiam.

1

Jak chcesz w MVC to najlepiej za pomocą jakiegoś frameworku. Całkiem popularny jest http://backbonejs.org/ :)

0

Wolałbym zrobić to w czystym JavaScript. Ale dzięki, przyjrzę się temu framework - owi.

0

wszystkie te dylmaty da się rozwiazać za pomoca eventów i wzorca obserwator. Czyli robisz tak, że modele mają metodę addEventListener (albo addObserver, listenTo, on itp.), z parametrem z nazwą eventu, np


// Jakas funkcja w widoku
....)
model.addListener('zaladowaneObrazki', function(obrazki) {
    obrazki.forEach(function(obrazek) {
       // rob cos z kazdym obrazkiem po kolei
   });
});

A Model zapisze sobie obserwatora (np. funkcję) w tablicy i będzie odpalal za kazdym razem kiedy zostanie wyemitowane zdarzenie 'zaladowaneObrazki' (wiec potrzeba jeszcze funkcji do emitowania zdarzeń, np. emit(), trigger(),

W zasadzie polecam zapoznanie się z Backbone, w nim zastosowano podobne rozwiązanie, więc nawet jeśli nie zamierzasz go używać, to i tak można przejrzeć API albo kod źródłowy.

Piszę grę dwuwymiarową z użyciem JS i elementu Canvas. Stworzenie gry samej w sobie nie sprawia jednak żadnych trudności, zamęt wprowadza wzorzec MVC, którego muszę użyć.

jak to musisz użyć? Ktoś ci każe?

0

Sam wybrałem czysty JavaScript, ponieważ stwierdziłem, że nie mogę cały czas iść na łatwiznę. Chciałbym dobrze zrozumieć ten wzorzec. Rozwiązanie z obserwatorem jest bardzo ciekawe. Zastanawiam się nadal czy aby na pewno obrazki umieszczać w modelu. Czy mogę umieścić je w widoku? Przecież nie są to dane, które będą przez grę przetwarzane i najwięcej wspólnego mają właśnie z widokiem.

0

w sumie można by przypasować adres url obrazka (tj. string np. "/images/hi-res/player.png") do modelu, ponieważ są to pewne metadane przypisane do danej jednostki w grze, ale już sam obiekt Image raczej do widoku ponieważ jest to element, który będzie się bezpośrednio wyświetlał.

Problem tylko co będzie, jeśli będziesz miał jeden model i dwa widoki? Np. jeśli będziesz chcial wyświetlić postać normalnie na ekranie, oraz na radarze/minimapie? Jeśli obrazki (jako obiekty Image) są przypisane do widoku, to mając dwa widoki musiałbyś niepotrzebnie tworzyć dwa obrazki, zamiast jednego. Wiec warto chyba (niezależnie od tego czy zdecydujesz się na MVC czy nie) zrobić jeszcze coś w rodzaju menedżera obrazków (np. stworzyć cały obiekt i nazwać go np, ImageManager albo ImageLoader), który by zarządzał obiektami Image. (podobnie warto zrobić do wszelkich innych reużywalnych "zasobów", np. pliki dźwiękowe, tekstury.

czyli widok by nie tworzył bezpośrednio obiektów Image, ale by pobierał z modelu sam adres url, i podawał go do menedżera, a menedżer zwracałby na podatawie adresu z'cache'owany obiekt Image (który bedzie ci jak rozumiem potrzebny do tego, żeby wyswietlic grafike na Canvasie). Mało tego, W zasadzie to menedżer/loader nawet móglby być odpowiedzialny za ustalenie adresu obrazka. W zasadzie to jeśli być ustalił jakąs ustaloną metodę nazywania plików graficznych i leżalyby one w ustalonym katalogu i miały proste nazwy, odpowiadajace typom np. obrazek dla żolnierza nazywałby sie 'soldier.png' i byłby w katalogu '/images/entities' albo dowolnie innym, ale wiadomym z gory - to adres obrazka nawet nie musiałby być nigdzie zapisywany, ale byłby automatycznie wykrywany na podstawie typu jednostki (np. obrazek dla jednostki o typie 'soldier' mialby adres 'images/entities/soldier.png').

Ale generalnie nie ma dogmatów i wszystko zależy jak będzie pasować do gry.

no i tam wspomniałeś o MVC, ale tak naprawdę, mimo że można użyć MVC albo MV* w grach, to nie wyczerpuje to jednak problemu zaprogramowania wszystkiego (problem ładowania zasobów, np. przez menedżery - o tym MVC nic nie mówi chyba. Komunikacja jednostek między sobą (czyli nie widoku z modelem, ale np. gracza z wrogiem), również MVC milczy na ten temat. Jako jeden z elementów okej, ale MVC jakos mi sie nie widzi jako calosciowe rozwiazanie.

0

Model MVC opisuje zazwyczaj aplikacje: WWW, desktop'owe. O użyciu tego wzorca w grach wspomina się już rzadziej. Menadżera obrazków już zrobiłem, i przyznam, że pomysł bardzo dobry. Nie jestem jednak pewien czy aby na pewno umieścić go w kontrolerze. Jeśli chodzi o całość gry i model MVC pomyślałem, aby rozszerzyć moduły o odpowiednie pod moduły, które zajmowałyby się mniejszymi operacjami. Coś podobnego do menadżera obrazków. Np. Kontroler zajmie się logiką gry. Chodzi tu zwłaszcza o przeciwników. Będzie zawierał on do tego specjalny pod moduł. Kolejny pod moduł zajmie się obsługą postaci gracza. itd. Podobnie z widokiem, oprócz prostego wyświetlania obrazków będzie zawierał pod moduł zajmujący się obsługą animacji. Będzie to dobre?

1 użytkowników online, w tym zalogowanych: 0, gości: 1