SarahJ

Fading trail

Recommended Posts

Hi,

I'm trying to create a fading trail using minimal graphic/sprite objects. Right now I have an object that is always moving at the same speed and direction, and I would like it to have a trail behind it.

I've looked at the mouse trail demo, however, I feel it is unnecessary to use have to use so many objects just to make a linear trail (the trail I need will always be in the same direction), as I'm going to need 10+ trails at once. Here are 2 of the options I've thought of so far:

  1.  Draw a rectangle graphics object, then use an alpha mask to create a fading an effect:
    • 1320950324_Untitled(14).png.7ffbee07d261d23c26be99ea55239335.png
  2. Have a really long sprite as a trail, then use set its frame to the length I need.

Which one would be more practical to use, and are there any better methods?

Thanks!

Share this post


Link to post
Share on other sites

Basically what do I want: I create gradient for Canvas2d or make it manually, and then upload that canvas with fromCanvas() or from() or more sophisticated method.

Alternatively: there is difficult implementation of meshes with colored shaders in https://github.com/gameofbombs/pixi-heavenhttps://gameofbombs.github.io/examples-heaven/#/mesh/rope-colored.js . Modify it to affect sprites-only and make it simple if you think you have enough time to learn it.

Here, I gave you ALL the code I have regarding gradients. You can wait for other guys but as far as I know no one else cares about gradients except you and I. Maybe there's a lurker :)

Again, PHOTOSHOP is your best friend. I still dont understand why dont you like "make a texture in photoshop" approach.

Share this post


Link to post
Share on other sites

What about create you gradient in other canvas.
https://www.w3schools.com/graphics/canvas_gradients.asp

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

// Create gradient
var grd = ctx.createLinearGradient(0, 0, 200, 0);
grd.addColorStop(0, "red");
grd.addColorStop(1, "white");

// Fill with gradient
ctx.fillStyle = grd;
ctx.fillRect(10, 10, 150, 80);

and than, create `generate` a texture from this canvas context ?

Am sure it can work ...  but at the expense of performance.
I do not remember which one, but there is a rpgmaker plugin that used this process with pixijs.

Share this post


Link to post
Share on other sites

OK, I was wrong, I forgot about @jonforum

5 minutes ago, jonforum said:

Am sure it can work ...  but at the expense of performance.
I do not remember which one, but there is a rpgmaker plugin that used this process with pixijs.

Cache black-white or transparent-opaque grad one time and use tint/darktint on it ;)

Gradients are basically 1d textures, use them with height=1. Vertex-coloring is not as versatile, you cant put linearRGB in it, for example.

Share this post


Link to post
Share on other sites

I will interest by this later, because I remember that I will need to look this at it in depth.
In fact I wanted to be able to generate texture guardian to apply this on a text box to generate a fadding mask text when scrolling the box.
And the box are dynamic size, so i can not use photoshop in this context!, scaling the image will also scale the linear mask picture and give weird result.

FKZDHOOb_o.jpg
it's an old test with a filter for fake linear, but the subject is interesting.
But am not energized to test it now . 😴

Share this post


Link to post
Share on other sites

Thanks for all of your quick replies, I never knew you could create a gradient like that! Back to the original question though, once the gradient is created, would it be right to use it as an alpha mask at the end of a trail?

Share this post


Link to post
Share on other sites

Here's the second one, super-v5 stuff: https://pixijs.io/examples/?v=v5.0.0-rc.2#/textures/gradient-resource.js

Yes, you can use it as an alphamask. Why do you need though? Your trail is simple rectangle, right?

In fact, that's one of common mask use-cases in Flash: alpha gradients. Its shame we cant replicate all that Flash stuff even after several years of coding.

Share this post


Link to post
Share on other sites

Masks is to be avoided as far as possible.
I use 1 or two only in some context, and my cpu get sick very fast.
So for me , no i dont think masks will be more performance friendly than the demo mouse trail  .

but I suppose it can vary in many contexts.
The best and most painful solution will be to test the 2 and check the cpu performance with a debugger SDK or web tools.

