Jump to content

Controlling Particles


Recommended Posts

Hi everybody,


I am currently playing around with babylon and it's really fun. I managed to reboot an old game project of mine based on the the awesome tutorial from temechon (http://pixelcodr.com/tutos/physics/physics.html) and a bunch of other great (basic) tutorials from the github wiki. The game is basically a remake of the classic dynablaster (aka bomberman). You control a player avatar that can place bombs to destroy blocks. 


Here is what I got so far: http://p215008.mittwaldserver.info/bbomberman/


I am kinda happy with it for now, but I got a little trouble controlling the particles that make the effect for the bomb detonation. I want them to stop on blocks they destroy and not just go trough them. I tried to mange that by setting a certain particle life time based on the distrance to the block that the bomb is going to destroy (line 544 in the code). Most of the time it works but sometimes it's just not accurate enough.




I am wondering now if there is a better way to control the length of this "ray of fire" or how i could improve the accurity.



A bit more info on how to play if somebody wants to try it out:


- you control the green player with WASD, plant bombs with SPACE

- for the blue player its 8456 and 0 for planting bombs

- you destroy blocks, sometimes you find powerups

- blue powerup is planing an additional bomb (you start with a limit of 1 bomb at a time, pick up a blue power up and you get to lay 2 bombs simultaneously)

- yellow power up increases the range of the fire blast (the problem seems to occur mostly with longer rays)

- you can't kill yourself or the other play (yet)

Yeah, well, that's it. I hope somebody can help me out here. I love playing with babylon and I really want to make that game happen :D
PS: Sorry for the messy code, I guess I'll have to go over it and structure it a bit better.
PPS: if you have any suggestion in general how to improve the code or for cool features for the game, I would love to hear them!!
Link to comment
Share on other sites

Ohw, my topic is finally visible :D I even posted it again because I didn't see that it has to be confirmed by an admin on my first post (sorry for that!!). I already updated the online version today after playing around with the values on the particle system for a long time and I think the problem got a bit better by now. I still have to test it some more to make sure it's okay now (If anybody else wants to try it, please let me know if it still happends or you find any other bugs).


@Deltakosh, I like that idea! So I could check the distance that the particle has traveled and then dispose it as soon it reached it's destination, right? Or could I even check for collisions? But how would I call such a function that processes every particle? Is there a tutorial or some kind of documentation on how to do that? I figured out that the particle system provides an array of the particles, so I guess I could check all the particles, on every frame, using the registerBeforeRender function and then iterating over all the particles. Hmm, I am wondering: if I have maybe 15 bombs exploding at the same time (4 players support in the future, each player can lay several bombs, bombs triggering each other) and each of them is emitting... lets say... 20 particles (probably even more). I would get at least 300 particles that I have to check and calculate the distance on every frame. Isn't that a heavy heavy task regarding performance?


I hope I got your idea right, if not just tell me ;)

Link to comment
Share on other sites

And about your particule problem, I would throw a ray in the 4 directions from the bomb, and detect the distance of the nearest wall in each direction.

If the wall is far away (distance > 10 for example) for a direction, the particule ray is not thrown in this direction.


Ok, you do it already. Don't mind me please :)

Link to comment
Share on other sites

Thanks for the feedback guys! I will keep you updated for sure (and I will probably have more questions in the future :P ).


@Temechon So it was not just a coincidence that your tutorial was pretty much perfectly what I needed to get started, eh? ;) How far are you with your bomberman? I would love to see it!


And yeah, I am already checking the distance to the fixed boxes, but not to the outer walls yet, but that's already on the ToDo list ;) I am really curious how you solve some of the little problems with this kind of game. I try to keep it simple but sometimes it just doesn't work as smoothly as I had expected that it would. From your tutorial I know that your code is a lot more structured than mine and you seem to know a lot  about how to use babylon, too, so I guess I could learn quite a bit from your approach.

Link to comment
Share on other sites

Hi iiceman... welcome to the forum!  Fun project you have going, there.  If you wish, take a look at this...


See how I replaced the default BABYLON.ParticleSystem.prototype._update(newParticles)... with my own slightly modified version of _update?   (editor line 220)

This doesn't solve your problem, but it allows you to more-easily experiment with modifications to the _update function.  The _update function, beit custom or default, services every particle.  Consider it an animation function.  I don't know if you'll have enough framerate time to do much work in there,  but maybe.

Let's look at the base particle class...


Take note of the .age and .lifeTime properties... and remember that you can make a particleSystem spawn YOUR OWN version of a particle.  Just make your own particle.js and <script> it into your project AFTER you bring in babylon.js.  Your custom Particle will be used by all created particleSystems from then-on. 

