• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Animacja 4 klatkowa

VPS Starter Arubacloud
0 głosów
791 wizyt
pytanie zadane 12 lutego 2017 w JavaScript przez Muhin Gaduła (4,120 p.)

Witam,

od jakiegoś czasu głowię się jak najefektowniej zrobić animację 4 klatek co 8px. Na dzień dzisiejszy robię coś takiego:

setTimeout("goX(xx+="+hx+");",65);
setTimeout("goX(xx+="+hx+");",130);
setTimeout("goX(xx+="+hx+");",185);
setTimeout("goX(xx+="+hx+");",260);

I w moim przypadku mam 3 elementy do animacji co daje mi łącznie 5 * 4 wiersze czegoś takiego, żeby ta animacja w ogóle była. Jest to nie praktyczne i strasznie nie efektywne. Czy zna ktoś jakiś lepszy sposób na animację 4 klatkową bez setTimeouta?

2 odpowiedzi

+1 głos
odpowiedź 13 lutego 2017 przez elwood Gaduła (4,180 p.)
wybrane 16 lutego 2017 przez Muhin
 
Najlepsza
Nie musisz używać żadnych setTimeout'ów. Musisz za to stworzyć jedną główną pętle, która będzie działała w nieskończoność. Canvas jest idealnym rozwiązaniem do tego typu rzeczy.

https://jsfiddle.net/qmxgfw8m/1/
komentarz 14 lutego 2017 przez Muhin Gaduła (4,120 p.)
W sumie źle zredagowałem to pytanie. Z samą animacją obrazka nie mam dużych problemów, bardziej chodzi mi o animację chodzenia. Postać musi przejść 32 px bez przeskoku, Obliczyłem, że muszę kazać jej w jednym kroku zrobić 4 animacje po 8 px i to da najlepszy efekt. Przy setTimeoutach sprawa była prosta, bo robiło się takie 4 z różnym odstępami czasowymi (po 50 ms) i jakoś w miarę płynnie szło to zrobić, a jak to zrobić w przypadku kiedy pętla główna leci cały czas dajmy na to co 70 ms?
komentarz 14 lutego 2017 przez elwood Gaduła (4,180 p.)
Nie za bardzo rozumiem o co chodzi z tym przeskokiem.

Sprawdź coś takiego https://jsfiddle.net/qmxgfw8m/2/
komentarz 14 lutego 2017 przez Muhin Gaduła (4,120 p.)
Fajnie to wygląda, ale mógłbyś mi wyjaśnić jak działa parę rzeczy  w tym kodzie? Widzę, że to jest robione na obiektach, a ja obiektowego JS znam tylko trochę z podręcznika.

Do czego służy pętla Update w tym kodzie?

Co ma przechowywać tablica entities?

Jak dokładnie jest zrobiona animacja ruchu postaci, że to tak ładnie wygląda?
komentarz 14 lutego 2017 przez elwood Gaduła (4,180 p.)

Tablica entities przechowuje wszystkie stworzone sprite'y. W momencie wywołania new Sprite() wykonywany jest construktor w którym jest dodanie obiektu do tablicy entities. (w końcu musimy mieć jakiś dostęp do stworzonych obiektów ;) )

this.game.entities.push(this);

Metoda update w classie Game literuje całą tablice entities i dla każdego obiektu (w tym wypadku nasz hero) wykonuje jego metodę update zdefiniowaną w classie Sprite. Sama metoda update odpowiada w tym wypadku za ruch postaci (w niej również powinieneś pisać fizykę, wykrywanie kolizji itp.

Metoda render w classie Game również literuje całą tablice entities, ale służy wyłącznie do rysowania obiektów na canvasie. 

Na ostatnie pytanie nie wiem jak odpowiedzieć :). Na pewno zamiast setTimeout z jakimiś dziwnymi odstępami czasowymi używaj 

window.requestAnimationFrame

Pozwala to na uzyskanie raczej stałych 60fps przy prostych projektach. 

 

komentarz 16 lutego 2017 przez Muhin Gaduła (4,120 p.)
edycja 16 lutego 2017 przez Muhin
Dzięki za małą podpowiedź.

Lekko zmodyfikowałem kod, żeby postać po zatrzymaniu patrzyła cały czas w kierunku w którym wcześniej szła.

Mam jeszcze dwa pytanka.

Czy moja modyfikacja nie pochodzi pod  druciarstwo? Można to nazwać dobrym posunięciem? Czy zrobiłbyś to inaczej?

Jak dopisać chodzenie w dół i w górę? Jak mniemam muszę operować w funkcji move().

(Prosiłbym bardziej o podpowiedź, niż gotową w stawkę. Chciałbym się czegoś nauczyć :D)
EDIT:

Udało mi się po dokładnej analizie kodu uzyskać taki efekt:
Oto moja modyfikacja: https://jsfiddle.net/0c23ponr/2/

Czy Twoim zdaniem wygląda to prawidłowo?
komentarz 16 lutego 2017 przez elwood Gaduła (4,180 p.)
Widzę poradziłeś sobie z poprzednimi błędami jakie były w switchu i w heroState :).

Jedna uwaga, kodu this.states['idle'].fy = this.states[this.currentState].fy; nie wykonuj w metodzie draw, ona odpowiada tylko za rysowanie i niech tak zostanie :).

