particle emitter

  ... the case you feel the need for a new feature or want to submit one.

particle emitter

Postby DLSkyNet » Wed Aug 04, 2010 12:30 pm

I already adapted your particlesystem class to work like a moveable/rotatable/attachable emitter. An emitter can be attached to a shape and automatically adapts position and rotation. Particle spawning is also similar to your particlesystem beside that it has no automatic interval and the particles spawn at the current position of their emitter. So far it works good and as needed!

What i would need now is that velocity/acceleration initializers for particles are able to be influenced by (at least) the rotation of their emitter. I hacked something together that works in a very very dirty way but is far from being as elegant as you normally do things :)

Any chance that something similar will be implemented?
DLSkyNet
 
Posts: 12
Joined: Fri Jul 30, 2010 9:03 am

Re: particle emitter

Postby Nicolas Gramlich » Wed Aug 04, 2010 3:24 pm

Hi,

as you are keeping your modifications in private :P I cannot see what you did there.
Did you subclass the ParticleSystem to make it "follow" a Shape :?:
You can even place the ParticleSystem at a specific position of the Sprite, see: CoordinateConversionExample

Making the velocity of a modifier related to the rotation of the sprite should not be much more than a call to FloatMath.sin / FloatMath.cos .

So you are suggesting sth like this should be part of AndEngine itself :?:

Best Regards,
Nicolas
Nicolas Gramlich
Site Admin
 
Posts: 1734
Joined: Mon Jun 07, 2010 6:20 pm
Location: Schriesheim, Germany

Re: particle emitter

Postby DLSkyNet » Wed Aug 04, 2010 4:08 pm

Sorry, did not have the code at hand when I posted!

