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

Animacja 4 klatkowa

0 głosów
137 wizyt
pytanie zadane 12 lutego w JavaScript, jQuery, AJAX przez Muhin Obywatel (1,610 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 przez elwood Obywatel (1,500 p.)
wybrane 16 lutego 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 przez Muhin Obywatel (1,610 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 przez elwood Obywatel (1,500 p.)
Nie za bardzo rozumiem o co chodzi z tym przeskokiem.

Sprawdź coś takiego https://jsfiddle.net/qmxgfw8m/2/
komentarz 14 lutego przez Muhin Obywatel (1,610 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 przez elwood Obywatel (1,500 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 przez Muhin Obywatel (1,610 p.)
edycja 16 lutego 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 przez elwood Obywatel (1,500 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 przez Muhin Obywatel (1,610 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 przez elwood Obywatel (1,500 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 przez Muhin Obywatel (1,610 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 przez Ehlert Szeryf (98,200 p.)
edycja 13 lutego przez Ehlert

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

EDIT: Link

komentarz 13 lutego przez Muhin Obywatel (1,610 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 przez Ehlert Szeryf (98,200 p.)
dałem linka

Podobne pytania

0 głosów
2 odpowiedzi 75 wizyt
pytanie zadane 22 maja w JavaScript, jQuery, AJAX przez BeSSeSSt Obywatel (1,180 p.)
0 głosów
1 odpowiedź 113 wizyt
pytanie zadane 17 stycznia w JavaScript, jQuery, AJAX przez mowmiheniek Stary wyjadacz (11,810 p.)
0 głosów
1 odpowiedź 50 wizyt

37,418 zapytań

74,639 odpowiedzi

144,769 komentarzy

17,339 pasjonatów

Przeglądających: 90
Pasjonatów: 3 Gości: 87

Motyw:

Akcja Pajacyk

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

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...