Płynny ruchu obiektu poruszanego kursorami po siatce

0

Witajcie drodzy koledzy,

próbuję napisać w miarę prosty kod, z założenia przy użyciu jedynie JS+jQuery, który umożliwiałby ruch obiektem po siatce. Mój obecny kod co prawda spełnia zamierzoną funkcję, ale w momencie, gdy obiekt (sterowanie kursorami) nagle zmienia kierunek ruchu, to chwilami występuje małe zatrzymanie obiektu (na jakieś 0.3 - 0.5 sekundy) i dopiero podejmowany jest ruch w innym kierunku.

Macie może pomysł zaradzić temu problemowi, albo posiadacie może jakiś kawałek kodu dotyczący ruchu po siatce (samo JS + jQ)?

<script data-require="[email protected]" data-semver="2.2.4" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

<script>
$(document).ready(function(e){

var in_move=0;




function move(obj,kierunek,stop=0)
{

  if (kierunek=='r')
  {
    $(obj).animate({left: '-=32px'}, 300, 'linear', function(){ in_move=0; } );
  }
  else if (kierunek=='l')
  {
    $(obj).animate({left: '+=32px'}, 300, 'linear', function(){ in_move=0; } );
  }
  else if (kierunek=='t')
  {
    $(obj).animate({top: '+=32px'}, 300, 'linear', function(){ in_move=0; });
  }
  else if (kierunek=='b')
  {
    $(obj).animate({top: '-=32px'}, 300, 'linear', function(){ in_move=0; });
  }


  return false;
}




$(document).keydown(function(e)
{
  var kierunek;

       if (e.which == 37) kierunek='l';
  else if (e.which == 38) kierunek='t';
  else if (e.which == 39) kierunek='r';
  else if (e.which == 40) kierunek='b';

  if (kierunek!==undefined && in_move==0)
  {
    in_move=1;
    move('#map',kierunek);
  }

});




});
</script>


<div id="tab">
</div>


<style>

#player
{
  width:32px;
  height:32px;
  background-color:red;
  left:128px;
  top:128px;
  position:absolute;
  z-index:20;
  image-rendering:pixelated;
  image-rendering:-webkit-optimize-contrast;
  image-rendering:crisp-edges
}

#window_box
{
  margin:100px 0 0 300px;
  width:256px;
  height:256px;
  background-color:#eee;
  position:relative;
  overflow:hidden;
  border:solid red 2px
}

#map
{
  position:absolute;
  width:640px;
  height:640px;
  top:0;
  left:0
}

.tree
{
  background-color:#000;
  background-size:cover;
  image-rendering:pixelated;
  image-rendering:-webkit-optimize-contrast;
  image-rendering:crisp-edges
}

</style>

<div class="pozycja">x: 0, y: 0</div>


<div id="window_box">

  <div id="player"></div>

<div id="map">

  <div class="tree" style="width:32px;height:32px;position:absolute;left:0;top:0"></div>
  <div class="tree" style="width:32px;height:32px;position:absolute;left:0;top:32px"></div>
  <div style="background-color:orange;width:32px;height:32px;position:absolute;left:calc(640px - 32px);top:0"></div>

  <div style="background-color:green;width:32px;height:32px;position:absolute;left:128px;top:0"></div>     <!-- 0x4 -->
  <div style="background-color:green;width:32px;height:32px;position:absolute;left:128px;top:64px"></div>

</div>

</div>

Pozdrawiam!

3