Here it is:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public class Emitter extends Rectangle {
  2.         // ===========================================================
  3.         // Constants
  4.         // ===========================================================
  5.  
  6.         // ===========================================================
  7.         // Fields
  8.         // ===========================================================
  9.  
  10.         private final ArrayList<Particle> mParticles = new ArrayList<Particle>();
  11.         private final ArrayList<IParticleInitializer> mParticleInitializers = new ArrayList<IParticleInitializer>();
  12.         private final ArrayList<IParticleModifier> mParticleModifiers = new ArrayList<IParticleModifier>();
  13.        
  14.         private final Shape mEmitter;
  15.         private final ILayer mLayer;
  16.         private final Vector2 mOffset;
  17.         private final TextureRegion mTextureRegion;
  18.         private final float mWidth, mHeight, mLimitFactor;
  19.        
  20.         private float mParticlesDueToSpawn;
  21.         private int mParticleModifierCount;
  22.         private int mParticleInitializerCount;
  23.         private Vector2 position;
  24.  
  25.         private RectangleVertexBuffer mSharedParticleVertexBuffer = null;
  26.  
  27.         // ===========================================================
  28.         // Constructors
  29.         // ===========================================================
  30.  
  31.         public Emitter(final Shape pEmitter, final Vector2 pOffset, final ILayer pLayer, final TextureRegion pTextureRegion, final float pLimitFactor) {
  32.                 super(0, 0, 10, 10);
  33.                 this.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
  34.                
  35.                 this.mEmitter = pEmitter;
  36.                 this.mLayer = pLayer;
  37.                 this.mOffset = pOffset;
  38.                 this.mTextureRegion = pTextureRegion;
  39.                
  40.                 this.mLayer.addEntity(this);
  41.  
  42.                 mWidth = 5;
  43.                 mHeight = 5;
  44.                 mLimitFactor = pLimitFactor;
  45.         }
  46.  
  47.         // ===========================================================
  48.         // Getter & Setter
  49.         // ===========================================================
  50.  
  51.         // ===========================================================
  52.         // Methods for/from SuperClass/Interfaces
  53.         // ===========================================================
  54.        
  55.         /*
  56.         @Override
  57.         protected void onPositionChanged() { }
  58.         */
  59.        
  60.         @Override
  61.         protected void onManagedDraw(final GL10 pGL, final Camera pCamera) {
  62.                 for(Particle particle : mParticles) {
  63.                         particle.onDraw(pGL, pCamera);
  64.                 }
  65.         }
  66.        
  67.         @Override
  68.         protected void onManagedUpdate(final float pSecondsElapsed) {
  69.                 super.onManagedUpdate(pSecondsElapsed);
  70.                
  71.                 final float a = this.mEmitter.getRotation();
  72.                 final double d = Math.toRadians(a);
  73.                 final double sin = (float) Math.sin(d);
  74.                 final double cos = (float) Math.cos(d);
  75.                
  76.                 final Vector2 offset = new Vector2();
  77.                 offset.x = (float) (cos * this.mOffset.x - sin * this.mOffset.y);
  78.                 offset.y = (float) (sin * this.mOffset.x + cos * this.mOffset.y);
  79.                
  80.                 position = new Vector2(this.mEmitter.getSceneCenterCoordinates()[0] - mWidth, this.mEmitter.getSceneCenterCoordinates()[1] - mHeight).add(offset);
  81.                
  82.                 this.setPosition(position.x, position.y);
  83.                 this.setRotation(a);
  84.                
  85.                 for(Iterator<Particle> iterator = mParticles.iterator(); iterator.hasNext();) {
  86.                         final Particle particle = iterator.next();
  87.                        
  88.                         final ArrayList<IParticleModifier> particleModifiers = this.mParticleModifiers;
  89.                         for(int i = this.mParticleModifierCount - 1; i >= 0; i--) {
  90.                                 particleModifiers.get(i).onUpdateParticle(particle);
  91.                         }
  92.                        
  93.                         particle.onUpdate(pSecondsElapsed);
  94.                        
  95.                         if(particle.isDead() == true){
  96.                                 iterator.remove();
  97.                         }
  98.                 }
  99.                
  100.                 if(this.mParticlesDueToSpawn > 0) {
  101.                         this.spawnParticles();
  102.                 }
  103.         }
  104.  
  105.         // ===========================================================
  106.         // Methods
  107.         // ===========================================================
  108.  
  109.         public void addParticleModifier(final IParticleModifier pParticleModifier) {
  110.                 this.mParticleModifiers.add(pParticleModifier);
  111.                 this.mParticleModifierCount++;
  112.         }
  113.  
  114.         public void removeParticleModifier(final IParticleModifier pParticleModifier) {
  115.                 this.mParticleModifierCount--;
  116.                 this.mParticleModifiers.remove(pParticleModifier);
  117.         }
  118.  
  119.         public void addParticleInitializer(final IParticleInitializer pParticleInitializer) {
  120.                 this.mParticleInitializers.add(pParticleInitializer);
  121.                 this.mParticleInitializerCount++;
  122.         }
  123.  
  124.         public void removeParticleInitializer(final IParticleInitializer pParticleInitializer) {
  125.                 this.mParticleInitializerCount--;
  126.                 this.mParticleInitializers.remove(pParticleInitializer);
  127.         }
  128.        
  129.         public void spawn(int particles) {
  130.                 this.mParticlesDueToSpawn += particles;
  131.                
  132.                 this.spawnParticles();
  133.         }
  134.        
  135.         private void spawnParticles() {
  136.                 final int particlesToSpawnThisFrame = (int) (Math.random() * (this.mParticlesDueToSpawn * mLimitFactor));
  137.                
  138.                 this.mParticlesDueToSpawn -= particlesToSpawnThisFrame;
  139.  
  140.                 for(int i = 0; i < particlesToSpawnThisFrame; i++){
  141.                         this.spawnParticle();
  142.                 }
  143.         }
  144.  
  145.         private void spawnParticle() {
  146.                 final Particle particle;
  147.                
  148.                 if(this.mSharedParticleVertexBuffer == null) {
  149.                         particle = new Particle(position.x - mWidth, position.y - mHeight * 2, this.mTextureRegion);
  150.                         this.mSharedParticleVertexBuffer = particle.getVertexBuffer(); 
  151.                 } else {
  152.                         particle = new Particle(position.x - mWidth, position.y - mHeight * 2, this.mTextureRegion, this.mSharedParticleVertexBuffer);
  153.                 }
  154.                
  155.                 particle.setBlendFunction(this.mSourceBlendFunction, this.mDestinationBlendFunction);
  156.  
  157.                 final ArrayList<IParticleInitializer> particleInitializers = this.mParticleInitializers;
  158.                 for(int i = this.mParticleInitializerCount - 1; i >= 0; i--) {
  159.                         final String classname = particleInitializers.get(i).getClass().getSimpleName();
  160.  
  161.                         if(classname.equalsIgnoreCase("AccelerationInitializer") || classname.equalsIgnoreCase("VelocityInitializer")) {
  162.                                 final double d = Math.toRadians(this.mEmitter.getRotation() + 225);
  163.                                 final double sin = (float) Math.sin(d);
  164.                                 final double cos = (float) Math.cos(d);
  165.                                
  166.                                 final Vector2 direction = new Vector2(10, 10);
  167.                                
  168.                                 direction.x = (float) (cos * direction.x - sin * direction.y);
  169.                                 direction.y = (float) (sin * direction.x + cos * direction.y);
  170.                                
  171.                                 if(classname.equalsIgnoreCase("VelocityInitializer")) {
  172.                                         particle.setVelocity(direction.x, direction.y);
  173.                                 } else if(classname.equalsIgnoreCase("AccelerationInitializer")) {
  174.                                         particle.setAcceleration(direction.x / 5, direction.y / 5);
  175.                                 }
  176.                         } else {
  177.                                 particleInitializers.get(i).onInitializeParticle(particle);
  178.                         }
  179.                 }
  180.                        
  181.                 final ArrayList<IParticleModifier> particleModifiers = this.mParticleModifiers;
  182.                 for(int i = this.mParticleModifierCount - 1; i >= 0; i--) {
  183.                         particleModifiers.get(i).onInitializeParticle(particle);
  184.                 }
  185.                
  186.                 mParticles.add(particle);
  187.         }
  188.  
  189.         // ===========================================================
  190.         // Inner and Anonymous Classes
  191.         // ===========================================================
  192. }
  193.  
