Plynnosc animacji Jquery keypress settimout albo setinterval

0

Witam,
Chciałbym ogarnąć sobie js + jquery, a żeby to zrobić to trzeba pisać, bez tego sie nie obejdzie :)
Zacząłem robić gierke, mam zamiar później dodać skok, jakąś walke, może nawet statystki (wszystko w celach edukacyjnych), ale na razie męcze się z animacją postaci.
jest ona oparta na Spirte, w moim przypadku żeby animacja szła do przodu musi być
background-position: Xpx 154px;
Przy czym X z przedziału [0,80,160,240];
mimo że ustawiam settimeout albo setinterval na 200ms 500ms 1000ms to po przytrzymaniu klawisza idzie to duzo duzo szybciej. Otworzcie konsole to mozecie to zobaczyc, Wypiasana jest tam wartosc X.

Tutaj jest link: http://176.122.228.58/artur/jquery/index.php.html
Klawisz A i D :)
A tutaj code

<!doctype html>
<html>
<head>
	<meta charset="utf-8" />
	<title>Demo</title>
	<link rel="stylesheet" type="text/css" href="css/style.css" />
	<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.js"></script>
	<script src="libs/jquery.spritely.js"></script>
	
	<script>var bgleft=0;</script>
	<script>
   
	$(document).ready(function(){
		
	$('body').keypress(function(event){
	$('body').keyup(function(event){
	   clearTimeout(animacja); 
	});
	klawisz = event.keyCode;
	console.log(klawisz);
	console.log(bgleft);
  var animacja = false;

		if  (klawisz == 100){
		   if(bgleft>240){
		   bgleft=0;
		}
		animacja = false;
		$('#char').animate({
		"left":"+=8px"
		},10);
		var animacja =  setTimeout(function(){
			$('#char').css('background-position',""+bgleft+"px 154px");
		   bgleft+=80;
		  },500);
		}
		
		if (klawisz == 97){
			if(bgleft>240){
			bgleft=0;
			} 
			$('#char').animate({
			"left":"-=8px"
			},5);
			animacja =  setTimeout(function(){
			$('#char').css('background-position',""+bgleft-5+"px 230px");
			bgleft+=80;
			},500);
		}
		
		if (klawisz == 119){
			$('#char').animate({
				"top":"-=0px"
			},500);
		}
		
		if (klawisz == 115){
			$('#char').animate({
				"top":"+=0px"
			},500);
		}
	});

   
	});
	</script>
	
</head>
<body>

<embed height="1" width="1" src="images/theme.mp3">
<script>


	var styl="background: url('images/chmura.png'); width:100%;height:111px;position:absolute;";
	document.write('<div id="chmurki" style="'+styl+'top:50; px;padding-left:0px;"></div>');
	$('#chmurki').pan({fps: 30, speed: 3, dir: 'left'});
	
</script>
 
   <div id="char"></div>
	
 <div id="ground"></div>
<div id="wypelnienie"></div>

	
 
</body>
</html>

Dziękuje z góry za pomoc ;)

0

Animacje tworzone przy wykorzystaniu funkcji setTimeout() oraz setInterval() nie będą działać płynnie. Zainteresuj się requestAnimationFrame: http://css-tricks.com/using-requestanimationframe/.
Na mojej stronie: http://lukaszrydzkowski.pl/portfolio/ znajdziesz opis napisanej przeze mnie w JS gry "Bouncing Ball", która wykorzystuję requestAnimationFrame. Możesz tam pobrać dokumentację oraz kod źródłowy aby zobaczyć jak wygląda wykorzystanie tego mechanizmu w praktyce.

0

przy przytrzymaniu klawisza, zapewne zaczyna się odpalać ileś eventów keypress w bardzo krótkim odstępie czasu, a że w każdym wywołaniu keypress odpalasz nową animację.... to się kumuluje.

Więc pomocny będzie albo jakiś ogranicznik czasowy (JEŚLI upłynął_czas_progowy TO animuj JEŚLI NIE nie rób nic),
albo po prostu zrób to w ten sposób, że będziesz przechowywał gdzieś współrzędne i prędkość vx i vy sprajta, i go animował (nawet bez pomocy jQuery, przecież to tylko:

var char = $("#char")[0]; // zamieniamy element jQuery na zwykły element DOM, poprzez odwołanie się do zerowego indeksu 
.....
char.x = 100; // gdzie ma byc sprajt
char.y = 200; 

char.vx = 0;  // predkosc pozioma
char.vy = 0; // predkosc pionowa

...
// zdarzenie keypress

var speed = 0.3; // przykladowa szybkosc
JEŚLI lewo TO char.vx = -speed;
JEŚLI prawo TO char.vx = speed;

...
setInterval(function() {
  char.x += char.vx;
  char.y += char.vy;
  char.style.left = char.x + "px";
  char.style.top = char.y + "px";
}, 1000/60); 

No i poza tym piszesz kod w ten sposób, jakby tylko jeden sprajt był w grze. Raczej powinieneś zrobić jakąś tablicę czy coś w tym stylu, i poruszać sprajtami hurtowo, iterując po tablicy. No chyba, że nie zamierzasz dodawać jakichś innych obiektów niż ten ludek.

edit: no i to, co mój przedmówca wspomniał, można użyć zdarzenia requestAnimationFrame, zamiast setInterval, ale to już tzw. optymalizacja. No i nie wiem czy nie lepsze będzie zdarzenie keydown do tego.

0

Kod pisze tak żeby działał. Nigdy nic nie pisalem :) Mam zamiar poźniej go zmienic w bardziej obiektowy :)
Jak widzisz keydown? Keydown dziala tylko jako jedno nacisniecie klawisza anie przytrzymanie go :)

