Анимация Javscript мигает

#javascript #canvas

#javascript #холст

Вопрос:

Я создаю игру на javascript, и анимированный спрайт мигает, когда он движется, я думаю, это связано со скоростью анимации, потому что мне также нужно ее замедлить. вот мой код для обновления анимации

      var playerani = setInterval(function(){
               
                if(animate == true){
                    if(aniframe == maxframes){
                    aniframe = 1
                }else{
                    aniframe  = 1;
                }
                
                
                }
           

                if(controller.left == true){
                    animate = true;
                     window.aniimgY = 576; 
                }else if(controller.up == true){
                    animate = true;
                     window.aniimgY = 512; 
                }else if(controller.down == true){
                    animate = true;
                     window.aniimgY = 640; 
                }else if(controller.right == true){
                    animate = true;
                     window.aniimgY = 704; 
                }else{
                    animate = false;
                    aniframe = 0;
                }
            
         
            },10)
          
  

Вот таблица спрайтов

И Gif анимации

Вы можете протестировать игру здесь

Комментарии:

1. Ну, нет никакого способа протестировать ваш код. Но на первый взгляд я бы сказал, что вы должны использовать requestAnimationFrame вместо setInterval того, чтобы вызывать свой цикл, поскольку requestAnimationFrame пытается поддерживать частоту обновления на уровне 60 кадров в секунду.

2. Кажется, это лучший способ анимации игрока, но он все равно мигает, когда он движется

3. Как я уже сказал, нет способа протестировать ваш код. Попробуйте создать фрагмент в редакторе вопросов с помощью <> кнопки на панели инструментов и сделать свой код работоспособным. Или создайте jsfiddle, codepen или другой ресурс, в котором мы можем запускать ваш код.

4. Вы можете протестировать его на ryangrube.com/projects/tilegame

5. Это выглядит как отключение из-за одной ошибки. У вас есть только 9 кадров, 8, если вы не учитываете первый незанятый кадр, но ваш maxframe увеличивается до 10, что приведет к тому, что изображение не будет отображаться для одного или двух кадров в зависимости от того, как вычисляются смещения atlas. Если ваш максимальный кадр установлен на 8, это должно это исправить, но, как сказал @EmielZuurbier, мы не можем точно сказать, что происходит без кода.

Ответ №1:

Как предложил @HanYolo, установите var maxframes = 8; :

 var aniframe = 0;
var maxframes = 8;
var animate = false;


window.aniimg = document.getElementById("aniimg1")

var timer = null;
var aniTimer = null;
var levelnum = 0;

var img = document.getElementById("img")
var img2 = document.getElementById("img2")

var c = document.getElementById("c");
var ctx = c.getContext('2d')
var props = document.getElementById("props");
var prps = c.getContext('2d')
var tilesize = 32;
var tiles = 10;


player = {
  size: 10,
  x: 150,
  y: 150,
  v: 2,
}

controller = {
  up: false,
  right: false,
  left: false,
  down: false,
  keyParse: function(key) {
    switch (key) {
      //keydowns
      case 38:
        this.up = true;
        break;
      case 37:
        this.left = true;
        break;
      case 39:
        this.right = true;
        break;
      case 40:
        this.down = true;
        break;

    }
  },
  keyStop: function(key) {
    switch (key) {
      //keydowns
      case 38:
        this.up = false;
        break;
      case 37:
        this.left = false;
        break;
      case 39:
        this.right = false;
        break;
      case 40:
        this.down = false;
        break;

    }

  }
}





function drawlvl() {
  for (y = 0; y < lvl[levelnum].length; y  ) {
    for (x = 0; x < lvl[levelnum][y].length; x  ) {
      switch (lvl[levelnum][y][x]) {
        case 0:
          //nw grass
          var imgvar = img
          var sx = 32;
          var sy = 192;
          break;
        case 1:
          //w dirt
          var imgvar = img
          var sx = 224;
          var sy = 160;
          break;
        case 2:
          //nw top dirt
          var imgvar = img
          var sx = 128;
          var sy = 96;
          break;
        case 3:
          //nw bottom dirt
          var imgvar = img2
          var sx = 95;
          var sy = 320;
          break;
        case 4:
          //lvl up dirt
          var imgvar = img
          var sx = 224;
          var sy = 160;
          break;
        case 5:
          //lvl down dirt
          var imgvar = img
          var sx = 224;
          var sy = 160;
          break;
        case 6:
          //w water
          var imgvar = img
          var sx = 0;
          var sy = 416;
          break;
        case 7:
          //w water side left
          var imgvar = img
          var sx = 0;
          var sy = 288;
          break;
        case 8:
          //w water side right
          var imgvar = img2
          var sx = 223;
          var sy = 128;
          break;
      }
      ctx.drawImage(imgvar, sx, sy, 32, 32, x * tilesize, y * tilesize, tilesize, tilesize)
    }
  }
}

walkable_blocks = [1, 6, 7, 8]
walkable_props = [0, 8, 9, 10, 11, 12]
lvlup_blocks = [4]
lvldown_blocks = [5]