Na pytanie czy zrobił bym to inaczej, to za bardzo nie mogę się wypowiedzieć, bo nawet nie wiem co chcesz zrobić :). Przykład który przedstawiłem jest bardzo prosty i wymagał by wielu przeróbek. Mam pytanie tylko odnośnie tego ruchu, czemu w taki dziwny sposób ma się poruszać ta postać tzn te 32 px na ruch? Nie wygląda to zbyt płynnie.
komentarz 16 lutego 2017 przez Muhin Gaduła (4,120 p.)
Chodzi mi o to, że w kodzie który podałeś postać zawsze wraca do pozycji "idle"  i przyjmuje fy: 0, a w moim kodzie jak widać aktualne fy jest zapisywane do tablicy states co pozwala uzyskać efekt bez zmiany kierunku do przodu. Można to zobaczyć jak porównasz sobie rezultat mojego kodu z Twoim podanym wcześniej. Co do 32 px, to mając animację 4x4 przy 32 px według mnie najładniej to wygląda. Zresztą jak miałem to na setTimeoutach, to wyglądało dużo gorzej od tego. A co Ty byś proponował w tej kwestii? Jeszcze zauważyłem, że podczas zmiany speed z 1 na 2 lub więcej wszystko zaczyna się sypać. Wiesz może dlaczego tak się dzieje?
komentarz 16 lutego 2017 przez elwood Gaduła (4,180 p.)

Nie napisałem, by nie używać kodu this.states['idle'].fy = this.states[this.currentState].fy tylko by zrobić to w innym miejscu. Odpowiednim miejscem do tego będzie metoda move.

 move(){
    	if(this.x < this.distanceToGoX || this.x > this.distanceToGoX){
      		this.x += this.currentState === 'right' ? this.speed : -this.speed;
      	}else if(this.y < this.distanceToGoY || this.y > this.distanceToGoY){
        	this.y += this.currentState === 'down' ? this.speed : -this.speed;	
        }else{
        	if(!this.isMoving && !this.game.keyPressed){
          	this.states['idle'].fy = this.states[this.currentState].fy;
        		this.currentState = 'idle';
        		this.current_f = 0;
        		return;
        }

        this.isMoving = false;
        return;
      }
    }

Nadal nie rozumiem tych 32px :(. Wielkość animacji nie ma znaczenia. Co do zmiany prędkości to wiem. Źle napisany if w metodzie move ;-) 

Sprawdź ten kod. Tutaj nie ma poruszania "32px" tylko bardziej tradycyjnie. Przykład powinien Cię trochę bardziej nakierować na problem z chodzeniem bohatera. Możesz tutaj dowolnie zmieniać prędkość czy szybkość wyświetlania klatek. Dodatkowo możesz napisać przyśpieszanie do maksymalnej prędkości i hamowanie.

https://jsfiddle.net/0c23ponr/4/

 

komentarz 17 lutego 2017 przez Muhin Gaduła (4,120 p.)

Nie napisałem, by nie używać kodu this.states['idle'].fy = this.states[this.currentState].fy tylko by zrobić to w innym miejscu. Odpowiednim miejscem do tego będzie metoda move.

 Źle się wyraziłem. Myślałem, że nie wiedziałeś dlaczego używam tego kodu

 this.states['idle'].fy = this.states[this.currentState].fy

więc starałem się to wyjaśnić.:)

Co do kodu który mi podesłałeś, rzeczywiście ładnie i płynnie to wygląda, ale to nie pasuje do mapek których będę chciał używać.

Jedna kratka na tej mapce ma 32 px na 32 px, dlatego też uparłem się na to 32 px animacji. Każda kolizja jaka będzie na takiej mapce zawsze będzie miała 32 na 32 co w kordach dawałoby 1,1.

+1 głos
odpowiedź 13 lutego 2017 przez Ehlert Ekspert (212,630 p.)
edycja 13 lutego 2017 przez Ehlert

Pokaż obrazek który zawiera klatki animacji. I nie podawaj w pierwszym argumencie stringa... no

EDIT: Link

komentarz 13 lutego 2017 przez Muhin Gaduła (4,120 p.)

Używam takiego obrazka jak wyżej.

Jednak bardziej zależy mi na innej odpowiedzi. Może opiszę to tak:

Mam 3 animacje do wykonania:

1 animacja to animacja obrazka wyżej;

2 animacja to animacja ruchu postaci (1 kratki 32 px );

3 animacja mapy pod postacią (1 kratka 32 px);

jako, że jedna kratka ma 32 px dzielę to na 4 * 8 px, żeby to wyglądało płynnie. Jak wiadomo w takiej sytuacji animacja może wykonać się tylko w danej sytuacji, czyli jak kliknę strzałkę. Po stronie kodu mam ifa który sprawdza jaka strzałka jest kliknięta, a później 5 funkcji z tymi timeOutami. Gdzieś czytałem, że mam to zrobić w canvasie, ale w canvasie wygląda to tak samo, bo też muszę zrobić ten ruch setTimeoutami.

komentarz 13 lutego 2017 przez Ehlert Ekspert (212,630 p.)
dałem linka

Podobne pytania

0 głosów
2 odpowiedzi 576 wizyt
pytanie zadane 22 maja 2017 w JavaScript przez BeSSeSSt Obywatel (1,190 p.)
0 głosów
1 odpowiedź 152 wizyt
pytanie zadane 22 lutego 2023 w JavaScript przez Grzegorz Mikina Dyskutant (8,060 p.)
0 głosów
2 odpowiedzi 181 wizyt
pytanie zadane 1 czerwca 2020 w JavaScript przez michal3254 Nowicjusz (140 p.)

92,453 zapytań

141,262 odpowiedzi

319,086 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...