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

question-closed element canvas, a animacja poruszania

Aruba Cloud VPS - 50% taniej przez 3 miesiące!
0 głosów
355 wizyt
pytanie zadane 27 kwietnia 2021 w JavaScript przez Nabuchadonozor Gaduła (3,120 p.)
zamknięte 29 kwietnia 2021 przez Nabuchadonozor

Witam z uśmiechem,

otóż ostatnio zacząłem pracować z elementem canvas. Poniżej jest obraz, który używam do animowania efektu poruszania się. Problem polega na tym, że kiedy kliknę a (lewo) lub d (prawo) - animacja poruszania przez chwile idzie w wybranym kierunku przez (około) pierwszą sekundę kawałkiem obrazka z pierwszej kolumny wiersza 2(klikając a)/5(klikając d), a po tej chwilce zaczyna ostro animować tak jak powinno, ze kolejne dwa (razem trzy) na zmianę się zmieniają. Wie ktoś może na czym polega problem?

Na wszelki cały kod, ale problem najpewniej będzie widniał w move.js lub animate.js. Z góry dzięki za wszelką pomoc!

index.html:

<!DOCTYPE html>
<html>
 
<head>
  <title>document</title>
  <link rel="stylesheet" href="style.css">
</head>
 
<body>
  <canvas id="myCanvas" width="1000px" height="500px"></canvas>

  <script src="js/specification.js"></script>
  <script src="js/draw.js"></script>
  <script src="js/animate.js"></script>
  <script src="js/move.js"></script>
 
</body>
 
</html>

draw.js:

var myImage = new Image();
myImage.src = 'img/man.png';
myImage.addEventListener('load', loadImage, false);

function loadImage(e){
    animate();
}

function animate(){
    ctx.clearRect(0, 0, 1000, 500)
    ctx.drawImage(myImage, shiftX, shiftY, frameWidth, frameHeight, xMan, yMan, frameWidth, frameHeight);
    
    xMan += dx;

    requestId = requestAnimationFrame(animate);
}

move.js:

document.addEventListener("keydown", isKeyDown, false);
document.addEventListener("keyup", isKeyUp, false);

function isKeyDown(e){
    if(e.key == "d"){
        moveRight();
        dx = velocity;
    }
    if(e.key == "a"){
        moveLeft();
        dx = -velocity;
    }
}

function isKeyUp(e){
    if(e.key == "d"){
        moveStopRight();
        dx = 0;
    }
    if(e.key == "a"){
        moveStopLeft();
        dx = 0;
    }
}

animate.js:

function moveStopRight(){
    shiftY = 0;
    shiftX = 0;
}

function moveStopLeft(){
    shiftY = frameHeight*3;
    shiftX = 0;
}

function moveRight(){
    shiftX += frameWidth;
    shiftY = frameHeight;

    if(shiftX >= frameWidth*3){
        shiftX = 0;
    }
}

function moveLeft(){
    shiftX += frameWidth;
    shiftY = frameHeight*4;

    if(shiftX >= frameWidth*3){
        shiftX = 0;
    }
}

specification.js:

var canvas = document.querySelector('#myCanvas');
var ctx = canvas.getContext('2d');

//start&stopMainAnimate
var requestId;

//animateMan
var shiftX = 0; //startXImage
var shiftY = 0; //startXImage
var frameWidth = 90; //oneFrame
var frameHeight = 100; //oneFrame
var xMan = 0;
var yMan = 400;
var dx = 0;
var velocity = 3;

 

komentarz zamknięcia: za głęboka woda jak dla mnie

1 odpowiedź

+1 głos
odpowiedź 27 kwietnia 2021 przez rafal.budzis Szeryf (85,380 p.)
wybrane 28 kwietnia 2021 przez Nabuchadonozor
 
Najlepsza

Hej problem który widać na pierwszy rzut oka to brak wzorca projektowego. Gry opierają się lub powinny się opierać na "pętli czasu rzeczywistego". Która jest podzielona na dwie funkcje update (tutaj zmieniasz pozycje elementów sprawdzasz stan klawiatury itp) oraz draw która odpowiada za rysowanie :) (dwie funkcje w jednym requestAnimationFrame)

W obecnym podejściu nie panujesz nad tym czy event keydown oraz keyup wykona się przed rysowaniem w canvas czy po :) Lepszym rozwiązaniem jest zapisywanie do zmiennej stanu klawiatury (korzystając z tych samych eventów)  i sprawdzanie go zawsze przed rysowaniem (cześć update)

