画布drawImage莫名其妙地偏移了1个像素 [英] Canvas drawImage is inexplicably offset by 1 Pixel

查看:133
本文介绍了画布drawImage莫名其妙地偏移了1个像素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做一个使用角色精灵表的画布游戏.
角色的尺寸为64px宽和128px高,每个动画10帧.
因此,单个动画的总宽度为640px宽和128px高.
但是,当我使用以下代码时,动画偏移1px,有时在按住移动键时会闪烁.

I'm working on a canvas game that's using a sprite sheet for the character.
The dimensions of character is 64px wide and 128px high with 10 frames per animation.
So the total width of a single animation is 640px wide and 128px high.
However when I use the following code, The animation is offset by 1px, Sometimes flashing when I hold down a movement key.

player.width = 64;  
player.height = 128;  
player.x = canvas.width / 2;
player.y = canvas.height / 2;


ctx.drawImage(
    LoadedImages.player_sprite,
    64, // This is offset by 1px when moving. 63px fixes it.
    128,
    player.width,
    player.height,
    player.x,
    player.y,
    player.width,
    player.height
);  

这是发生的情况的图片:

将宽度更改为63似乎可以解决问题,但是并不能解释为什么它首先要这样做.

Here's a picture of what happens:

Changing the width to 63 seems to fix the problem, But it doesn't explain why it's doing it in the first place.

完整的代码可在Codepen上获得
http://codepen.io/Codewoofy/pen/QNGLNj
雪碧表:

The full code is available on Codepen
http://codepen.io/Codewoofy/pen/QNGLNj
Sprite Sheet:

完整代码:

var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;

// jQuery Objects
var $canvas = $("#canvas");
var $debug = $("#debug");

var KEY = {
   W: 1,
   UP: 38,
   LEFT: 39,
   RIGHT: 37,
   SPACE: 32,
   SHIFT: 16
};

var COLOR = {
   DARKRED: "#9C1E33",
   WHITE: "#FFFFFF"
}

var MESSAGE = {
   UNDEFINED: "",
   PRELOAD_ATTEMPT: "Attempting to preload: ",
   ERROR_IMAGE_PRELOAD: "Unable to preload images.",
   SUCCESS_IMAGE_PRELOAD: "Images successfully preloaded."
}

// Images
var Images = {
   player_sprite: "http://h.dropcanvas.com/30npe/Talia-Sheet-Fix.png",
   main_background: "http://h.dropcanvas.com/9kgs1/background_main.png"
}
var LoadedImages = {};

// Dictionaries.
var game = {};
game.enviroment = {};
game.canvas = $canvas[0];
game.canvas.height = 500;
game.canvas.width = 700;
var ctx = game.canvas.getContext('2d');
var player = {};

// Debug
game.debug = function(msg) {
   if (msg == "") msg = MESSAGE.UNDEFINED;
   $debug.prepend(msg + "<br />");
}

// Preloader.
game.loadImages = function() {
   LoadedImages = {};
   Object.keys(Images).forEach(function(path) {
      game.debug(MESSAGE.PRELOAD_ATTEMPT + path);
      var img = new Image;
      img.onload = function() {
         LoadedImages[path] = img;
         if (Object.keys(LoadedImages).length == Object.keys(Images).length) {
            game.onImagesLoaded();
         }
      }
      img.onerror = function() {
         game.onFailedPreload();
      }
      img.src = Images[path];
   });
}

game.onFailedPreload = function() {
   game.debug(MESSAGE.ERROR_IMAGE_PRELOAD);
}

game.onImagesLoaded = function() {
   game.debug(MESSAGE.SUCCESS_IMAGE_PRELOAD);
   game.game_update();
}