function gameLoop() {


  if (controller.up == true) {
    player.newY = player.y - player.v
  } else if (controller.left == true) {
    player.newX = player.x - player.v
  } else if (controller.right == true) {
    player.newX = player.x   player.v
  } else if (controller.down == true) {
    player.newY = player.y   player.v
  } else {
    player.newY = player.y;
    player.newX = player.x;


  }




  function playerani() {



    if (animate == true) {
      if (aniframe == maxframes) {
        aniframe = 1
      } else {
        aniframe  = 1;
      }


    }
    if (window.aniimgY == null) {
      window.aniimgY = 640;
    }

    if (controller.left == true) {
      animate = true;
      window.aniimgY = 576;
    } else if (controller.up == true) {
      animate = true;
      window.aniimgY = 512;
    } else if (controller.down == true) {
      animate = true;
      window.aniimgY = 640;
    } else if (controller.right == true) {
      animate = true;
      window.aniimgY = 704;
    } else {
      animate = false;
      aniframe = 0;
    }


  }

  player.col = Math.floor((player.newX   5) / tilesize)
  player.row = Math.floor((player.newY   5) / tilesize)

  tileval = lvl[levelnum][player.row][player.col]
  propval = propsArr[levelnum][player.row][player.col]
  ctx.fillStyle = "black"
  if (walkable_blocks.includes(tileval) amp;amp; walkable_props.includes(propval)) {

    player.y = player.newY;
    player.x = player.newX;



    if (player.x <= 0) {
      player.x = 0
    }
    if (player.y <= 0) {
      player.y = 0
    }
    if (player.x   player.size >= c.width) {
      player.x = c.width - player.size;
    }
    if (player.y   player.size >= c.height) {
      player.y = c.height - player.size;
    }

  } else if (lvlup_blocks.includes(tileval)) {
    document.getElementById("body").style.ainmation = "fadeInAnimation";
    document.getElementById('body').style.animationPlayState = "running";
    if (timer == null) {
      timer = setTimeout(function() {
        levelnum  ;
        player.x = 280;
        player.y = 150;
        timer = null;
      }, 2500)
      if (aniTimer == null) {
        aniTimer = setTimeout(function() {
          document.getElementById("body").style.animationPlayState = "paused";
          clearTimeout(aniTimer)
          aniTimer = null;
        }, 5000)
      }
    } else {

    }
  } else if (lvldown_blocks.includes(tileval)) {
    document.getElementById("body").style.ainmation = "fadeInAnimation";
    document.getElementById('body').style.animationPlayState = "running";
    if (timer == null) {
      timer = setTimeout(function() {
        levelnum--;
        player.x = 33;
        player.y = 150;
        timer = null;
      }, 2500)
    }
    if (aniTimer == null) {
      aniTimer = setTimeout(function() {
        document.getElementById("body").style.animationPlayState = "paused";
        clearTimeout(aniTimer);
        aniTimer = null;

      }, 5000)
    }

  } else {
    player.y = player.y;
    player.x = player.x;

    if (player.x <= 0) {
      player.x = 0
    }
    if (player.y <= 0) {
      player.y = 0
    }
    if (player.x   player.size >= c.width) {
      player.x = c.width - player.size;
    }
    if (player.y   player.size >= c.height) {
      player.y = c.height - player.size;
    }
  }
  ctx.fillRect(0, 0, c.width, c.height)
  drawlvl()
  drawprops()
  drawEnemy()
  playerani()

  ctx.drawImage(window.aniimg, 64 * (Math.floor(aniframe)), window.aniimgY, 64, 64, player.x - 16, player.y - 16, 48, 48)

}




var gameintertval = setInterval(function() {
  gameLoop()
}, 10)

document.addEventListener('keydown', function(event) {
  controller.keyParse(event.keyCode)
})
document.addEventListener('keyup', function(event) {
  controller.keyStop(event.keyCode)
})  
 body { 
    zoom: 100%;
    animation: fadeInAnimation ease 5s; 
    animation-play-state: paused;
    animation-iteration-count: infinite;
} 

  
@keyframes fadeInAnimation { 
    0% { 
        opacity: 1; 
    } 
    50% { 
        opacity: 0; 
     } 
    100% {
        opacity: 1;
    } 
} 
canvas{
    position: absolute;
    
}
#props{
    z-index: 1000;
}
#c{
    z-index: -1000;
}  
 <html>

<head>
  <title>TileGame</title>
  <base href="http://ryangrube.com/projects/tilegame/">
</head>

<body id="body">
  <img id="img" style="display: none;" src="TileSet_V1.png">
  <img id="img2" style="display: none;" src="TileSet_V2.png">
  <img id="img3" style="display: none;" src="TileSet_V3.png">
  <img id="aniimg1" style="display: none;" src="no_dagger.png">
  <img id="aniimg2" style="display: none;" src="dagger.png">

  <canvas id="c" width="320" height="320" style="background-color: black;border:3px solid black;"></canvas>
  <canvas id="props" width="320" height="320" style="border:3px solid black;"></canvas>

  <script src="map.js"></script>
  <script src="props.js"></script>
  <script src="drawprops.js"></script>
  <script src="enemy.js"></script>
  <script src="drawenemy.js"></script>

</body>

</html>