0

keydown powtarza się na jednej z przeglądarek, nie pamiętam której.
na innych robisz tak, że sam powtarzasz event po keydown co określony czas, dopóki nie ma keyup z tym klawiszem

0

A jaksprawdzić ten czas podprogowy. Mam już inny pomysł właśnie z keydown ale jestem w pracy do 18 i ten czas podprogowy potrzebny mi w razie "W"

0

Druga wersja gry z keydown i requestanimationframe();
Niestety nie wiem dlaczego, mimo ze jest troche lepiej i animacja sie nie zacina, to nadal jest za szybko.
http://176.122.228.58/artur/rpg/index.html

Jquery:

  window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame });
var postac =  document.querySelector('#postac');
var bgleft = 0;
var gora;
function animacja(kierunek){
     switch(kierunek){
        case 'prawo':
        gora = 154;
        break;
        case 'lewo':
        gora = 231;
        break;
        case 'gora':
        gora = 0;
        break;
        case 'dol':
        gora = 77;
        break;
     }
     if(bgleft>240){
     bgleft=0;
     }
     $('#postac').css('background-position',""+bgleft+"px "+gora+"px");
     bgleft+=80;
     window.requestAnimFrame(animacja);
     console.log(bgleft);
     console.log(gora);
}

$(document).keydown(function(e){
    
    switch(e.keyCode){
        case 65: //lewo
        $('#postac').css('left', '-=' + 5);
        
        animacja('lewo');
        e.preventDefault();
        break;
        case 68: //prawo
       $('#postac').css('left', '+=' + 5);
       animacja('prawo');
       e.preventDefault();
        break;
        
        case 83: //gora
        $('#postac').css('top', '+=' + 5);
        animacja('gora');
        e.preventDefault();
        break;
        
        case 87: //dol
        animacja('dol');
        $('#postac').css('top', '-=' + 5);
        
    }
});

CSS:

 #gra{
    margin: auto;
    width:1280px;
    height:760px;
    background-color: green;
}

#postac{
     position:relative;
     width:75px;
     height:75px;
     left:136px;
     top:320px;
     z-index:1;
     background: url('../images/postac.png');
     background-position: 240px 0px;
}

0

Nie wiem czy dokładnie o taki efekt Ci chodzi, ale po zmodyfikowaniu zdarzenia keydown w poniższy sposób możesz uzyskać efekt wolniejszej animacji:

var counter = 0;
var divisor = 3;
$(document).keydown(function(e)
{
    if (counter++ % divisor === 0)
    {
        switch(e.keyCode){
            case 65: //lewo
                $('#postac').css('left', '-=' + 15);
                animacja('lewo');
                e.preventDefault();
                break;
            case 68: //prawo
                $('#postac').css('left', '+=' + 15);
                animacja('prawo');
                e.preventDefault();
                break;
            case 83: //gora
                $('#postac').css('top', '+=' + 15);
                animacja('gora');
                e.preventDefault();
                break;
            case 87: //dol
                animacja('dol');
                $('#postac').css('top', '-=' + 15);
                break;
        }   
    }
    
});
$(document).keyup(function() {
    counter = divisor;
});
0
Tarvald napisał(a):

Kod pisze tak żeby działał. (...) Mam zamiar poźniej go zmienic w bardziej obiektowy :)

I nie ma w tym nic złego. Po prostu im dłużej programujesz, tym bardziej przewidujesz, co ci może być potrzebne później, i robisz juz na wstępie bardziej elastyczny kod.

0

% aż tyle czasu zajmuje ze spowolni to animacje?

0

Operator % zwraca resztę dzielenia: http://stackoverflow.com/questions/8900652/what-does-do-in-javascript
Poniższy fragment odpowiada za to, aby przesunięcie postaci następowało w momencie wystąpienie co trzeciego zdarzenia keydown, gdy użytkownik trzyma przyciśnięty przycisk:

var counter = 0;
var divisor = 3;
...
if (counter++ % divisor === 0)
{
...

Możesz modyfikować szybkość animacji zmieniając wartość zmiennej divisor (im większa wartość tej zmiennej tym animacja powinna być wolniejsza).

Dzięki poniższemu fragmentowi kodu pierwsze wystąpienie zdarzenia keydown, a więc np. pojedyńcze przyciśnięcie klawisza zawsze spowoduję wykonanie ruchu postaci:

...
$(document).keyup(function() {
    counter = divisor;
});

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