简体   繁体   English

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

[英]Canvas | How do I create a Y-axis trail, from an X-axis moving object

I'm making a game in Canvas/Phaser at the moment and I'm looking for a solution for the following problem. 我目前正在用Canvas / Phaser开发游戏,正在寻找以下问题的解决方案。

I need to make Y-axis trail from an object that only moves on the X-axis, so that it looks like it leaves a dust trail. 我需要从仅在X轴上移动的对象制作Y轴轨迹,以使其看起来像尘埃轨迹。

However everywhere I look people are creating trail from bouncing balls or other X/Y moving objects, this is not what I want to create. 但是,在我看来,到处都是人们通过弹跳球或其他X / Y运动对象创建轨迹的,这不是我想要创建的。

I am using the Phaser game framework to develop the game, if there is a solution within this framework that would be supurb, but if you could help me with a pure canvas solution/idea that would be great too! 我正在使用Phaser游戏框架开发游戏,如果该框架中有可以替代的解决方案,但是如果您可以通过纯画布解决方案/想法帮助我,那也将很棒!

I hope I chose the right words for my explanation, below I added a picture and a small video that visualizes my wanted end result. 我希望我选择了正确的词来进行解释,下面我添加了一张图片和一个小型视频,这些可视化了我想要的最终结果。

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

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

I do not know phaser, but since you are also asking for plain canvas example, here is one for that: 我不知道相位器,但是由于您还要求提供简单的画布示例,因此这里有一个示例:

FIFO buffer (array) FIFO缓冲区(数组)

You can use a FIFO buffer (first-in-first-out) or a delay-buffer. 您可以使用FIFO缓冲区(先进先出)或延迟缓冲区。 Store the x and/or y value depending on your needs to the buffer. 根据需要将x和/或y值存储到缓冲区。 When the buffer is full according to predefined max value, the first value is thrown out. 当缓冲区根据预定义的最大值已满时,将丢弃第一个值。

Now you have the tail values you and they can now be rendered anyway you want. 现在您有了尾部值,现在就可以根据需要渲染它们。

Demo 演示版

Below we store just x. 在下面,我们只存储x。 For the tail a gradient is defined. 为尾部定义了渐变。 This will give the best/smoothest result, but you can also create an array with predefined color matching the entries in the fifo-buffer. 这将提供最佳/平滑的结果,但是您也可以创建一个预定义的颜色与fifo缓冲区中的条目匹配的数组。

Just be aware that in that case you need to render solids only (no alpha) or the transition between each line segment will be visible. 请注意,在这种情况下,您只需要渲染实体(不渲染Alpha),否则将可见每个线段之间的过渡。

And that is basically everything there is to it. 基本上,这就是一切。 Just make it fit in with your render cycle. 只要使其适合您的渲染周期即可。

Performance tips: 性能提示:

  • If you move in y-direction the gradient need to follow. 如果沿y方向移动,则需要遵循渐变。 Instead of creating a new gradient every time, use translate() for the player head. 与其每次都创建一个新的渐变,不如对玩家头部使用translate()。 This will also translate the gradient line definition. 这还将转换渐变线定义。
  • Using typed array can improve performance if you need many/long tails. 如果您需要长尾巴,使用类型化数组可以提高性能。 These are faster than list/node arrays but does not come with shift so you need to use a cyclic pointer instead. 它们比列表/节点数组快,但不带移位,因此您需要使用循环指针。
  • For the game in the video, just render a single tail once, the reuse it for the other heads. 对于视频中的游戏,只需绘制一条尾巴一次,然后将其重新用于其他头部即可。
  • Instead of using shadow for glow as in the demo, use an image for the head with glow already applied. 与其在演示中使用阴影来发光,不如使用已经应用了发光的头部图像。

 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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM