Create Stars Background

In Starling, you can create a particle system with PDParticleSystem, it's usefull, but not everytime.

What if you want create a some background with stars, which fly from left to right, if you create it with PDParticleSystem you get this:

You need wait while stars fill the whole region. Also, this very simple particle system will consume needless cpu time then it need, because PDParticleSystem is very universal.

In this tutorial i will show you how you can create stars background without PDParticleSystem, and filling whole region immediatly after creating particle system.

UPDATE: ParticleSystem.as now contains a method, populate(), which will initialize particles in the system already part-way through their lifespans. This makes things simpler for the application developer, and the code sample below is updated accordingly. – @ericsoco

This example requires direct access to ParticleSystem.mParticles. This pull request details modifications needed for the example to compile. Alternatively, make ParticleSystem.mParticles into a protected var.

All code will be in one file, you can copy and paste it in one file, and run it.

/**
 * We start from routine work to create project and main classes.
 */
package {
 
	import flash.display.Sprite;
	import flash.display.StageScaleMode;
 
	import starling.core.Starling;
 
	[SWF(width=800, height=450, backgroundColor=0, frameRate=60)]
 
	public class StarsExample extends flash.display.Sprite {
 
		public function StarsExample() {
			stage.scaleMode = StageScaleMode.NO_SCALE;
			var s:Starling = new Starling(Main, stage);
			s.showStats = true;
			s.start();
		}
 
	}
 
}
 
import flash.display.BitmapData;
import flash.display3D.Context3DBlendFactor;
import flash.geom.Rectangle;
 
import starling.core.Starling;
import starling.display.Sprite;
import starling.display.Stage;
import starling.extensions.ColorArgb;
import starling.extensions.Particle;
import starling.extensions.ParticleSystem;
import starling.textures.Texture;
 
class Main extends Sprite {
	public function Main() {
		var stars:Stars = new Stars();
		stars.start();
		Starling.juggler.add(stars);
		addChild(stars);
	}	
}
 
/**
 * Our custom particle class.
 */
class StarParticle extends Particle {
	public var speed:Number;
}
 
/**
 * This is stars particle system
 */
class Stars extends ParticleSystem {
 
	// texture for star
	private static var particleTexture:Texture;
 
	private const lifeSpan:Number = 30.0;
	// main color of stars, will be some randomize in initParticle
	private const color:ColorArgb = new ColorArgb(0.5, 0.5, 1.0);
 
	public function Stars() {
		var numParticles:int = 100;
		createTexture();
 
		super(particleTexture, numParticles / lifeSpan, numParticles, numParticles,
			Context3DBlendFactor.SOURCE_ALPHA, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA);
 
		// ParticleSystem.populate() will initialize Particles
		// already part-way through their lifespans.
		populate(numParticles);
	}
 
	// create a simple texture with white "+"
	private function createTexture():void {
		if (particleTexture) return;
		var skin:BitmapData = new BitmapData(8, 8, true, 0);
		var r:Rectangle = new Rectangle();
		r.setTo(2, 1, 1, 3);
		skin.fillRect(r, 0xFFFFFFFF);
		r.setTo(1, 2, 3, 1);
		skin.fillRect(r, 0xFFFFFFFF);
		particleTexture = Texture.fromBitmapData(skin, false);
		skin.dispose();
	}
 
	/**
	 * Create out own particle class instead default
	 */
	override protected function createParticle():Particle {
		return new StarParticle();
	}
 
	/**
	 * This function will initialize particle every time it start its life
	 */
	override protected function initParticle(_particle:Particle):void {
		var particle:StarParticle = _particle as StarParticle;
		var st:Stage = Starling.current.stage;
 
		// reset current time to zero
		particle.currentTime = 0.0;
		// randomize life time 30 + 30 * [-0.5, 0.5] = [15, 45]
		particle.totalTime = lifeSpan + lifeSpan * (Math.random() - 0.5);
 
		// randomize size of star [1.0, 2.5]
		particle.scale = 1.0 + 1.5 * Math.random();
		// place star outsize of left bound
		particle.x = -particleTexture.width * 0.5 * particle.scale;
		// randomize vertical placement of star
		particle.y = st.stageHeight * Math.random();
		// calculate speed, we need add speed*pasedTime to `x` on every advance
		// in the end we should be outside of right bound
		particle.speed = ((st.stageWidth + particleTexture.width * particle.scale) - particle.x) / particle.totalTime;
 
		// randomize star color
		color.red   = 0.5 + 0.25 * (Math.random() * 2.0 - 1.0);
		color.green = 0.5 + 0.25 * (Math.random() * 2.0 - 1.0);
		particle.color = color.toRgb();
	}
 
	/**
	 * Advance every star
	 * when currentTime will be more then totalTime, star will go to
	 * initParticle method and all start again
	 */
	override protected function advanceParticle(_particle:Particle, passedTime:Number):void {
		var particle:StarParticle = _particle as StarParticle;
		particle.x += particle.speed * passedTime;
		particle.currentTime += passedTime;
	}
 
}

When you run it, you immediatly get this: