yeti logo icon
Close Icon
contact us
Yeti postage stamp
We'll reply within 24 hours.
Thank you! Your message has been received!
A yeti hand giving a thumb's up
Oops! Something went wrong while submitting the form.

Android Particle System: Creating basic effects for games

By
Rudy Mutter
-
July 7, 2011

Currently Yeti is working on a cross platform mobile game called Ripcord. The game’s main experience involves the player sky diving in different levels, where they need to avoid harmful objects in the sky, like birds and planes, while collecting coins. I’ve been building the Android version of the game and got the basic game play completed, but the game was looking flat.

I had not built any animations or effects that helped give the user the feeling of falling or feedback when they collide with an object so I went on a Google hunt for an android particle system tutorial/example/library that I could use. There were plenty of great websites involving particle systems for use with OpenGL, but none if you were just working with the regular android graphic library (which I am currently).

I figured at this point that I would just give it a try myself, while looking at one of the OpenGL examples for some guidance. The first effect I wanted to accomplish was for something in the background that would make it seem like the sky diver was falling. I also wanted to make whatever I built to be reusable so that it would not be hard to create the effect for the player colliding with another object.

The first class I created was ParticleSystem. This class took in a starting y position, a starting x position, an upper bound for the x position, a speed, an upper bound for the speed, number of particles, and the bitmap of the particle. This first effect would have every particle starting at the bottom of the screen and shooting upwards to create a wind like effect. The particles, when they reached the top of the screen would be removed and replaced with a new particle at the bottom of the screen at a random x position. They would also be given a random speed, within the speed range specified.

package com.yeti.ripcord;import android.graphics.Bitmap;import android.graphics.Canvas;public class ParticleSystem {    private Particle particles[];    private int startYPos;    private int startXPos;    private int xPosRange;    private int minSpeed;    private int speedRange;    private Bitmap bitmap;    public ParticleSystem(int startYPos, int startXPos,     int xPosRange, int minSpeed, int speedRange,     Bitmap bitmap) {     this.startYPos = startYPos;     this.startXPos = startXPos;     this.xPosRange = xPosRange;     this.minSpeed = minSpeed;     this.bitmap = bitmap;     this.speedRange = speedRange;     particles = new Particle[numParticles];        for (int i = 0; i < particles.length; i++) {            particles[i] = new Particle(startYPos, startXPos,             xPosRange, minSpeed, speedRange,             bitmap);        }    }    public void doDraw(Canvas canvas) {     for(int i = 0; i < particles.length; i++) {     Particle particle = particles[i];     particle.doDraw(canvas);     }    }    public void updatePhysics(int altDelta) {     for(int i = 0; i < particles.length; i++) {     Particle particle = particles[i];     particle.updatePhysics(altDelta);     // If this particle is completely out of sight     // replace it with a new one.     if(particle.outOfSight()) {     particles[i] = new Particle(startYPos, startXPos,     xPosRange, minSpeed, speedRange,     bitmap);     }     }    }}

Besides creating the initial particles in the constructor of the class, there would be two more functions updatePhysics and doDraw that will delegate to every particle in the system for their respective method calls. As you could guess, updatePhysics involves moving the particle’s position and deciding if it needs to be replaced, while doDraw draws the particle onto the canvas.

The Particle class was created next, where it also had the methods updatePhysics and doDraw as well as outOfSight. This method contains the logic for deciding if a particle is completely out of the canvas bounds. updatePhysics for this effect slowly decreases the y position of the particle while checking to see if it is out of sight. The variable passed into this method, distChange, is the amount of distance the player has fallen in the last game loop. This way, if the player starts to fall slower, the effect will also move slower, which looks pretty cool. doDraw draws the particle’s bitmap at its current x and y position.

package com.yeti.ripcord;import android.graphics.Bitmap;import android.graphics.Canvas;class Particle {    private int xpos;    private int ypos;    private int speed;    private Bitmap bitmap;    public Particle(int startYPos, int startXPos,     int xPosRange, int minSpeed, int speedRange,     Bitmap bitmap) {     xpos = startXPos + (int) (Math.random() * xPosRange);     ypos = startYPos);     this.speed = (int) (minSpeed + Math.random() * speedRange);     this.bitmap = bitmap;    }    public void updatePhysics(int distChange) {     ypos -= distChange * speed;    }    public void doDraw(Canvas canvas) { canvas.drawBitmap(bitmap, xpos, ypos, null);    }    public boolean outOfSight() {     return ypos <= -1 * bitmap.getHeight();    }}

To use this particle system, you simply create a new one, with parameters appropriate for the effect you’re trying to make. Whenever your game loop calls methods that update the physics for your game or draws your game on the canvas, you need to call the respective methods on the particle system as well. From here it is very easy to change the update physics logic to do many different things depending on what kind of effects you’d like to create. In another post I will cover extending the ParticleSystem to create collision effects, where particles explode from the objects the sky diver hits.

Rudy Mutter is a CTO + Founding Partner at Yeti. He found his passion for technology as a youth, spending his childhood developing games and coding websites. Rudy now resides in the Yeti Cave where he architects Yeti’s system and heads up project production.

Follow Rudy on Twitter.

You Might also like...

colorful swirlsAn Introduction to Neural Networks

Join James McNamara in this insightful talk as he navigates the intricate world of neural networks, deep learning, and artificial intelligence. From the evolution of architectures like CNNs and RNNs to groundbreaking techniques like word embeddings and transformers, discover the transformative impact of AI in image recognition, natural language processing, and even coding assistance.

A keyboardThe Symbolicon: My Journey to an Ineffective 10-key Keyboard

Join developer Jonny in exploring the Symbolicon, a unique 10-key custom keyboard inspired by the Braille alphabet. Delve into the conceptualization, ideas, and the hands-on process of building this unique keyboard!

Cross-Domain Product Analytics with PostHog

Insightful product analytics can provide a treasure trove of valuable user information. Unfortunately, there are also a large number of roadblocks to obtaining accurate user data. In this article we explore PostHog and how it can help you improve your cross-domain user analytics.

Browse all Blog Articles

Ready for your new product adventure?

Let's Get Started