Keep in mind that a particle's geometry/mesh... is NOT defined in the base particle class (duh?).  :)  Particle geometry is done in the particleSystem class.  Don't worry about any of that.  Just note that a particle has an .age and a .lifeTime.

Now look at particleSystem...


See the default _update function at line 138?  That's the one I over-ride in my demo.

With a CUSTOM _update function (should you decide to try one)... you could MAYBE shoot a ray at each particle... and if its distance from the emitter is greater than xxx, you could maybe set the particle.lifeTime to 0.  Then, the next frame, the _update function would see that the particle's .age is greater than its .lifeTime (line 145), and would determine that it is time for that particle to die (actually, it gets pushed into the spare particles tank called _stockParticles).

But, _update has to run fast.  You don't get to waste much time inside that FOR-loop, or your particles will get boggy.  I don't know if you will have enough time to fire-up a measuring ray on each currently-being-serviced particle.

In my demo, I wanted to override color1, color2, colorDead, and use a random color instead.   (this._colorizer func.)

And I wanted to "twinkle" the particle by doing mid-flight random particle sizing.  (this._sizer func)

You might use a this._checkIfParticleNeedsToDie(particle) function.  But maybe DON'T call a function, and instead, do all your work on particle... right there inside the _update function FOR-loop.  You need speed!  (No, not the kind you find at truckstops.)  ;)

What a way to go!  Have your .lifeTime property set to 0 (if distance from emitter > xxx).  :D

Anyhooooo... I just wanted to show you how to hijack the default ParticleSystem.prototype._update function, so you could do some easy bog-testing.  I hope I didn't tell you anything incorrect.  :)  Good luck, and keep us posted on your discoveries, if you please.  Party on!

Link to comment
Share on other sites

@iiceman My game is not very much developped... I have a player walking in a map, and he can pose some bombs.. And that's all for now. I spend a lot of time on small details, like the game GUI, player animations, and so on. I want a game that can be played on keyboard and gamepad, with a lot of bonus... I want a lot of things :) 


I'm working on it, it's a big side project, and I want it to be something before showing it to the world :)

Unlike you, I don't use the physics engine. My tutorial was only because the question 'How can i move with activated physics ?' was asked a lot on this forum, and I thought it could help (and it helped you ! ;) )
Link to comment
Share on other sites

@Temechon, I see, I see, well good luck with it then! Let me know if you decide that it is good enough to be shown :D


@Wingnut, first of all: those Christmas trees absolutely beautiful, very nice!! Second: that really helped a lot I think! Thanks A LOT for the detailed explanation (I need it explained just like that so that I get what's going on). I think I understood most of it and I started to play around. It seems to do what I expected it to do.. at least after hours of trying things out :P




I got those two light sabers each of the blades ends after a certain distance from it's emitter. I just calculate the distance (that's good enough for my bomberman, too) within the FOR-loop so I don't need any ray casting. Performance seems to be good as far as I can tell, but please let me know if any of you experiences performance problems. The only thing that I couldn't really figure out yet: how do the particles get the colorDead color? They didn't seem to chance color when I set their life time to 0 after they reach the calculated distance.


But if that's not possible, it's no problem, I can use it just like that for my game I think. I learned a bit more about Babylon once again today (still a lot left that I don't know).

Link to comment
Share on other sites

Hey, I like this answer ! I might use it for my game ;)


If DK could create a function customParticleUpdate(part) for a particle system it would be huge (this function could be added in the for loop for performance reasons).


I will create a PR for this if you don't mind. It's done, waiting for validation.

Link to comment
Share on other sites

Thanks iiceman.  Hey, I like your distance measuring code.  I'm going to borrow that.  :)


You could remove your line 89 and then change your line 90 to...

var distance = this.emitter.position.subtract(particle.position).length();

I think that works, too... but no promises.  Good looking light sabers!  Well done!


If you look at area 152-155 of your demo, you will see the code for caulculating colors, and it is done on new particles (which have un-modified particle.lifeTime's).  ColorDead is the color that the particles change to... just before they die.  By rushing-along the death of your particles, they never reach the time for them to change to their dead color. 


Really, colorDead might be better named colorElderly or colorDying.  :)  You could also think of it as color3, but I don't think it is interpolated the same way as color1->color2.  I think (maybe incorrectly) that colorDead was meant to simulate fireworks... where particles have a "burnout color"... a final "sizzle" before they die.  *shrug*


When you over-ride the particle.lifeTime, you circumvent the linear interpolator (LERP) that calculates colorStep.  You kill the particle before the interpolation has time to complete.  This is why you should REALLY try to use particleSystem.maxLifeTime instead of my hacky idea.