Myślałem wpierw, że dwie animacje się konfliktują (w jQuery było coś do zatrzymywania poprzedniej animacji https://api.jquery.com/stop/ ) ale jak patrzę na kod, to odpalasz nową dopiero po zatrzymaniu kolejnej.

linear

Przy linear powinno "szarpać" i zmieniać nagle kierunek ruchu i to jest okej, ale nie powinno się zatrzymywać na 0.3-0.5 sekundy. Nie mam pomysłu poza tym, żeby otworzyć profiler w dev toolsach w zakładce wydajność i zobaczyć, co tam się dzieje. Albo wywalić jQuery i animować to choćby za pomocą CSS3, przeglądarkowej funkcji animate ( https://developer.mozilla.org/en-US/docs/Web/API/Element/animate ) albo ręcznie. Bo jQuery ci w zasadzie niewiele pomaga i tak tutaj, a co najwyżej może przeszkodzić (szczególnie, że używasz jakieś starej wersji jQuery sprzed 4 lat z tego co widzę...).

image-rendering:pixelated;
 image-rendering:-webkit-optimize-contrast;
image-rendering:crisp-edges

BTW wow. Nie znałem tej właściwości CSS. Zawsze człowiek się czegoś nowego nauczy.

0

Dzięki za wskazówkę :)

kod zmodyfikowany, działa znacznie lepiej jeżeli chodzi o płynność, został jeszcze jedynie problem polegający na tym, że gdy obiekt porusza się w jednym kierunku przez "przyduszenie" kursora, to w momencie puszczeniu klawisza (keyup) obiekt robi jeszcze jakby jeden dodatkowy krok w danym kierunku.

Masz może jakiś pomysł jak można temu zaradzić?


<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>



<script>
$(document).ready(function(e){

var in_move=0;

function player_position()
{
  var map_pos_l=(parseInt( $('#map').css('left').replace('px','') )/32) - (parseInt( $('#player').css('left').replace('px','') )/ 32);
  var map_pos_t=(parseInt( $('#map').css('top').replace('px','') )/32)  - (parseInt( $('#player').css('top').replace('px','') )  / 32);

  $('.pozycja').html('x: '+map_pos_l+', y: '+map_pos_t);

  return {'x':map_pos_l,'y':map_pos_t};
}

function move_possible(kierunek)
{
  var pos=player_position();

  var pos_x=pos.x;
  var pos_y=pos.y;

       if (kierunek=='r') pos_x--;
  else if (kierunek=='l') pos_x++;
  else if (kierunek=='t') pos_y++;
  else if (kierunek=='b') pos_y--;

  if (tablica_obiektow[pos_x+','+pos_y]===undefined) return 1;

  return tablica_obiektow[pos_x+','+pos_y].movable;
}



var tablica_ruchow=[];



function move(obj)
{
  var kierunek = tablica_ruchow[0];

  if (kierunek===undefined) return;

  if (move_possible(kierunek))
  {
    if (kierunek=='r')
    {
      var object_1 = document.getElementById("map");
      var wartosc;

      if (object_1.style.left!=='') wartosc=parseInt(object_1.style.left.replace('px',''))-32;
      else wartosc=-32;

      wartosc=wartosc+'px';

      var object_2 = object_1.animate([{ left: wartosc }],
      {
        duration: 300,
        easing:'linear',
        iterations: 1
      });

      object_2.onfinish = function() { object_1.style.left=wartosc; tablica_ruchow.shift(); }
    }
    else if (kierunek=='l')
    {
      var object_1 = document.getElementById("map");
      var wartosc;

      if (object_1.style.left!=='') wartosc=parseInt(object_1.style.left.replace('px',''))+32;
      else wartosc=32;

      wartosc=wartosc+'px';

      var object_2 = object_1.animate([{ left: wartosc }],
      {
        duration: 300,
        easing:'linear',
        iterations: 1
      });

      object_2.onfinish = function() { object_1.style.left=wartosc; tablica_ruchow.shift(); }
    }
    else if (kierunek=='t')
    {
      var object_1 = document.getElementById("map");
      var wartosc;

      if (object_1.style.top!=='') wartosc=parseInt(object_1.style.top.replace('px',''))+32;
      else wartosc=32;

      wartosc=wartosc+'px';

      var object_2 = object_1.animate([{ top: wartosc }],
      {
        duration: 300,
        easing:'linear',
        iterations: 1
      });

      object_2.onfinish = function() { object_1.style.top=wartosc; tablica_ruchow.shift(); }

  }
    else if (kierunek=='b')
    {
      var object_1 = document.getElementById("map");
      var wartosc;

      if (object_1.style.top!=='') wartosc=parseInt(object_1.style.top.replace('px',''))-32;
      else wartosc=-32;

      wartosc=wartosc+'px';

      var object_2 = object_1.animate([{ top: wartosc }],
      {
        duration: 300,
        easing:'linear',
        iterations: 1
      });

      object_2.onfinish = function() { object_1.style.top=wartosc; tablica_ruchow.shift(); }
    }
  }
  else tablica_ruchow=[];

  


  if (tablica_ruchow.length>1) tablica_ruchow=[];



  return false;
}




var search_timeout = undefined;

$(document).bind('keydown', function(e)
{
  if(search_timeout != undefined)
  {
    clearTimeout(search_timeout);
  }

    var $this = this;

    var delay=1;

    if (tablica_ruchow.length>0) delay=300;

    search_timeout = setTimeout(function() {
        search_timeout = undefined;

        var kierunek;

if (e.which == 37) kierunek='l';
else if (e.which == 38) kierunek='t';
else if (e.which == 39) kierunek='r';
else if (e.which == 40) kierunek='b';


if (kierunek!==undefined)
{
tablica_ruchow.push(kierunek);

move('#map');
}

        
    }, delay);
});









var tablica_obiektow={

"0,0":{"movable":0},
"0,-1":{"movable":0},

}




});
</script>


<div id="tab">
</div>


<style>

#player
{
  width:32px;
  height:32px;
  background-color:red;
  left:128px;
  top:128px;
  position:absolute;
  z-index:20;
  image-rendering:pixelated;
  image-rendering:-webkit-optimize-contrast;
  image-rendering:crisp-edges
}

#window_box
{
  margin:100px 0 0 300px;
  width:256px;
  height:256px;
  background-color:#eee;
  position:relative;
  overflow:hidden;
  border:solid red 2px
}

#map
{
  position:absolute;
  width:640px;
  height:640px;
  top:0;
  left:0
}

.tree
{
  background-color:#000;
  background-size:cover;
  image-rendering:pixelated;
  image-rendering:-webkit-optimize-contrast;
  image-rendering:crisp-edges
}

</style>

<div class="pozycja">x: 0, y: 0</div>


<div style="position:absolute;right:100px;top:100px;width:300px;height:500px" id="ruchy"></div>


<div id="window_box">

  <div id="player"></div>

<div id="map">

  <div class="tree" style="width:32px;height:32px;position:absolute;left:0;top:0"></div>
  <div class="tree" style="width:32px;height:32px;position:absolute;left:0;top:32px"></div>
  <div style="background-color:orange;width:32px;height:32px;position:absolute;left:calc(640px - 32px);top:0"></div>

  <div style="background-color:green;width:32px;height:32px;position:absolute;left:128px;top:0"></div>     <!-- 0x4 -->
  <div style="background-color:green;width:32px;height:32px;position:absolute;left:128px;top:64px"></div>

</div>

</div>
0

Gdzie masz to keyup? W tym kodzie, który wrzuciłeś, nie ma keyup

Ruszasz mapą czy obiektem w końcu? Bo move('#map'); sugeruje, że przesuwasz mapę, a to zdanie który umożliwiałby ruch obiektem po siatce. sugerowałoby, że chcesz ruszać obiektami po mapie.

Aaa... zaraz, chyba, że to jedno i to samo (w scenariuszu, gdzie grafika symbolizująca gracza stoi w miejscu, a przesuwa się tło).

Chociaż jeśli tak, to raczej powinieneś trzymać gdzieś aktualne współrzędne gracza (współrzędne w świecie gry!) w jakimś obiekcie np.

player = {
   x: 10, y: 20
}

A mapę przesuwać na podstawie tych współrzędnych (zamiast bawić się w dzikie parsowanie stringów).

Bo teraz robisz tak:

parseInt( $('#map').css('left').replace('px','') )/32) - (parseInt( $('#player').css('left').replace('px','') )/ 32);