Parsed in 0.020 seconds, using GeSHi 1.0.8.4


So I did not subclass ParticleSystem but changed it a bit :) What I think is extremely "dirty" is the part where the classname is used... Keep in mind, I am not a native Java-Developer :(

Had a look at your example as well, I will double check what I ended up with!

So you are suggesting sth like this should be part of AndEngine itself :?:


And to answer your question: I personally would like to see it in there but it is up to you if you think it is worth being incorporated :)

Keep up your extremely good work!
Dirk
DLSkyNet
 
Posts: 12
Joined: Fri Jul 30, 2010 9:03 am

Re: particle emitter

Postby Nicolas Gramlich » Thu Aug 05, 2010 5:53 pm

Yes, thats actually a little dirty ;)
Also some unnecessary double/float casts :P

At some point we have to decide what to include directly into AndEngine and what not. And I think (while it would still be useful for many) is a little too specific to be in the core of AndEngine.

Best Regards,
Nicolas
Nicolas Gramlich
Site Admin
 
Posts: 1734
Joined: Mon Jun 07, 2010 6:20 pm
Location: Schriesheim, Germany

Re: particle emitter

Postby DLSkyNet » Fri Aug 06, 2010 7:22 am

Thanks for the feedback Nicolas, greatly appreciate it. I already did clean the code up a little yesterday and simplified those dirty little if statements :oops:

I mainly asked you if it would be possible to integrate something like this because I tried to stay as close as possible to built-in functions but then reached a point where I felt (correct me if I am wrong) the need to hack/extend your particleInitializers. Hacking your code is something I personally dislike, it is far to well layed and thought out and you obviously have a lot of things in mind I would not even think of :)

Kind regards and keep up your great work
Dirk
DLSkyNet
 
Posts: 12
Joined: Fri Jul 30, 2010 9:03 am

Re: particle emitter

Postby Timothy Lee Russell » Mon Aug 23, 2010 5:28 am

+1 to a particle emitter that you can attach to a sprite...

I'm using something like this in my Silverlight game MarbleNinja (it is my, this is going to take forever and never be finished, "build an engine from scratch to know how stuff works" project).

http://snoffleware.com/Pages/MarbleNinja.aspx

For anything "real", I use libraries from people who actually know what they're doing (like Nicolas)...but I could definitely see this being a very useful feature in AndEngine.
Timothy Lee Russell
 
Posts: 7
Joined: Mon Aug 09, 2010 6:18 am

Re: particle emitter

Postby Nicolas Gramlich » Tue Oct 05, 2010 12:47 pm

ParticleSystem now has "Emitters" in its constructor.
(You cannot attach them to Sprites but that wouldn't be more than an UpdateHandler. )

I'm not sure if i pushed that change yet (If not yet, i will soon).

Best Regards,
Nicolas
Nicolas Gramlich
Site Admin
 
Posts: 1734
Joined: Mon Jun 07, 2010 6:20 pm
Location: Schriesheim, Germany

Re: particle emitter

Postby frezeed » Tue Jan 17, 2012 10:13 pm

Hi Nicolas

I would really appreciate if you could implement the possibility to rotate an emitter.
For using a particle system as a nozzle for instance it is indispensable to have that functionality... as the nozzle should not rotate immediately with the shape it is attached to...
I think there are quite a lot of situtations it would be really useful.

Greetings from Switzerland
frezeed
 
Posts: 48
Joined: Sat Feb 12, 2011 6:48 pm


Return to Features

Who is online

Users browsing this forum: No registered users and 5 guests