2016-03-15 45 views
1

我正在使用一個精靈表單來處理角色。
字符的尺寸是64px寬和128px高,每個動畫10幀。
因此,單個動畫的總寬度是640px寬,128px高。
但是,當我使用以下代碼時,動畫偏移1px,有時按住移動鍵時會閃爍。Canvas drawImage被莫名其妙地抵消了1 Pixel

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 
); 

這裏發生了什麼圖片:
Damn
更改寬度63似乎來解決這個問題,但它並不能解釋爲什麼它做它擺在首位。

完整的代碼可在Codepen
http://codepen.io/Codewoofy/pen/QNGLNj
雪碧表:
oh

全碼:

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>

回答

3

這個問題似乎是,你player.x是一個浮動。這種方式很難說明像素完美的塗料。

player.xdrawImage()或當您更新速度值。

使用位運算符,你可以簡單地做:

player.x += player.velX | 0;

+0

我沒有考慮到這一點,海量感謝。 – Kain

+1

當然!順便說一下,這個問題很重要。一個額外的建議。當你使用'drawImage()'和'clearRect()'時,你不需要開始和關閉路徑。那些額外的操作沒有做任何事情,從長遠來看,如果你把它們拿出來,你會獲得性能。 – 1cgonza

+0

感謝您的建議@ 1cgonza – Kain

相關問題