Możesz zerknąć jak zrobiłem po u siebie 7 lat temu :o https://budzis.pl/Wpisy/Programy/Ostatnia-choinka/ Zamiast requestAnimationFrame wykorzystałem wtedy setTimeout ale obecnie polecam korzystać dalej z requestAnimationFrame :) Całość pisałem w ES5 może coś się przyda :) 

komentarz 28 kwietnia 2021 przez Nabuchadonozor Gaduła (3,120 p.)
edycja 28 kwietnia 2021 przez Nabuchadonozor

Dzięki wielkie za odpowiedź! Bałem się, że zbyt obszerny post dałem, przez co nikt nie odpisze... Gratki za pomysł giereczki! (jak coś nie działa Ci pierwsze dwa przekierowania w nagłówku "Autor") A podałbyś nazwę tego wzorca? Bo jak wpisałem parę fraz, to nie mogłem znaleźć nic o przekazywaniu dwóch funkcji w jednym requestAnim...? Mógłbym to prosto naprawić za pomocą setInterval(), jednakże właśnie widziałem w necie wiele naprowadzeń użytkowanie requestAnim... Zaraz wezmę się za obrobienie kodu w te nazwy co podałeś, bo szczerze miałem problem wymyślić jak to poukładać, żeby wyglądało bardzo logicznie. Jeszcze raz dziękuję!

komentarz 28 kwietnia 2021 przez Nabuchadonozor Gaduła (3,120 p.)

Chyba, że chodziło o to, iż mam zrobić jedną funkcję, w której wywołują się dwie funkcję główne - draw(), update() ? i potem requestAnimationFrame(doubleFunction) ?

komentarz 28 kwietnia 2021 przez rafal.budzis Szeryf (85,380 p.)

Jest kilka sposobów. Podam dwa przykłady ;) 

 


function update() {
    // TODO update object
    draw();
}

function draw() {
    // TODO draw object
    window.requestAnimationFrame(update);
}

window.requestAnimationFrame(update);

lub np tak :

 

function update() {
     // TODO update object
}

function draw() {
    // TODO draw object
}

function gameLoop() {
    update();
    draw();
    window.requestAnimationFrame(gameLoop);
}

window.requestAnimationFrame(gameLoop);

Sam wybierz jak wolisz ;) 

PS. na wiele pytań na forum nie odpisuje bo są zbyt mało obszerne i trudno zrozumieć o co chodzi ;) Im dokładniej opiszesz problem tym lepiej ;) 

komentarz 29 kwietnia 2021 przez Nabuchadonozor Gaduła (3,120 p.)

Próbowałem coś wykminić z tym update(), jednakże chyba muszę cofnąć się na jakiś czas o jeden poziom, bo kurcze nie chciało mi trybić, popatrzałem też na necie różne wzorce, jednakże próbowałem wszystkiego co potrafię, a nadal przez sekundę animacja się zacina i po sekundzie zaczyna postać animacje biegania (choć od początku już porusza się w prawidłową stronę, tylko ta animacja się przycina...).
Zapamiętam na przyszłość o tym rozpisywaniu, dzięki za próbę pomocy!

komentarz 29 kwietnia 2021 przez rafal.budzis Szeryf (85,380 p.)

Może łatwiej będzie skorzystać z jakiejś gotowej biblioteki? Np dużo słyszałem o https://www.pixijs.com/ ale sam nie korzystałem. 

komentarz 3 maja 2021 przez Nabuchadonozor Gaduła (3,120 p.)
Dzięki za pomysł, jednakże chodziło bardziej o takie poduczenie się czystego js'a, w miarę ciekawy sposób :)

Podobne pytania

0 głosów
1 odpowiedź 216 wizyt
pytanie zadane 15 marca 2019 w C# przez niezalogowany
0 głosów
2 odpowiedzi 157 wizyt
pytanie zadane 8 kwietnia w JavaScript przez niezalogowany
0 głosów
0 odpowiedzi 123 wizyt

93,180 zapytań

142,193 odpowiedzi

321,990 komentarzy

62,511 pasjonatów

Advent of Code 2024

Top 15 użytkowników

  1. 1873p. - dia-Chann
  2. 1848p. - Łukasz Piwowar
  3. 1831p. - CC PL
  4. 1827p. - Łukasz Eckert
  5. 1651p. - Łukasz Siedlecki
  6. 1572p. - Tomasz Bielak
  7. 1545p. - Michal Drewniak
  8. 1531p. - rucin93
  9. 1509p. - rafalszastok
  10. 1506p. - Marcin Putra
  11. 1487p. - Adrian Wieprzkowicz
  12. 1447p. - Mikbac
  13. 1356p. - ssynowiec
  14. 1289p. - Anonim 3619784
  15. 1169p. - Grzegorz Aleksander Klementowski
Szczegóły i pełne wyniki

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

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...