为什么缩放后的HTML5画布上的“像素”奇怪地对齐? [英] Why are the 'pixels' on my scaled HTML5 canvas strangely aligned?

查看:91
本文介绍了为什么缩放后的HTML5画布上的“像素”奇怪地对齐?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在写一些基于HTML5 canvas / JS的蛇形克隆,类似于经典的诺基亚蛇。 (这是我的第一个HTML5 canvas / JS游戏,也是我的第一个游戏,我仍然是新手程序员;))

I'm currently writing a little HTML5 canvas/JS based snake clone similar to the classic Nokia Snake. (This is my first HTML5 canvas/JS game as well as my first game, I'm still a novice programmer ;) )

为了保持简单,我决定制作蛇和樱桃的每个部分只有1个像素,但是通常会导致非常小的蛇和樱桃! ;)因此,我决定使用.scale(8,8)缩放画布,以便每个像素为8 * 8。

To keep things simple I decided to make every segment of the snake and the cherry just 1 pixel, however that would normally result in a very tiny snake and cherry! ;) So I decided to scale the canvas with .scale(8,8) so every pixel would be 8*8.

var snake = {
  length: 4,
  direction: "right",
  color: "#9A9A92",
  location: [{x: 32, y: 32}, {x: 31, y: 32}, {x: 30, y: 32}, {x: 29, y: 32}]
}
var cherry = {
  color: "#B1001D",
  x: Math.random()*65,
  y: Math.random()*65
}
var ToDrawOrNotToDraw; //limits the speed of the snake
function moveSnake(eventinfo){
  if(eventinfo.keyCode === 38){
    if(snake.direction === "left" || snake.direction === "right"){
      snake.direction = "up";
    }
  }
  else if(eventinfo.keyCode === 40){
    if(snake.direction === "left" || snake.direction === "right"){
      snake.direction = "down";
    }
  }
  else if(eventinfo.keyCode === 37){
    if(snake.direction === "up" || snake.direction === "down"){
      snake.direction = "left";
    }
  }
  else if(eventinfo.keyCode === 39){
    if(snake.direction === "up" || snake.direction === "down"){
      snake.direction = "right";
    }
  }
}
function draw(){
  requestAnimationFrame(draw);
  if(ToDrawOrNotToDraw === true){
    var snakeDrawerCount = 0;
    ctx.fillStyle = "#006C00";
    ctx.fillRect(0, 0, 64, 64);
    ctx.fillStyle = cherry.color;
    ctx.fillRect(cherry.x, cherry.y, 1, 1);
    ctx.fillStyle = snake.color;
    if(snake.direction === "up"){
      if(snake.location[0].y > 0){
        snake.location.unshift({x: snake.location[0].x, y: snake.location[0].y-1});
        snake.location.pop();
      }
      else {
        snake.location.unshift({x: snake.location[0].x, y: 64});
        snake.location.pop();
      }
    }
    else if(snake.direction === "down"){
      if(snake.location[0].y < 64){
        snake.location.unshift({x: snake.location[0].x, y: snake.location[0].y+1});
        snake.location.pop();
      }
      else {
        snake.location.unshift({x: snake.location[0].x, y: 0});
        snake.location.pop();
      }
    }
    else if(snake.direction === "left"){
      if(snake.location[0].x > 0){
        snake.location.unshift({x: snake.location[0].x-1, y: snake.location[0].y});
        snake.location.pop();
      }
      else {
        snake.location.unshift({x: 64, y: snake.location[0].y});
        snake.location.pop();
      }
    }
    else {
      if(snake.location[0].x < 64){
        snake.location.unshift({x: snake.location[0].x+1, y: snake.location[0].y});
        snake.location.pop();
      }
      else {
        snake.location.unshift({x: 0, y: snake.location[0].y});
        snake.location.pop();
      }
    }
    var snakeDrawerCount = 0;
    while(snakeDrawerCount < snake.location.length){
      ctx.fillRect(snake.location[snakeDrawerCount].x, snake.location[snakeDrawerCount].y, 1, 1);
      snakeDrawerCount++;
    }
    ToDrawOrNotToDraw = false;
  }
  else {
    ToDrawOrNotToDraw = true;
  }
}

var cnvs = document.getElementById("cnvs");
window.addEventListener("keydown", moveSnake, false);
var ctx = cnvs.getContext("2d");
ctx.scale(8,8); //actual size of the canvas is 512 * 512, this gives the 'pixels'/blocks on the canvas a size of 8 * 8, so the canvas will get a size of 64 * 64 'pixels'/blocks
draw();

但是由于某些奇怪的原因,那些大像素(8 * 8缩放像素)似乎重叠了彼此。如此处所示:

But for some strange reason those 'big pixels' (the 8*8 scaled pixels) seem to overlap each other. As can be seen here:



不幸的是,我绝对不知道为什么会这样,因为我之前提到过,我对HTML5 canvas / JS还是很陌生,之前我只是用Qt / QML / C ++和Python编程。我在Firefox 26(在Linux上)和Konqueror(在KDE 4.11)(WebKit)上都试用了我的游戏,两种浏览器似乎都存在问题,因此我认为这与Gecko无关。

Unfortunately I have absolutely no idea why this is happening, because as I mentioned earlier I'm still very new to the HTML5 canvas/JS stuff, I have only programmed in Qt/QML/C++ and Python before. I tried my game in both Firefox 26 (on Linux) and Konqueror (on KDE 4.11)(WebKit), both browsers seem to have the issue, so I don't think it is Gecko-related.

推荐答案

问题来自抗锯齿/子像素化。

The problem comes from anti-aliasing / sub-pixeling.

将樱桃放入董事会以一个随机值。随机值的问题在于它是一个浮点值,因此樱桃将被放置一些小数点的偏移量,因此被浏览器子像素化。

Your cherry is placed in the board at a random value. The problem with the random value is that it's a float value so the cherry will be placed offset with some decimals and therefor sub-pixeled by the browser.

此子像素化的结果也被缩放(当您将其颜色更改为例如白色时更清楚),结果是它与网格不匹配。

When using scale the result of this sub-pixeling is also scaled (which is more clear when you change its color to for example white) and the result is that it doesn't match the grid.

要解决这个问题,只需将Cherry的x和y位置强制为整数,例如这样:

To solve this simply force the x and y position of the cherry to integer, for example like this:

var cherry = {
  color: "#B1001D",
  x: Math.random()*65|0,
  y: Math.random()*65|0
}

在此处摆弄

Fiddle here

| 是按位或运算符,用于强制数字首先是整数,以便能够使用按位或。由于我们将OR设为0,所以输出是相同的(除了切掉浮点小数)。

| is the bitwise OR operator which forces the number first to an integer in order to be able to use bitwise OR. Since we OR with 0, the output is the same (beyond cutting the float decimal).

这篇关于为什么缩放后的HTML5画布上的“像素”奇怪地对齐?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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