but in my personals tests, result told me to avoid as much as possible the use of mask in my project.

image.thumb.png.ec16239a8d36c4c673f2e182e50de0d9.png

wihout i get ~ 10 to 12% work

 

Share this post


Link to post
Share on other sites

Thanks, everyone for helping, I've managed to make a working example of it as a trail now: codepen.io/anon/pen/YgBapq

Just one question: With my current code, the trail pops up immediately behind the source. I would like it to act as the mouse trail example; growing as the source first moves, like this:

817341703_Untitled(15).png.34877b79b9c3b74ff4e7cf73a2f3b786.png

I originally wanted to use a frame, but it seems like you can't crop a sprite, only a texture, and I don't want to have to make a new texture every frame. What would be the best way to do this?

Share this post


Link to post
Share on other sites

I mean "texture.frame.x= something; texture._updateUvs();" that'll trigger sprite onTextureUpdate automatically, because "sprite._textureID" will differ from "texture._updateID"

That's why we removed underscore from function name - users should use it when they change frame, its not a private API anymore.

Share this post


Link to post
Share on other sites

Finished! :) Here's the code for anyone who is looking for a solution in the future:

var app = new PIXI.Application({
  width: window.innerWidth,
  height: window.innerHeight,
  antialias: true
});

document.body.appendChild(app.view);

app.renderer.view.style.position = "absolute";
app.renderer.view.style.display = "block";
app.renderer.backgroundColor = 0x000000;

var source = new PIXI.Graphics(); // The source of the trail (Red triangle)
source.speed = 4; // How fast the source moves
var angle = Math.random() * Math.PI * 2; // Give the source a random direction

source.velocity = { // Set it's velocity to move it in the random direction
  x: Math.cos(angle) * source.speed,
  y: Math.sin(angle) * source.speed
};
source.pivot.set(0.5);
source.rotation = angle;

source.position.set(window.innerWidth / 2, window.innerHeight / 2); // Start in the center of the window
source.beginFill(0xff0000);
source.drawPolygon([ // Draw a triangle
  40, 0,
  0, 15,
  0, -15
]);
source.endFill();
app.stage.addChild(source);

var gradient = createGradient('white', 'rgba(255, 255, 255, 0)', 250, 20); // Create the gradient texture

var trail = PIXI.Sprite.from(gradient); // Create a sprite from the texture
trail.anchor.y = 0.5;
trail.rotation = source.rotation + Math.PI;
app.stage.addChild(trail);

var length = 0; // Length starts off with 0, grows with the source moving

app.ticker.add((delta) => {
  source.position.x += source.velocity.x;
  source.position.y += source.velocity.y;

  trail.position.x = source.position.x;
  trail.position.y = source.position.y;
  if (length + 2 < 250) {
    length += source.speed; // Constrain the length to not go over 250
    gradient.frame = new PIXI.Rectangle(0, 0, length, 20);
    gradient._updateUvs(); // Update the sprite after setting a new frame in the texture
  }
});

function createGradient(start, end, width, height) {
  var canvas = document.createElement('canvas');
  canvas.width = width;
  canvas.height = height;

  var ctx = canvas.getContext('2d');
  var gradient = ctx.createLinearGradient(0, 0, width, 0);
  gradient.addColorStop(0, start);
  gradient.addColorStop(1, end);

  ctx.fillStyle = gradient;
  ctx.beginPath(); // Draws it in a triangular shape
  ctx.moveTo(width, height / 2);
  ctx.lineTo(0, 0);
  ctx.lineTo(0, height);
  ctx.fill();

  return PIXI.Texture.fromCanvas(canvas);
}

 

Share this post


Link to post
Share on other sites

@ivan.popelyshev Instead of

On 3/25/2019 at 7:31 PM, ivan.popelyshev said:

texture.frame.x= something; texture._updateUvs();

Could you edit the sprites textures frame directly, like:

var sprite = new PIXI.Sprite(<gradient texture>);
sprite.texture.frame = new PIXI.Rectangle(<...>); // Edit it directly

Or is this bad practice?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.