• 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

VPS Starter Arubacloud
0 głosów
229 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,160 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,160 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,160 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ź 183 wizyt
pytanie zadane 15 marca 2019 w C# przez niezalogowany
0 głosów
0 odpowiedzi 97 wizyt
0 głosów
1 odpowiedź 481 wizyt
pytanie zadane 14 października 2018 w JavaScript przez Grzegorz :> Dyskutant (8,050 p.)

92,315 zapytań

141,121 odpowiedzi

318,635 komentarzy

61,763 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!

...