在HTML 5 Canvas

时间:2016-06-14 04:11:45

标签: javascript html5 canvas

刚编辑我的问题,使其更清晰,更明显。

我正在为我的游戏构建一个背景,我希望我的背景保持在我在背景上绘制的对象的相对相对位置,除了玩家对象,就像FPS游戏,除了我的游戏是2D。我很确定已经完成了一千次,但我不知道在哪里可以找到解决方案。

我的游戏旨在始终将我的角色聚焦在屏幕中央,并在背景的其他部分绘制其他物体。

假设我的背景与9帧的大小一样大,如下所述,一帧是我浏览器屏幕的确切大小。

enter image description here

现在,如果我的角色从第1帧到第9帧,我的角色将始终保持在中心位置,即大约(frame.width / 2,frame.height / 2),因为我的角色会有某种形状。因此屏幕将显示框架' 9'而不是框架' 1'现在。在移动过程中,我将能够看到其他物体移动过来的'来自我的角色。

我使用Map类绘制背景,其render()方法如下:

var drawBackground = function (callback) {      
  callback(this);
}

image.onload = drawBackground(() => {
  var pattern = this.ctx.createPattern(image, 'repeat');
  this.ctx.fillStyle = pattern;
  this.ctx.fillRect(0, 0, this.paintWidth, this.paintHeight);
  // this.ctx.drawImage(image, 0, 0, 10000, 10000);

});
image.src = require('../media/bg.jpg');

现在我的代码出现了问题。因为我的背景(地图)绘图总是重绘我的角色周围的屏幕,我看到的效果就像背景与我的角色一起移动,而其他一切都停留在同一个位置。这看起来并不自然。我希望背景和所有其他对象保持在同一位置。他们不跟我的角色一起移动。我怎么能这样做?

我使用animate()函数来显示动画。

function animate() {

  map.clear(); // clearRect

  ... Some code to track my character...

  map.render();

  character.render();

  requestAnimationFrame(animate);
}

animiate();

编辑:

有些人建议我使用两幅画布。我实际上正在使用两幅画布。

这是我在index.html文件中的设置:

<canvas id="background" style="z-index: 1;">You are viewing the Game Background Canvas -- Update your browser!</canvas>
<canvas id="canvas" style="z-index: 2;">...</canvas>

他们有css样式如下:

#canvas, #background {position: absolute;left: 0px; top: 0px;}

我的背景使用&#39;背景&#39;画布,我的角色使用&#39; canvas&#39;,但我的其他对象也使用&#39; background&#39;画布,他们没有跟我的角色一起移动,只有背景随着我的角色移动,这很奇怪。

2 个答案:

答案 0 :(得分:2)

要绘制背景的方式,您只需要在-character.x, -character.y处绘制背景,假设这是存储字符位置的位置。要使用画布图案执行此操作,只需将画布转换为该位置,然后在原点+角色的位置绘制图案。

需要摆弄这么多东西的原因是因为画布图案的工作方式。它们就像帆布渐变;在你填写的地方并不重要,它几乎就像你使用魔法文本来揭示隐藏的颜色。如果你填补100,100或200,200的位置并不重要;模式始终从0,0开始。所以我们将0,0改为负面玩家的位置,并在正面玩家的位置绘制。

image.onload = drawBackground(() => {
  var pattern = this.ctx.createPattern(image, 'repeat');
  this.ctx.fillStyle = pattern;
  this.ctx.save();
  this.ctx.translate(-character.x, -character.y);
  this.ctx.fillRect(character.x, character.y, this.paintWidth, this.paintHeight);
  this.ctx.restore();
});

根据OP的要求,我会尝试解释这个&#39; magic&#39;更详细。

画布图案是一种填充样式,如纯色或画布渐变。将fillRect等方法想象成一个窗口刮水器,擦拭脏窗口以显示另一侧。使用画布图案时,另一面是反复平铺的图案。现在,想象一下这个图案构成了通过窗口可见的墙壁。 (为了简单起见,想象一下墙壁接近窗户,所以你只能看到窗户的任何擦拭部分的形状投射在墙壁上。)假设你要将窗户的随机盒形状擦拭干净到揭示了背后图案的一部分。在左上角,您不一定会看到其中一个图案拼贴的左上角。你可能会看到中间。或任何随机位。现在,假设我们希望瓷砖的左上角位于从窗口擦除的盒子形状的左上角。我们必须改变壁纸开始平铺的位置。在画布上,我们只使用翻译。我们将画布的原点(x = 0,y = 0)转换为我们需要它的任何东西(这与现在无关),然后我们执行fillRect。但是,fillRect将在新的原点执行。我们不希望这样。因此,我们将x和y设置为开始填充与我们翻译画布原点的量相反。然后,我们可以通过改变我们翻译画布原点的数量来查看我们想要的模式的任何部分。

在我们的例子中,我们通过角色x和y位置的负面版本进行翻译。 (负面使得背景移动角色所做的其他方式。)然后,我们从角色的位置开始绘制模式,因为-character.x + character.x = 0,我们想要从屏幕的左上角。你有它!最后,我们只需要使用context.save和context.restore将画布的原点更改回屏幕的左上角,以获得最终结果!

答案 1 :(得分:0)

使用两个画布用于角色,另一个用于移动背景,您可以使用绝对定位将它们放置在相同位置。

<div style="position: relative;">
  <canvas id="layer1" width="100" height="100" 
    style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
  <canvas id="layer2" width="100" height="100" 
    style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
</div>