Look at line 139 and 143.

139. var emitPower = randomNumber(this.minEmitPower, this.maxEmitPower);143. particle.lifeTime = randomNumber(this.minLifeTime, this.maxLifeTime);

I wonder what would happen if you removed the random... like this...

139. var emitPower = this.maxEmitPower;143. particle.lifeTime = this.maxLifeTime;

Then, maybe, you could remove your measuring system and go back to a time-based measuring... and it would be consistent and accurate (no random).  And then, your color1, color2, and colorDead should start working correctly, doing 3 colors across the length of the saber beams. 


BUT, time-based measuring could vary from machine to machine.  Maybe distance measuring should be a "backup" to time measuring, in case the user has a lightning-fast computer.  I could easily be wrong on this (and oh so many other things).  :)


I made another version.




In this version, I remove the distance measuring, and I used a separate particleSystem for each saber.  Pre-createBeam call, I made the particleSystem, and then made color1, color2, colorDead.  THEN I called createBeam, sending those things as arguments/parameters. 


In our hijacked function, I also removed those 2 randoms, as mentioned earlier (but line numbers changed).  And... I adjusted the emitBox settings in line 70 and 71... to make the beams emit from the ends of the hilts.  (I used their Y values to make a beam start-location offset.)


And now, the 3 colors work.  At least I THINK they do, but I have no clue where the yellow is coming from. *scratch scratch*  This is a fun experiment, huh?  I like it.

Link to comment
Share on other sites

Yeah, it is a fun experiment for sure! :D


I played around a bit more and if you are right I won't have to modify the update function at all, because all you did is fix the value for lifeTime and emitPower and it seems to work. So we could achieve the same by setting min and max values for emitPower and lifeTime to the same value, aight? Well, I am gonna try it out within the bomberman game and we will see how it turns out. None the less I learn alot and I am sure it will come handy sooner or later ;)


By the way, here is the latest version of the lightsaber playground. I didnt change much, except I that removed the the overwritten update function AND ADDED SPARKLES for the colliding lightsabers :D




Thanks again for the help guys!!

Link to comment
Share on other sites

Wow, awesome, very nice... and super fast integration! Thank you! I am gonna play around with it as soon as I have some time. :D


By the way, in the docs you wrote:


  • startPositionFunction = (worldMatrix: Matrix, positionToUpdate: Vector3): This function can be defined to specify initial direction for every new particle. By default, this function is defined with the following code: ...

This "direction" is supposed to be "position", right? Or did I get something wrong here?

Link to comment
Share on other sites


iiceman:  So we could achieve the same by setting min and max values for emitPower and lifeTime to the same value, right?

Yeah, good deducing!  That eliminates the affect of the randomNumber calls.  Well done.





This function will be called after regular update (age, position, color, etc.).

Is this what we want?  I think I would have made it be instead of the regular update. 


Using an 'additional' update function that gets called after the default update, we are looping through all particles... twice.  The default does it once, and then the custom does it again.  I could see where that might be boggy. 


I think we might see folks rarely use this 'additional' update method because they will get better speeds by doing the complete function over-ride like I have been doing.  But, I'm not sure.  A custom (additional) update is an interesting idea, but maybe it is 'inini'.


inini = infeasible'n'implausible'n'impractical.  Cute, eh?  ;)  I'm trying to invent a new word.


If I am thinking correctly, a particle keeps 'state' on certain values (I hope I'm using 'state' correctly here).  Colorstep, age, and possibly angle values... change on a particle... each time it gets updated.  When a particle first arrives at a user-made custom update function, its colorStep has already been set to a value that takes it from color1 to color2 linearly across the span of the particle's lifeTime.  Let's pretend the user initially set color1 as red and color2 as blue.  Now the user sets particle.color = green in the custom update.  This would completely screw-up colorStep which is set to interpolate from red to blue.


It seems that, under certain conditions, the custom update is having to reverse (revert?) activity that was done moments ago by the default update function.  If it does that, the action in the default update... was a waste of time.  The custom update reversed the change that the default update made.  The two update functions are actually doing battle with each other... under certain circumstances.


Maybe I'm thinking this wrong, though.  That's common for me.  :)

Link to comment
Share on other sites

@iiceman: You're right I meant position and not direction (copy/paste hell)

@Wingnutt: I'm ok with a full replacement. So far it is an addition to standard behavior but we can replace it. In this case the default behavior is:

this.updateFunction = (particles: Particle[]): void => {    for (var index = 0; index < particles.length; index++) {        var particle = particles[index];        particle.age += this._scaledUpdateSpeed;        if (particle.age >= particle.lifeTime) { // Recycle            this._stockParticles.push(particles.splice(index, 1)[0]);            index--;            continue;        }        else {            particle.colorStep.scaleToRef(this._scaledUpdateSpeed, this._scaledColorStep);            particle.color.addInPlace(this._scaledColorStep);            if (particle.color.a < 0)                particle.color.a = 0;            particle.angle += particle.angularSpeed * this._scaledUpdateSpeed;            particle.direction.scaleToRef(this._scaledUpdateSpeed, this._scaledDirection);            particle.position.addInPlace(this._scaledDirection);            this.gravity.scaleToRef(this._scaledUpdateSpeed, this._scaledGravity);            particle.direction.addInPlace(this._scaledGravity);        }    }}

And you can override it by what ever you want :)


Sounds better like this!

Link to comment
Share on other sites

:)  Whatever you think is right, dk.  No matter how it's done, it's a new place to play.  Yay!   iiceman has contributed to framework core!  Way to go, iiceman!  You'll now receive some "I Contributed to Core" patches and stickers, and your certificate of contribution, and a Fudruckers gift certificate!  (not really).  But still, way to go! 


And thanks for the mod, dk!

Link to comment
Share on other sites

I played around with the particles and created a cool spinning double helix by modifying the update function for two different particle systems and letting them follow a sinus for y and cos for z path... looked pretty cool and i wanted to show it to you guys but somehow I seem to have hit F5 when I was pretty much done and it was all gone. I did the same yesterday trying to recreate my first attempt... and i think I hit F5 again :-/ I must still be drunk from the new years party. Now I give up... but looked cool and everything worked well, I think.

Link to comment
Share on other sites

Been there.  It sucks.  :/  Sorry.


I don't know if you were here for "The Seeking of Faery Dust" series of Wingnut goofiness... that started here.  There's probably 8-12 posts in a row... all involving particles, and lots of demos and playgrounds.  Bad coding all the way... it's all I know.  But... I really enjoy torturing the babylon particleSystem.  It has the abilities to make some strange looking scenes.  Tour through that area if you get bored, iiceman.  Seizure warning.  :)


It (d)evolved into emitting standard babylon shapes... planes, boxes, and having them tumble on all 3 axis.  Standard particles tumble on only one axis, and its not on an axis that can cause a flash of light to hit the camera - a sparkle. 


Later the tumbling mesh idea was deemed unbearably slow and that's when the fake sparkling via sizing and coloring in the update function... was tried and liked, at least by me.  It gave me the best sparkle for the cpu load.


But tumbling planes was fun to try.  It's ALL fun, as you know.  :)  If you're flying emitters with sine and cosine... yeah... you got particle madman disease.  Ain't it great?


The 2 particle demos on post #400 seem to be broken.  *scratch scratch*  They once worked.  hmmm.


Moebius pattern, eh?  cooooool.

Link to comment
Share on other sites

I checked your faery dust out and it's cool to see how it evolved. The Möbius pattern sounds cool, but I am not sure if I know how to do it. would be alot of trying out and see what's happening. It's too bad that I don't have much time to play around now that the vacation is over and work started again, but I made some progress with the bomberman and it's getting better step by step. Still so many ideas and so little time (and skill :-/ ).


By the way: I have some questions concerning bomberman stuff. Should I make a new thread for every problem/question that I have or is it better to start one thread for all my questions like you did with your chronicles?


Its stuff like rotation of meshes when physics is involved (I read the other threads I found but I think I need a more detailed explanation since I did not get it to work), but its also things like applying and modifying textures, how to do calculations like converting a direction vector to Euler rotation, and probably MANY MANY other questions :P

Link to comment
Share on other sites

Here's a Möbius pattern if you need it :

(my  *3, *2, *2 on each axis are optionnal radius factors)

 // Möbius ribbon : http://fr.wikipedia.org/wiki/Ruban_de_M%C3%B6bius path1 = []; path2 = []; for (var i = 0; i <= 60; i++) {  var v = 2.0 * Math.PI * i / 60;  path1.push( (1 + Math.cos(v/2) / 2) * Math.cos(v) * 3, (1 + Math.cos(v/2) / 2) * Math.sin(v) * 2, Math.sin(v/2) / 2 * 2);  path2.push( (1 - Math.cos(v/2) / 2) * Math.cos(v) * 3, (1 - Math.cos(v/2) / 2) * Math.sin(v) * 2, - Math.sin(v/2) / 2  * 2); } var mesh7 = new BABYLON.Mesh("mesh7", scene); createRibbon(mesh7, path1, path2);
Link to comment
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.

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.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...