Android Open Source - Coloring-book Particle System






From Project

Back to project page Coloring-book.

License

The source code is released under:

Apache License

If you think the Android project Coloring-book listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.plattysoft.leonids;
//from  w  ww  .  j  a v a  2 s  .  c om
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import com.plattysoft.leonids.initializers.AccelerationInitializer;
import com.plattysoft.leonids.initializers.ParticleInitializer;
import com.plattysoft.leonids.initializers.RotationInitiazer;
import com.plattysoft.leonids.initializers.RotationSpeedInitializer;
import com.plattysoft.leonids.initializers.ScaleInitializer;
import com.plattysoft.leonids.initializers.SpeeddByComponentsInitializer;
import com.plattysoft.leonids.initializers.SpeeddModuleAndRangeInitializer;
import com.plattysoft.leonids.modifiers.AlphaModifier;
import com.plattysoft.leonids.modifiers.ParticleModifier;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;

public class ParticleSystem {

  private static final long TIMMERTASK_INTERVAL = 50;
  private ViewGroup mParentView;
  private int mMaxParticles;
  private Random mRandom;

  private ParticleField mDrawingView;
  
  private ArrayList<Particle> mParticles;
  private ArrayList<Particle> mActiveParticles;
  private int mEmiterX;
  private int mEmiterY;
  private long mTimeToLive;
  private long mCurrentTime;
  
  private float mParticlesPerMilisecond;
  private int mActivatedParticles;
  private long mEmitingTime;
  
  private List<ParticleModifier> mModifiers;
  private List<ParticleInitializer> mInitializers;
  private ValueAnimator mAnimator;
  private Timer mTimer;

  private ParticleSystem(Activity a, int maxParticles, long timeToLive) {
    mRandom = new Random();
    mParentView = (ViewGroup) a.findViewById(android.R.id.content);
    
    mModifiers = new ArrayList<ParticleModifier>();
    mInitializers = new ArrayList<ParticleInitializer>();
    
    mMaxParticles = maxParticles;
    // Create the particles
    mActiveParticles = new ArrayList<Particle>(); 
    mParticles = new ArrayList<Particle> ();
    mTimeToLive = timeToLive;
  }
  
  /**
   * Creates a particle system with the given parameters
   * 
   * @param a The parent activity
   * @param maxParticles The maximum number of particles
   * @param drawableRedId The drawable resource to use as particle (supports Bitmaps and Animations)
   * @param timeToLive The time to live for the particles
   */
  public ParticleSystem(Activity a, int maxParticles, int drawableRedId, long timeToLive) {
    this(a, maxParticles, a.getResources().getDrawable(drawableRedId), timeToLive);
  }
  
  /**
   * Utility constructor that receives a Drawable
   * 
   * @param a The parent activity
   * @param maxParticles The maximum number of particles
   * @param drawable The drawable to use as particle (supports Bitmaps and Animations)
   * @param timeToLive The time to live for the particles
   */
  public ParticleSystem(Activity a, int maxParticles, Drawable drawable, long timeToLive) {
    this(a, maxParticles, timeToLive);
    if (drawable instanceof BitmapDrawable) {
      Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
      for (int i=0; i<mMaxParticles; i++) {
        mParticles.add (new Particle (bitmap));
      }
    }
    else if (drawable instanceof AnimationDrawable) {
      AnimationDrawable animation = (AnimationDrawable) drawable;
      for (int i=0; i<mMaxParticles; i++) {
        mParticles.add (new AnimatedParticle (animation));
      }
    }
    else {
      // Not supported, no particles are being created
    }
  }
  
  /**
   * Utility constructor that receives a Bitmap
   * 
   * @param a The parent activity
   * @param maxParticles The maximum number of particles
   * @param bitmap The bitmap to use as particle
   * @param timeToLive The time to live for the particles
   */
  public ParticleSystem(Activity a, int maxParticles, Bitmap bitmap, long timeToLive) {
    this(a, maxParticles, timeToLive);    
    for (int i=0; i<mMaxParticles; i++) {
      mParticles.add (new Particle (bitmap));
    }
  }