game.onLoad = function() {
   // Game settings
   game.keys = [];
   game.running = false;
   game.lastUpdate = 0;
   // Enviroment
   game.enviroment.gravity = 0.5;
   game.enviroment.friction = 0.9;
   // Player settings
   player.name = "Talia";
   player.color = COLOR.DARKRED;
   player.direction = 'L';
   player.width = 64;
   player.height = 128;
   player.speed = 4;
   player.walkspeed = 4;
   player.sprintspeed = 10;
   player.jumping = false;
   player.animation_frame = 0;
   player.velX = 0;
   player.velY = 0;
   player.x = 0;
   player.y = 0;
   // Player Stats
   player.health = 100;
   player.mana = 100;
   player.maxhealth = 100;
   player.maxmana = 100;

   game.loadImages();
}

/* Update the game every frame */
game.game_update = function() {
   // Sprint
   if (game.keys[KEY.SHIFT]) {
      console.log(LoadedImages);
      player.speed = player.sprintspeed;
   } else {
      player.speed = player.walkspeed;
   }
   // Jump
   if (game.keys[KEY.UP] || game.keys[KEY.SPACE]) {
      if (!player.jumping) {
         player.jumping = true;
         player.velY = -player.walkspeed * 2;
      }
   }
   // Left
   if (game.keys[KEY.LEFT]) {
      player.direction = "L";
      if (player.velX < player.speed) {
         player.velX++;
      }
   }
   // Right
   if (game.keys[KEY.RIGHT]) {
      player.direction = "R";
      if (player.velX > -player.speed) {
         player.velX--;
      }
   }
   // Gravity and Friction
   player.velX *= game.enviroment.friction;
   player.velY += game.enviroment.gravity;
   player.x += player.velX;
   player.y += player.velY;

   // Collisions
   // LEFT RIGHT
   if (player.x >= game.canvas.width - player.width) { // Check Right Collision
      player.x = game.canvas.width - player.width;
   } else if (player.x <= 0) { // Check Left Collision
      player.x = 0;
   }
   // UP DOWN
   if (player.y >= game.canvas.height - player.height) {
      player.y = game.canvas.height - player.height;
      player.jumping = false;
   }

   // Draw Objects
   game.draw_background();
   game.draw_player();

   // Request next animation frame
   requestAnimationFrame(game.game_update);
}

game.draw_player = function() {
   ctx.beginPath();
   ctx.drawImage(LoadedImages.player_sprite, 64, 128, player.width, player.height, player.x, player.y, player.width, player.height);
   /*
   if (player.direction == "R") {
      ctx.drawImage(LoadedImages.player_sprite, 65, 128, player.width, player.height, player.x, player.y, player.width, player.height);
   } else if (player.direction == "L") {
      ctx.drawImage(LoadedImages.player_sprite, 63, 0, player.width, player.height, player.x, player.y, player.width, player.height);
   }
   */

   ctx.closePath();
}

game.draw_background = function() {
   ctx.beginPath();
   ctx.clearRect(0, 0, game.canvas.width, game.canvas.height);
   ctx.closePath();
}

game.draw_UI = function() {
   ctx.beginPath();

   ctx.closePath();
}

/* Listeners */
document.body.addEventListener("keydown", function(e) {
   game.keys[e.keyCode] = true;
});

document.body.addEventListener("keyup", function(e) {
   game.keys[e.keyCode] = false;
});

/* Load Game */
window.addEventListener("load", function() {
   game.onLoad();
});

body,
html {
   position: relative;
}

canvas {
   border: 1px solid black;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width="700" height="500"></canvas>Use Arrow keys to move.
<p id="debug"><p>

推荐答案

问题似乎是您的player.x是浮点型.这样很难解释像素完美的涂料.

The issue seems to be that your player.x is a float. That way is hard to account for pixel perfect paints.

圆形player.x或使用速度更新值时.

Round player.x on the drawImage() or when you update the value with velocity.

使用按位运算符,您可以简单地执行以下操作:

Using a bitwise operator, you could simply do:

player.x += player.velX | 0;

这篇关于画布drawImage莫名其妙地偏移了1个像素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