如何从 X 轴移动对象创建 Y 轴轨迹

问题描述 投票:0回答:1

我目前正在 Canvas/Phaser 中制作游戏,正在寻找以下问题的解决方案。

我需要从仅在 X 轴上移动的物体制作 Y 轴轨迹,这样它看起来就像留下了灰尘轨迹。

然而,无论我看到哪里,人们都在用弹跳球或其他 X/Y 移动物体创建轨迹,这不是我想要创建的。

我正在使用 Phaser 游戏框架来开发游戏,如果这个框架内有一个解决方案,那就太好了,但如果你能帮助我提供一个纯画布解决方案/想法,那就太好了!

我希望我为我的解释选择了正确的词语,下面我添加了一张图片和一个小视频来可视化我想要的最终结果。

http://vrrsus.com/static/lastvoyage/web6.jpg

https://youtu.be/Fd7VOACEKig?t=22m32s

javascript html canvas phaser-framework
1个回答
3
投票

我不知道移相器,但由于您还要求提供纯画布示例,因此这里有一个:

FIFO 缓冲区(数组)

您可以使用 FIFO 缓冲区(先进先出)或延迟缓冲区。根据缓冲区的需要存储 x 和/或 y 值。当缓冲区根据预定义的最大值已满时,第一个值将被丢弃。

现在您有了尾部值,并且现在可以按照您想要的方式渲染它们。

演示

下面我们只存储 x。对于尾部定义了一个梯度。这将提供最佳/最平滑的结果,但您也可以创建一个具有与 fifo 缓冲区中的条目匹配的预定义颜色的数组。

请注意,在这种情况下,您只需要渲染实体(无 Alpha),否则每个线段之间的过渡将可见。

这基本上就是它的全部内容。只需使其适合您的渲染周期即可。

性能提示:

  • 如果沿 y 方向移动,则需要跟随渐变。不必每次都创建新的渐变,而是对玩家头部使用 translate() 。这也将翻译渐变线定义。
  • 如果您需要很多/长尾,使用类型化数组可以提高性能。这些比列表/节点数组更快,但不带有移位,因此您需要使用循环指针。
  • 对于视频中的游戏,只需渲染一次单个尾巴,然后将其重复用于其他头部。
  • 不要像演示中那样使用阴影进行发光,而是使用已应用发光的头部图像。

var ctx = document.querySelector("canvas").getContext("2d");
ctx.fillStyle = "#fff";

var fifo = [],           // fifo buffer to cycle older x values through
    max = 30,            // max positions stored in the buffer
    i = 0,               // just for demo, make x cycle on screen
    size = 8,            // draw size
    x = 300,             // x-pos from mousemove event
    y = 30,              // y-pos for player head
    
    // make gradient for the tail stroke:
    // Adjust range as needed
    gradient = ctx.createLinearGradient(0, 30, 0, 280);

// brightest color on top, transparent color at bottom.
gradient.addColorStop(0, "#ccd");
gradient.addColorStop(1, "rgba(200,200,240,0)");

// set up canvas
ctx.strokeStyle = gradient;
ctx.lineWidth = 10;
ctx.lineJoin = "round";
ctx.lineCap = "square";

// glow effect (because we can.. :) )
ctx.shadowColor = "rgba(255,255,255,0.5)";
ctx.shadowBlur = 20;

ctx.canvas.onmousemove = function(e) {
  var rect = this.getBoundingClientRect();
  x = e.clientX - rect.left;
};

// main loop -
(function loop() {

  // push new value(s) to fifo array (for demo, only x)
  fifo.push(x);
  
  // fifo buffer full? Throw out the first value
  if (fifo.length > max) fifo.shift();

  // render what we got;
  ctx.clearRect(0, 0, 600, 480);
  
  ctx.beginPath();
  ctx.moveTo(fifo[0], y + fifo.length * size);
  for(var t = 1; t < fifo.length; t++) {
    ctx.lineTo(fifo[t], y + (fifo.length - t) * size);
  }
  ctx.stroke();
  
  // draw main player head
  ctx.translate(x, y);
  ctx.rotate(0.25*Math.PI);
  ctx.fillRect(-size*0.5, -size*0.5, size*2, size*2);
  ctx.setTransform(1,0,0,1,0,0);
                 
  requestAnimationFrame(loop)
})();
canvas {background:#000}
<canvas width=600 height=360></canvas>

© www.soinside.com 2019 - 2024. All rights reserved.