  /**
   * Utility constructor that receives an AnimationDrawble
   * 
   * @param a The parent activity
   * @param maxParticles The maximum number of particles
   * @param animation The animation to use as particle
   * @param timeToLive The time to live for the particles
   */
  public ParticleSystem(Activity a, int maxParticles, AnimationDrawable animation, long timeToLive) {
    this(a, maxParticles, timeToLive);
    // Create the particles
    for (int i=0; i<mMaxParticles; i++) {
      mParticles.add (new AnimatedParticle (animation));
    }
  }
  /**
   * Adds a modifier to the Particle system, it will be executed on each update.
   * 
   * @param modifier
   * @return
   */
  public ParticleSystem addModifier(ParticleModifier modifier) {
    mModifiers.add(modifier);
    return this;
  }
  
  public ParticleSystem setSpeedRange(float speedMin, float speedMax) { 
    mInitializers.add(new SpeeddModuleAndRangeInitializer(speedMin, speedMax, 0, 360));    
    return this;
  }
  
  public ParticleSystem setSpeedModuleAndAngleRange(float speedMin, float speedMax, int minAngle, int maxAngle) {
    mInitializers.add(new SpeeddModuleAndRangeInitializer(speedMin, speedMax, minAngle, maxAngle));    
    return this;
  }
  
  public ParticleSystem setSpeedByComponentsRange(float speedMinX, float speedMaxX, float speedMinY, float speedMaxY) {
    mInitializers.add(new SpeeddByComponentsInitializer(speedMinX, speedMaxX, speedMinY, speedMaxY));    
    return this;
  }
  
  public ParticleSystem setInitialRotationRange (int minAngle, int maxAngle) {
    mInitializers.add(new RotationInitiazer(minAngle, maxAngle));
    return this;
  }
  
  public ParticleSystem setScaleRange(float minScale, float maxScale) {
    mInitializers.add(new ScaleInitializer(minScale, maxScale));
    return this;
  }
  
  public ParticleSystem setRotationSpeed(float rotationSpeed) {
    mInitializers.add(new RotationSpeedInitializer(rotationSpeed, rotationSpeed));
    return this;
  }
  
  public ParticleSystem setRotationSpeedRange(float minRotationSpeed, float maxRotationSpeed) {
    mInitializers.add(new RotationSpeedInitializer(minRotationSpeed, maxRotationSpeed));
    return this;
  }
  
  public ParticleSystem setAccelerationModuleAndAndAngleRange(float minAcceleration, float maxAcceleration, int minAngle, int maxAngle) {
    mInitializers.add(new AccelerationInitializer(minAcceleration, maxAcceleration, minAngle, maxAngle));
    return this;
  }
  
  public ParticleSystem setAcceleration(float acceleration, int angle) {
    mInitializers.add(new AccelerationInitializer(acceleration, acceleration, angle, angle));
    return this;
  }
  
  /**
   * Configures a fade out for the particles when they disappear
   * 
   * @param duration fade out duration in miliseconds
   * @param interpolator the interpolator for the fade out (default is linear)
   */
  public ParticleSystem setFadeOut(long milisecondsBeforeEnd, Interpolator interpolator) {
    mModifiers.add(new AlphaModifier(255, 0, mTimeToLive-milisecondsBeforeEnd, mTimeToLive, interpolator));
    return this;
  }
  
  /**
   * Configures a fade out for the particles when they disappear
   * 
   * @param duration fade out duration in miliseconds
   */
  public ParticleSystem setFadeOut(long duration) {
    return setFadeOut(duration, new LinearInterpolator());
  }
  
  /**
   * Starts emiting particles from a specific view. If at some point the number goes over the amount of particles availabe on create
   * no new particles will be created
   * 
   * @param emiter  View from which center the particles will be emited
   * @param particlesPerSecond Number of particles per second that will be emited (evenly distributed)
   * @param timeToLive miliseconds the particles will be displayed
   * @param emitingTime time the emiter will be emiting particles
   */
  public void emit (int x, int y, int particlesPerSecond, int emitingTime) {
    // Setup emiter
    configureEmiter(x,y);
    mActivatedParticles = 0;
    mParticlesPerMilisecond = particlesPerSecond/1000f;
    // Add a full size view to the parent view    
    mDrawingView = new ParticleField(mParentView.getContext());
    mParentView.addView(mDrawingView);
    
    mDrawingView.setParticles (mActiveParticles);
    mCurrentTime = 0;
    mEmitingTime = emitingTime;
    startAnimator(new LinearInterpolator(), emitingTime+mTimeToLive);
  }
  
  /**
   * Starts emiting particles from a specific view. If at some point the number goes over the amount of particles availabe on create
   * no new particles will be created
   * 
   * @param emiter  View from which center the particles will be emited
   * @param particlesPerSecond Number of particles per second that will be emited (evenly distributed)
   */
  public void emit (int x, int y, int particlesPerSecond) {
    // Setup emiter
    configureEmiter(x,y);
    mActivatedParticles = 0;
    mParticlesPerMilisecond = particlesPerSecond/1000f;
    // Add a full size view to the parent view    
    mDrawingView = new ParticleField(mParentView.getContext());
    mParentView.addView(mDrawingView);
    mEmitingTime = -1; // Meaning infinite
    mDrawingView.setParticles (mActiveParticles);
    mCurrentTime = 0;
    mTimer = new Timer();
    mTimer.schedule(new TimerTask() {      
      @Override
      public void run() {
        onUpdate(mCurrentTime);
        mCurrentTime += TIMMERTASK_INTERVAL;
      }
    }, 0, TIMMERTASK_INTERVAL);
  }
  
  /**
   * Launches particles in one Shot
   * 
   * @param emiter View from which center the particles will be emited
   * @param numParticles number of particles launched on the one shot
   */
  public void oneShot(int x, int y, int numParticles) {
    oneShot(x, y, numParticles, new LinearInterpolator());
  }
  
  /**
     * Launches particles in one Shot using a special Interpolator
   * 
   * @param emiter View from which center the particles will be emited
   * @param numParticles number of particles launched on the one shot
   * @param interpolator the interpolator for the time
   */
  public void oneShot(int x, int y, int numParticles, Interpolator interpolator) {
    configureEmiter(x,y);
    mActivatedParticles = 0;
    mEmitingTime = mTimeToLive;
    // We create particles based in the parameters
    for (int i=0; i<numParticles && i<mMaxParticles; i++) {
      activateParticle(0);
    }
    // Add a full size view to the parent view    
    mDrawingView = new ParticleField(mParentView.getContext());
    mParentView.addView(mDrawingView);
    mDrawingView.setParticles (mActiveParticles);
    // We start a property animator that will call us to do the update
    // Animate from 0 to timeToLiveMax
    startAnimator(interpolator, mTimeToLive);
  }

  private void startAnimator(Interpolator interpolator, long animnationTime) {
    mAnimator = ValueAnimator.ofInt(new int[] {0, (int) animnationTime});
    mAnimator.setDuration(animnationTime);
    mAnimator.addUpdateListener(new AnimatorUpdateListener() {      
      @Override
      public void onAnimationUpdate(ValueAnimator animation) {
        int miliseconds = (Integer) animation.getAnimatedValue();
        onUpdate(miliseconds);
      }
    });
    mAnimator.addListener(new AnimatorListener() {      
      @Override
      public void onAnimationStart(Animator animation) {}
      
      @Override
      public void onAnimationRepeat(Animator animation) {}
      
      @Override
      public void onAnimationEnd(Animator animation) {
        cleanupAnimation();
      }
      
      @Override
      public void onAnimationCancel(Animator animation) {
        cleanupAnimation();        
      }
    });
    mAnimator.setInterpolator(interpolator);
    mAnimator.start();
  }