A to jest mocno partyzanckie... Bo to tak jakbyś trzymał współrzędne gracza ukryte gdzieś w pozycji diva #map, która to pozycja zależy od przeglądarki (i odpalonych albo nie animacji). Czyli nie panujesz nad danymi w swojej grze.

0

Cześć, zgadza się, chciałam napisać to tak, żeby obiekt był nieruchomy, a ruszała się po prostu "plansza".

Dodałam keyup-a, ale nie działa tak jak powinien - tj. czyści tablicę ruchów, ale nie naprawia to niepożądanego efektu "dodatkowego kroku" i nie wiem jak temu zaradzić :(

Dodałam trochę grafik:

<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>



<script>
$(document).ready(function(e){

var in_move=0;

function player_position()
{
  var map_pos_l=(parseInt( $('#map').css('left').replace('px','') )/32) - (parseInt( $('#player').css('left').replace('px','') )/ 32);
  var map_pos_t=(parseInt( $('#map').css('top').replace('px','') )/32)  - (parseInt( $('#player').css('top').replace('px','') )  / 32);

  $('.pozycja').html('x: '+map_pos_l+', y: '+map_pos_t);

  return {'x':map_pos_l,'y':map_pos_t};
}

function move_possible(kierunek)
{
  var pos=player_position();

  var pos_x=pos.x;
  var pos_y=pos.y;

       if (kierunek=='r') pos_x--;
  else if (kierunek=='l') pos_x++;
  else if (kierunek=='t') pos_y++;
  else if (kierunek=='b') pos_y--;

  if (tablica_obiektow[pos_x+','+pos_y]===undefined) return 1;

  return tablica_obiektow[pos_x+','+pos_y].movable;
}



var tablica_ruchow=[];

var krok_top=1;

function move(obj)
{
  var kierunek = tablica_ruchow[0];

  if (kierunek===undefined) return;

  if (move_possible(kierunek))
  {
    if (kierunek=='r')
    {
      var object_1 = document.getElementById("map");
      var wartosc;

      if (object_1.style.left!=='') wartosc=parseInt(object_1.style.left.replace('px',''))-32;
      else wartosc=-32;

      wartosc=wartosc+'px';

      document.getElementById("player").classList.remove("stand_t");
      document.getElementById("player").classList.remove("stand_l");
      document.getElementById("player").classList.remove("stand_b");

      document.getElementById("player").classList.add("stand_r");
      document.getElementById("player").classList.add("animacja_right"+krok_top);

      var object_2 = object_1.animate([{ left: wartosc }],
      {
        duration: 300,
        easing:'linear',
        iterations: 1
      });


      object_2.onfinish = function()
      {
        object_1.style.left=wartosc; tablica_ruchow.shift(); document.getElementById("player").classList.remove("animacja_right"+krok_top);
    
        if (krok_top==1) krok_top=2;
        else             krok_top=1;
      };



    }
    else if (kierunek=='l')
    {
      var object_1 = document.getElementById("map");
      var wartosc;

      if (object_1.style.left!=='') wartosc=parseInt(object_1.style.left.replace('px',''))+32;
      else wartosc=32;

      wartosc=wartosc+'px';

      document.getElementById("player").classList.remove("stand_t");
      document.getElementById("player").classList.remove("stand_r");
      document.getElementById("player").classList.remove("stand_b");

      document.getElementById("player").classList.add("stand_l");
      document.getElementById("player").classList.add("animacja_left"+krok_top);

      var object_2 = object_1.animate([{ left: wartosc }],
      {
        duration: 300,
        easing:'linear',
        iterations: 1
      });


      object_2.onfinish = function()
      {
        object_1.style.left=wartosc; tablica_ruchow.shift(); document.getElementById("player").classList.remove("animacja_left"+krok_top);
    
        if (krok_top==1) krok_top=2;
        else             krok_top=1;
      };

    }
    else if (kierunek=='t')
    {
      var object_1 = document.getElementById("map");
      var wartosc;

      if (object_1.style.top!=='') wartosc=parseInt(object_1.style.top.replace('px',''))+32;
      else wartosc=32;

      wartosc=wartosc+'px';

      document.getElementById("player").classList.remove("stand_b");
      document.getElementById("player").classList.remove("stand_r");
      document.getElementById("player").classList.remove("stand_l");

      document.getElementById("player").classList.add("stand_t");
      document.getElementById("player").classList.add("animacja_top"+krok_top);

      var object_2 = object_1.animate([{ top: wartosc }],
      {
        duration: 300,
        easing:'linear',
        iterations: 1
      });


      object_2.onfinish = function() { object_1.style.top=wartosc; tablica_ruchow.shift(); document.getElementById("player").classList.remove("animacja_top"+krok_top);
    
      if (krok_top==1) krok_top=2;
      else             krok_top=1;
    
    }

  }
    else if (kierunek=='b')
    {
      var object_1 = document.getElementById("map");
      var wartosc;

      if (object_1.style.top!=='') wartosc=parseInt(object_1.style.top.replace('px',''))-32;
      else wartosc=-32;

      wartosc=wartosc+'px';

      document.getElementById("player").classList.remove("stand_t");
      document.getElementById("player").classList.remove("stand_r");
      document.getElementById("player").classList.remove("stand_l");

      document.getElementById("player").classList.add("stand_b");
      document.getElementById("player").classList.add("animacja_bottom"+krok_top);

      var object_2 = object_1.animate([{ top: wartosc }],
      {
        duration: 300,
        easing:'linear',
        iterations: 1
      });

      object_2.onfinish = function() { object_1.style.top=wartosc; tablica_ruchow.shift(); document.getElementById("player").classList.remove("animacja_bottom"+krok_top);
    
      if (krok_top==1) krok_top=2;
      else             krok_top=1;

      }
    }
  }
  else tablica_ruchow=[];

  


  if (tablica_ruchow.length>1) tablica_ruchow=[];



  return false;
}





var search_timeout = undefined;

$(document).bind('keydown', function(e)
{
  if(search_timeout != undefined)
  {
    clearTimeout(search_timeout);
  }

    var $this = this;

    var delay=1;

    if (tablica_ruchow.length>0) delay=300;

    search_timeout = setTimeout(function() {
        search_timeout = undefined;

        var kierunek;

if (e.which == 37) kierunek='l';
else if (e.which == 38) kierunek='t';
else if (e.which == 39) kierunek='r';
else if (e.which == 40) kierunek='b';


if (kierunek!==undefined)
{
tablica_ruchow.push(kierunek);

move('#map');
}

        
    }, delay);
});









var tablica_obiektow={

"0,0":{"movable":0},
"0,-1":{"movable":0},

}




});
</script>


<div id="tab">
</div>


<style>

#player
{
  width:32px;
  height:32px;
  background-size:cover;
  left:128px;
  top:128px;
  position:absolute;
  z-index:20;
  image-rendering:pixelated;
  image-rendering:-webkit-optimize-contrast;
  image-rendering:crisp-edges
}


#player.stand_t { background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAC8SURBVHjatJIxDsMwCEU/VgeOxBE6+ggde6SMPULGHsFHYiNLbNkYK5GqIlmOvoHAAzIzeCOiWQRgZuS1RxSswlE8iMh8knQ3GABUeKou4UdLV32vWmnfFWIvqjDweo5Rny+46Az0TGC6ZQNw61RfMxsZ6JYvy/c+YQt3rLaQvKBbRjRKFW5/73dhqECFGyhfKr/3loiLriGqcLv7M7x1EKdVbqPyYyz7MMY/QhReQzz1EGK0ptUx0qodAwDYmZ/bnomalwAAAABJRU5ErkJggg=='); }
#player.stand_b { background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADTSURBVHjajFOxEYMwDHxxLjSSR0jpESgZyWVGoMwIjKROKYIcIQSJGtCf/tE/NqkqYhHRGQSgqhSxkpGlcsYHEWkUmf4lA4BUPm034aZ4E/AmdyNfgajsiVHEz5KFGAWilShiWZThvTfwskJ6y/3Pu9A+Y4EeMvBkXtb0PX6g2Dpm4WqDKGYWyB+kk8jz9XnOj5RsDXYRBaDSm0pltX7glVV6G73xDiH6kGTON7A5C7GkRgNx9NnxvjoHv8pymCIglZHdB4/7ECleZ7/J+FUJZvUeAEAynaXaJAeHAAAAAElFTkSuQmCC'); }
#player.stand_l { background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADHSURBVHjajFPBEcMgDJNyPBiJEfrMCH1mpIyRMTISP/UTKFDBlTsOMNhIsk1JaAfJ3vAMSXT2MDrnFN07kJQLsv3jDAA5RYtuaw/xztMAeL8sxbDiPTrnc/+hQ0nLAC2tgrDTQhKeTCifu8pa9m4WH0m9BhbBuVfoLp2bc3D7WS2E9rKm8hENAOJxLRGG8QeSwn1ZVLaYWkGqmCl2ouUUq218H1zNk1T5NR7Xl9J9rSnMiqroYBvKwW8pzKCXyX/aedbKAPAZAAH+xG1F//58AAAAAElFTkSuQmCC') }
#player.stand_r { background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADJSURBVHjalFO5DcMwDCQFFxxJI6TUCCkzkkqP4NIjeCR258KxQUpUhAgQYMK64x0fBkDRYebwBwC28TICa5YhsSVJ/4CJiDSLU5dC2e/XkEAO9QnvGjAztBb/et1/EgDgxQa3AmuhzRhV9blEhOhqLdBanu8LdmHSqEVaC3WWgpNmfbYkESFHg2Tb5EDrTnKoS9IR2G7IZ5tOoiviXUjNAs3iC/mN2/fhKD+DdGxk1XTZo12w8zDbg9BCa8VaiGzwaJ1HK90qOAcA2zbLXcB9QBoAAAAASUVORK5CYII='); }



#player.animacja_top1
{
  animation: ruch_top1 300ms steps(2) infinite;
  animation-timing-function: linear;
}

#player.animacja_top2
{
  animation: ruch_top2 300ms steps(2) infinite;
  animation-timing-function: linear;
}


@keyframes ruch_top1
{
    0% { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAC0SURBVHjapFO7DcUwCDysFIzkEV6ZEV6ZkVJmBJcZISPRXZrnyB/yHClINBjOBwdCEm9s8oIi4qKSlCGAiNCi4g64BQlPiwHAonbsAl5aGPU9mpFkFcqgRQW+n7pq26GH9QP9AdDWmQAeec4lWc/A1nlIv81xW3hqJCV4S+JJaVGv30sWFYP8oEvqqOqS3K2cbvlt+1/q3SqTlGoOrYxH8u+BpOuddFEv6UqX0TmXrLxrPAcAZnuR5cgASU0AAAAASUVORK5CYII='); }
  100% { background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAC8SURBVHjatJIxDsMwCEU/VgeOxBE6+ggde6SMPULGHsFHYiNLbNkYK5GqIlmOvoHAAzIzeCOiWQRgZuS1RxSswlE8iMh8knQ3GABUeKou4UdLV32vWmnfFWIvqjDweo5Rny+46Az0TGC6ZQNw61RfMxsZ6JYvy/c+YQt3rLaQvKBbRjRKFW5/73dhqECFGyhfKr/3loiLriGqcLv7M7x1EKdVbqPyYyz7MMY/QhReQzz1EGK0ptUx0qodAwDYmZ/bnomalwAAAABJRU5ErkJggg=='); }
}

@keyframes ruch_top2
{
    0% { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAC1SURBVHjapJOxDcQwCEU/VgpG8ghXZoQrM5LLjJAyI9xIdD/NJbIxJ+cUJDcInj4fIyTxJKYoKSIhlaQMASJCy4pfYA9Jd5sBwLJ26hIeRhrNPfJIzi3UScsKvF9t17pDP9Yb+gXQykwAt95ZS7L1wMo8lO9rhORf8/sRkidbmRGtss7VfyE0MZKqy3bldNkuyFRTG8i631upP6YTEikIb4Jk8wDQsobr87UkewXej+gC6zgGAGoqkcWskS5rAAAAAElFTkSuQmCC') }
    100% { background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAC8SURBVHjatJIxDsMwCEU/VgeOxBE6+ggde6SMPULGHsFHYiNLbNkYK5GqIlmOvoHAAzIzeCOiWQRgZuS1RxSswlE8iMh8knQ3GABUeKou4UdLV32vWmnfFWIvqjDweo5Rny+46Az0TGC6ZQNw61RfMxsZ6JYvy/c+YQt3rLaQvKBbRjRKFW5/73dhqECFGyhfKr/3loiLriGqcLv7M7x1EKdVbqPyYyz7MMY/QhReQzz1EGK0ptUx0qodAwDYmZ/bnomalwAAAABJRU5ErkJggg=='); }
}


#player.animacja_bottom1
{
  animation: ruch_bottom1 300ms steps(2) infinite;
  animation-timing-function: linear;
}

#player.animacja_bottom2
{
  animation: ruch_bottom2 300ms steps(2) infinite;
  animation-timing-function: linear;
}

@keyframes ruch_bottom1
{
    0% { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADUSURBVHjapFOxDYQwDPShFB6JEb5kBEpGovwRKBnhR3J3X4CRYwK89JGiRJF98fl8ICn/rNJ6BNBEJYlHAAC0XuUKOIN0vyaLiFivp+q6O376MdGP3fagu+IdEzNIjIWrkAEylQzivSgH93kQnRaxeWjzH3egPcYbWvUgJuu0NO/5g5KDrirIcU4BJCsKFch73c7xdarkmAeSsjeSIkKbB/q9ta1XbmlbHqIXXIlDgfCzV6XTUo10ydIAoEtmsj6aCdmNcZxbU5i9gJad41C1HBjXdwCCbY+zEJDHKgAAAABJRU5ErkJggg=='); }
  100% { background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADTSURBVHjajFOxEYMwDHxxLjSSR0jpESgZyWVGoMwIjKROKYIcIQSJGtCf/tE/NqkqYhHRGQSgqhSxkpGlcsYHEWkUmf4lA4BUPm034aZ4E/AmdyNfgajsiVHEz5KFGAWilShiWZThvTfwskJ6y/3Pu9A+Y4EeMvBkXtb0PX6g2Dpm4WqDKGYWyB+kk8jz9XnOj5RsDXYRBaDSm0pltX7glVV6G73xDiH6kGTON7A5C7GkRgNx9NnxvjoHv8pymCIglZHdB4/7ECleZ7/J+FUJZvUeAEAynaXaJAeHAAAAAElFTkSuQmCC'); }
}

@keyframes ruch_bottom2
{
    0% { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADKSURBVHjapJOxDYNAEAT30AdXEiU4pARCSiJ0CYQugZIuWwfm0HO+fywZCfFCv8Pt8isk8c9VspciklJJyi1ARGijogWOkOFXMQDYqF/TDT1/uht0t24GQ8t3LYyQeq/4X4iAaCVCPItyel8n6LLB1in3Px+gY48HesmgFuuypev4geLjuIXWBBmsmcEJeb4+z/lxEbtdkgKSOCC0UQmgeds6nWvXSd0FD7MOq57E/0R9GkvXcBBmfZDYxqxIfiZ0t3tAr51ZG98DAGCVkDuztpEWAAAAAElFTkSuQmCC') }
  100% { background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADTSURBVHjajFOxEYMwDHxxLjSSR0jpESgZyWVGoMwIjKROKYIcIQSJGtCf/tE/NqkqYhHRGQSgqhSxkpGlcsYHEWkUmf4lA4BUPm034aZ4E/AmdyNfgajsiVHEz5KFGAWilShiWZThvTfwskJ6y/3Pu9A+Y4EeMvBkXtb0PX6g2Dpm4WqDKGYWyB+kk8jz9XnOj5RsDXYRBaDSm0pltX7glVV6G73xDiH6kGTON7A5C7GkRgNx9NnxvjoHv8pymCIglZHdB4/7ECleZ7/J+FUJZvUeAEAynaXaJAeHAAAAAElFTkSuQmCC'); }
}


#player.animacja_left1
{
  animation: ruch_left1 300ms steps(2) infinite;
  animation-timing-function: linear;
}

#player.animacja_left2
{
  animation: ruch_left2 300ms steps(2) infinite;
  animation-timing-function: linear;
}


@keyframes ruch_left1
{
    0% { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADISURBVHjapFOxDcMwDBMND7qnk0/omBM69qSc0TPyUbWxS5TKruIWaAAjshXKJKWApPzz1PEAQFqRJL4WAEBrmt4EgFmR8gtYRMSapuxK3Ohm52Jv11RinekewbYuH3JAclogynKGnRckZW8lbV3ob4+z5RiSvQcpg3U5qGftLBkgi89mocbk0crdNBERvT/mFKMe98KXNX3Huyfj9zUbYXdeNztknDEpcQojMMqYTmPXxqY97Ys8oxzPRQmIv3OsPjruufH8NQDifbfDCwRUCQAAAABJRU5ErkJggg=='); }
  100% { background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADHSURBVHjajFPBEcMgDJNyPBiJEfrMCH1mpIyRMTISP/UTKFDBlTsOMNhIsk1JaAfJ3vAMSXT2MDrnFN07kJQLsv3jDAA5RYtuaw/xztMAeL8sxbDiPTrnc/+hQ0nLAC2tgrDTQhKeTCifu8pa9m4WH0m9BhbBuVfoLp2bc3D7WS2E9rKm8hENAOJxLRGG8QeSwn1ZVLaYWkGqmCl2ouUUq218H1zNk1T5NR7Xl9J9rSnMiqroYBvKwW8pzKCXyX/aedbKAPAZAAH+xG1F//58AAAAAElFTkSuQmCC'); }
}

@keyframes ruch_left2
{
    0% { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADISURBVHjapFOxDcMwDBMND7qnk0/omBM69qSc0TPyUbWxS5TKruIWaAAjshXKJKWApPzz1PEAQFqRJL4WAEBrmt4EgFmR8gtYRMSapuxK3Ohm52Jv11RinekewbYuH3JAclogynKGnRckZW8lbV3ob4+z5RiSvQcpg3U5qGftLBkgi89mocbk0crdNBERvT/mFKMe98KXNX3Huyfj9zUbYXdeNztknDEpcQojMMqYTmPXxqY97Ys8oxzPRQmIv3OsPjruufH8NQDifbfDCwRUCQAAAABJRU5ErkJggg=='); }
  100% { background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADHSURBVHjajFPBEcMgDJNyPBiJEfrMCH1mpIyRMTISP/UTKFDBlTsOMNhIsk1JaAfJ3vAMSXT2MDrnFN07kJQLsv3jDAA5RYtuaw/xztMAeL8sxbDiPTrnc/+hQ0nLAC2tgrDTQhKeTCifu8pa9m4WH0m9BhbBuVfoLp2bc3D7WS2E9rKm8hENAOJxLRGG8QeSwn1ZVLaYWkGqmCl2ouUUq218H1zNk1T5NR7Xl9J9rSnMiqroYBvKwW8pzKCXyX/aedbKAPAZAAH+xG1F//58AAAAAElFTkSuQmCC'); }
}



#player.animacja_right1
{
  animation: ruch_right1 300ms steps(2) infinite;
  animation-timing-function: linear;
}

#player.animacja_right2
{
  animation: ruch_right2 300ms steps(2) infinite;
  animation-timing-function: linear;
}

@keyframes ruch_right1
{
    0% { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADPSURBVHjapFKxDcMwDJOMDLqnk0/I6BMy9iSPOaFjT8hH1cYOqQ3JURoUNWAggUyKIsUA6J8znRWYOWQGwJcEzAzNckpsSdIvYCIizeLUpVD2Mp8SyKa+YTORmaG1+Nfr8ysBAJ7sT1NgRxg7Rq72S0SIrtYCraV/77Adk84i0lroMFJw0lXOliQi5GgTbUwOtD5JNvVNrAfNhzYnEUGzOD/G9wcFPYlPZ7k/eipjhOEihVu4zB2sWfw2HuRncbL1Ri87TqtdjjCmYY21tfcA0OzEK6VDDGAAAAAASUVORK5CYII='); }
  100% { background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADJSURBVHjalFO5DcMwDCQFFxxJI6TUCCkzkkqP4NIjeCR258KxQUpUhAgQYMK64x0fBkDRYebwBwC28TICa5YhsSVJ/4CJiDSLU5dC2e/XkEAO9QnvGjAztBb/et1/EgDgxQa3AmuhzRhV9blEhOhqLdBanu8LdmHSqEVaC3WWgpNmfbYkESFHg2Tb5EDrTnKoS9IR2G7IZ5tOoiviXUjNAs3iC/mN2/fhKD+DdGxk1XTZo12w8zDbg9BCa8VaiGzwaJ1HK90qOAcA2zbLXcB9QBoAAAAASUVORK5CYII='); }
}

@keyframes ruch_right2
{
    0% { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADPSURBVHjapFKxDcMwDJOMDLqnk0/I6BMy9iSPOaFjT8hH1cYOqQ3JURoUNWAggUyKIsUA6J8znRWYOWQGwJcEzAzNckpsSdIvYCIizeLUpVD2Mp8SyKa+YTORmaG1+Nfr8ysBAJ7sT1NgRxg7Rq72S0SIrtYCraV/77Adk84i0lroMFJw0lXOliQi5GgTbUwOtD5JNvVNrAfNhzYnEUGzOD/G9wcFPYlPZ7k/eipjhOEihVu4zB2sWfw2HuRncbL1Ri87TqtdjjCmYY21tfcA0OzEK6VDDGAAAAAASUVORK5CYII='); }
  100% { background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADJSURBVHjalFO5DcMwDCQFFxxJI6TUCCkzkkqP4NIjeCR258KxQUpUhAgQYMK64x0fBkDRYebwBwC28TICa5YhsSVJ/4CJiDSLU5dC2e/XkEAO9QnvGjAztBb/et1/EgDgxQa3AmuhzRhV9blEhOhqLdBanu8LdmHSqEVaC3WWgpNmfbYkESFHg2Tb5EDrTnKoS9IR2G7IZ5tOoiviXUjNAs3iC/mN2/fhKD+DdGxk1XTZo12w8zDbg9BCa8VaiGzwaJ1HK90qOAcA2zbLXcB9QBoAAAAASUVORK5CYII='); }
}







#window_box
{
  margin:100px 0 0 300px;
  width:256px;
  height:256px;
  background-color:#eee;
  position:relative;
  overflow:hidden;
  border:solid red 2px
}

#map
{
  position:absolute;
  width:640px;
  height:640px;
  top:0;
  left:0
}

.tree
{
  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAJDSURBVHjabFNPSJNhHH6+4SbZ2hjmnG7Txddmc6QVjlwxPkfTHTY/whgE1S5ih6EVFUniot0kOghCh26dInazPIw81KlDty5GB5M1pLSwXH9Yik+H1+/7tvSFl4ffj9/zh5ffKxH7HzOCbD9kxWrlJ7awJO07RMJUW7egn30BhS3oZ5kxhF6/RZkxHEQv+wIKvYjs9ePuDVjO8SbBoJTkRAWMvwSXOckzC+BnZnncEac7B3oQocYhaQhoxOtfTcx8MMjLnOSV96DjIjhN8IQ1tVcgKCU5RTCEEbpzAi99BD/xhk6+xwaeMl+gPFMjogmE2qJ0ZoVDCCOcpiD1NiXpzIIxT5reO2DXFOjPg6G2aL1AT/MgFVnVnayD4P0tK51Zge6cEJFnQEVWefbkAE0ZkKQR3zUqhpvPG+SYJ62Tj8waGO1OMNw5tCvgC/N06zD9ebDzGhi8JVBz/J+s9UNtUZKEyfbHhbW7z+F6loBvQcW2DWgyA+WxAizrQGm8AN/DNFZuCyyNF2CqAuaKXeyBKSMiRbsTdQ6KrNYlUGRVx3DnkP6IEgF4EaF59g065lSUJubRMafir3MdDT9sKF8twvM4gW37pl5b83G821iUoAkAQI8jTuuxX/pQ+5MBkbDaiG37pr65lrUWLCXm8eUR6gVas2DXqwR2Gqs6cSVVBAD4XhgJVlJFlB5A0j6TvsoE4BoVi6LIKt056CvrzomeP2/06t6g9rgvg9XDwNGnw/j2ewNNlgPgDvF9bNFwrvnO/wYATLtyn5yvVoIAAAAASUVORK5CYII=');
  background-size:cover;
  image-rendering:pixelated;
  image-rendering:-webkit-optimize-contrast;
  image-rendering:crisp-edges
}

</style>

<div class="pozycja">x: 0, y: 0</div>


<div style="position:absolute;right:100px;top:100px;width:300px;height:500px" id="ruchy"></div>


<div id="window_box">

  <div id="player" class="stand_t"></div>

<div id="map">

  <div class="tree" style="width:32px;height:32px;position:absolute;left:0;top:0"></div>
  <div class="tree" style="width:32px;height:32px;position:absolute;left:0;top:32px"></div>
  <div style="background-color:orange;width:32px;height:32px;position:absolute;left:calc(640px - 32px);top:0"></div>

  <div style="background-color:green;width:32px;height:32px;position:absolute;left:128px;top:0"></div>     <!-- 0x4 -->
  <div style="background-color:green;width:32px;height:32px;position:absolute;left:128px;top:64px"></div>

</div>

</div>
0

Weź spróbuj odtworzyć jakiś minimalny case (wywalając wszystko, co zbędne) i wrzuć na jsfiddle.net, to wtedy można się pobawić ;)

Np. tutaj minimalny przykład, który zrobiłem od zera:
https://jsfiddle.net/ezjxtw0n/

I nie zacina się przy zmianie kierunku.

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