How to implement a motion blur?


(Zeeshan Ahmad) #1

Does any body have any idea of the best way of motion blur (or just blur, for that matter) on an entity?

I have a pad in my game that moves (VarTween) when the user clicks at a specific x position. It would be really cool to have a light horizontal motion blur during the tween.


(Zachary Lewis) #2

You can use the BlurFilter on your BitmapData to add a blur.


(rostok) #3

Check out the code below. It creates and updates a buffer of Entity positions. Rendering is done by drawing same graphics from earliest position to current one. Assuming that graphics is an Image its alpha can be modified to make furthermost sprites almost invisible. I guess this code could even be converted to be some smart Class that other motionblurred entites may derive from.

package  
{
	import net.flashpunk.*;
	import net.flashpunk.graphics.*;
	import net.flashpunk.tweens.misc.*;
	import net.flashpunk.utils.*;
	
	/**
	 * ...
	 * @author rostok
	 */
	public class MotionBlurred extends Entity 
	{
		private var steps:uint = 5;
		private var positions:Vector.<Number> = new Vector.<Number>;
		
		public function MotionBlurred(x:Number=0, y:Number=0, graphic:Graphic=null) 
		{
			this.x = x;
			this.y = y;
			this.graphic = graphic;
			for (var i:int = 0; i < steps; i++) {
				positions.push(x);
				positions.push(y);
			}
		}
		
		override public function update():void 
		{
			positions.push(x);
			positions.push(y);
			if (Input.mousePressed) {
				clearTweens();
				var t:VarTween;
				t = new VarTween();
				t.tween(this, "x", Input.mouseX + world.camera.x, 0.5);
				addTween(t, true);
				t = new VarTween();
				t.tween(this, "y", Input.mouseY + world.camera.y, 0.5);
				addTween(t, true);
			}			
			super.update();
		}
		
		override public function render():void 
		{
			var lastX:Number = positions.shift();
			var lastY:Number = positions.shift();
			for (var i:int = 0; i < steps; i++) {
				Image(graphic).alpha = i / steps;
				Draw.graphic(graphic, FP.lerp(lastX, x, i / steps), FP.lerp(lastY, y, i / steps));
			}
			Image(graphic).alpha = 1;
			super.render();
		}
	}
}

init:

var e:Entity = FP.world.add(new MotionBlurred(0, 0, new Image(FP.getBitmap(embedClass))));


(Zeeshan Ahmad) #4

I don’t understand much how the above works. But I have sort of adapted the code into my class, and I have to say the results are awesome! (- although it was not quite the motion blur I was expecting, this is quite cool as well) Thanks


(rostok) #5

It is pretty simple. The trick is to record all entity’s positions in a buffer (positions var). To simplify things I use one Vector to store both x and y coordinates. In update I store those values and in render method I remove them. Without this you would just could at least get entity position from the previous frame which is obviously not enough. Maybe instead of Vector some linked list would be more appropriate but this was just a proof-of-concept.

Anyway play with “steps” parameter and maybe you could also use BlurFilter that Zach mentioned.