  private void configureEmiter(int x, int y) {
  //  int[] location = new int[2];
    int[] parentLocation = new int[2];
  //  emiter.getLocationInWindow(location);
    mParentView.getLocationInWindow(parentLocation);
  //  mEmiterX = location[0] + emiter.getWidth()/2 - parentLocation[0];
  //  mEmiterY = location[1] + emiter.getHeight()/2 - parentLocation[1];
    mEmiterX = x;
    mEmiterY = y;
  }

  private void activateParticle(long delay) {
    Particle p = mParticles.remove(0);    
    // Initialization goes before configuration, scale is required before can be configured properly
    for (int i=0; i<mInitializers.size(); i++) {
      mInitializers.get(i).initParticle(p, mRandom);
    }
    p.configure(mTimeToLive, mEmiterX, mEmiterY);
    p.activate(delay, mModifiers);
    mActiveParticles.add(p);
    mActivatedParticles++;
  }

  private void onUpdate(long miliseconds) {
    while (((mEmitingTime > 0 && miliseconds < mEmitingTime)|| mEmitingTime == -1) && // This point should emit
         !mParticles.isEmpty() && // We have particles in the pool 
         mActivatedParticles < mParticlesPerMilisecond*miliseconds) { // and we are under the number of particles that should be launched
      // Activate a new particle
      activateParticle(miliseconds);      
    }
    for (int i=0; i<mActiveParticles.size(); i++) {
      boolean active = mActiveParticles.get(i).update(miliseconds);
      if (!active) {
        Particle p = mActiveParticles.remove(i);
        i--; // Needed to keep the index at the right position
        mParticles.add(p);
      }
    }
    mDrawingView.postInvalidate();
  }

  private void cleanupAnimation() {
    mParentView.removeView(mDrawingView);
    mDrawingView = null;
    mParentView.postInvalidate();
    mParticles.addAll(mActiveParticles);
  }
  
  public void cancel() {
    if (mAnimator != null && mAnimator.isRunning()) {
      mAnimator.cancel();
    }
    if (mTimer != null) {
      mTimer.cancel();
      mTimer.purge();
      cleanupAnimation();
    }
  }
}




Java Source Code List

com.kidsgames.gamebase.DrawerActivity.java
com.kidsgames.gamebase.DrawingView.java
com.kidsgames.menu.DrawerSliderActivity.java
com.kidsgames.menu.FixedSpeedScroller.java
com.kidsgames.menu.FixedSpeedViewPager.java
com.kidsgames.menu.MainMenu.java
com.kidsgames.menu.SlideAdapter.java
com.kidsgames.utils.ResourceId.java
com.plattysoft.leonids.AnimatedParticle.java
com.plattysoft.leonids.ParticleField.java
com.plattysoft.leonids.ParticleSystem.java
com.plattysoft.leonids.Particle.java
com.plattysoft.leonids.initializers.AccelerationInitializer.java
com.plattysoft.leonids.initializers.ParticleInitializer.java
com.plattysoft.leonids.initializers.RotationInitiazer.java
com.plattysoft.leonids.initializers.RotationSpeedInitializer.java
com.plattysoft.leonids.initializers.ScaleInitializer.java
com.plattysoft.leonids.initializers.SpeeddByComponentsInitializer.java
com.plattysoft.leonids.initializers.SpeeddModuleAndRangeInitializer.java
com.plattysoft.leonids.modifiers.AccelerationModifier.java
com.plattysoft.leonids.modifiers.AlphaModifier.java
com.plattysoft.leonids.modifiers.ParticleModifier.java
com.plattysoft.leonids.modifiers.ScaleModifier.java