Constellation – A flocking experiment

This week I saw Flight 404’s “Swarm Behavior” on vimeo –

Swarm behavior from flight404 on Vimeo.

Yet another awesome video from Robert, using his Cinder framework. Cool!
In the description, he mentions the particle’s behavioral rules –

1) If I am far away from my neighbors, move towards them.
2) If I am too close to my neighbors, move away from them.
3) If I am neither too close or too far from my neighbors, move with them.

So I decided to try and implement these rules in Flash. The idea changed a few times, and ended up looking like an interactive constellation app. So here it is! It’s still pretty rough around the edges – but I’m quite pleased with how it’s developing.

See and edit the code over on Wonderfl

CODE

package{

	[SWF(width="465", height="465", frameRate="50")]

	import flash.events.*;
	import flash.events.KeyboardEvent;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Stage;
	import flash.geom.Point;
	import flash.filters.BlurFilter;
	import flash.filters.ColorMatrixFilter;
	import flash.filters.ConvolutionFilter;
	import flash.filters.GlowFilter
	import flash.text.TextField;
	import com.bit101.components.*;
	
 	public class BFCWonderfl extends MovieClip {
		
		//Vars - 
		//You can play with these ones - 
		private var numBoids:int=20;
		//Boids closer than this will feel crowded!
		private var minDist:int=90;
		//Boid further away than another than this will be lonely!
		private var maxDist:int=100;
		//This is how fast the boids can move. TOP SPEED!
		private var maxSpeed:Number = 3;
		//This is how much boids influence each other - lower number = more influence
		private var divideBy:int=100;
		//Shall the boids slow down with friction?
		private var enableFriction:Boolean = true;
		private var friction:Number = 0.9;
		//Settle down - if they're not too close and not too far away from their friends - they'll just stop
		private var settleDown:Boolean = false;
		
		private var boidColour:uint = 0xffffff;
		private var lineColour:uint = 0xffffff;
		private var bgColour:uint   = 0x000033;
		
		private var glow:GlowFilter = new GlowFilter();
		private var glowColour:uint = 0x99ffff;

		//But you should probably leave these as is - 
		private var boidArray:Array=[];
		private var menuHeight:Number = 85;
		private var doMidi:Boolean = false;
		private var BMD:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight-menuHeight, false, bgColour);
		private var BF:BlurFilter = new BlurFilter(5,5,1);
		private var Bit:Bitmap = new Bitmap(BMD);
		private var bitHolder:MovieClip = new MovieClip;
		private var ballHolder:MovieClip = new MovieClip;
		private var isMouseDown:Boolean = false;
		private var TB:TextField = new TextField();
		private var myCheckBox1:CheckBox;
		private var myCheckBox2:CheckBox;
		private var mySlider1:HSlider;
		private var mySlider2:HSlider;
		//Boid Flock Class
		public function BFCWonderfl():void{
			trace("Init!");
			addChild(bitHolder);
			bitHolder.addChild(Bit);
			addChild(ballHolder);
			
			glow.color = glowColour;
			glow.alpha = .5;
			glow.blurX = 5;
			glow.blurY = 5;
			
			ballHolder.filters = [glow];
			
			addChild(TB);
			TB.y = 0;
			TB.width = stage.stageWidth-10;
			TB.height = 75;
			TB.selectable = false;
			TB.text = "Constellation by Lawrie\nhttp://www.LawrieCape.co.uk\nSpace to add a boid at mouse - click to attract - any other key to reset.\n\nADD MINIMAL COMPS HERE - MIN MAX sliders and Friction Settle checkboxes";
			
			myCheckBox1 = new CheckBox(this,5,50,"Friction?",updateVals);
			myCheckBox1.selected = true;
			myCheckBox2 = new CheckBox(this,5,70,"Settle?",updateVals);
			var sLabel:Label  = new Label(this,75,45,"Min size");
			var sLabel2:Label = new Label(this,75,65,"Max size");
				
			mySlider1 = new HSlider(this,125,50,updateVals);
			mySlider2 = new HSlider(this,125,70,updateVals);
			
			mySlider1.setSliderParams(1,200,75);
			mySlider2.setSliderParams(1,200,100);
			
			addChild(myCheckBox1);
			addChild(myCheckBox2);
			
			addChild(mySlider1);
			addChild(mySlider2);	
			
			bitHolder.y = menuHeight;
			ballHolder.y = menuHeight;
			ballHolder.mouseEnabled  = false;
			ballHolder.mouseChildren = false;
			bitHolder.alpha=1;
			
			BMD.fillRect(BMD.rect, bgColour);

			bitHolder.addEventListener(MouseEvent.MOUSE_DOWN, mouseIsDown);
			bitHolder.addEventListener(MouseEvent.MOUSE_UP,   mouseIsNotDown);			
			stage.addEventListener(KeyboardEvent.KEY_UP, makeASingleBoid);

			addEventListener(Event.ENTER_FRAME, updateBoids);
			//makeBoids(numBoids);
		}
		
		private function makeASingleBoid(e:KeyboardEvent):void{
			if(e.keyCode==32){
				makeBoids(1,mouseX,mouseY);
			}
			else{
				reset();
			}
		}
		
		private function mouseIsDown(e:Event):void{
			isMouseDown = true;
		}
		private function mouseIsNotDown(e:Event):void{
			isMouseDown = false;
		}
		
		private function makeBoids(makeXBoids:int, bX:Number = 0, bY:Number = 0):void {
			for (var i:int=0; imaxDist) {
					B.speedX-=B.distToB2X/divideBy;
					B.speedY-=B.distToB2Y/divideBy;
				}
				//2) If I am too close to my neighbors, move away from them.
				else if (B.distToB2stage.stageWidth){
					B.x=stage.stageWidth-B.speedX;
					B.speedX*=-friction;
				}
				else if(B.x<0){
					B.x=-B.speedX;
					B.speedX*=-friction;
				}
				if (B.y>(stage.stageHeight-menuHeight)){
					B.y=(stage.stageHeight-menuHeight)-B.speedY;
					B.speedY*=-friction;
				}
				else if(B.y<0){
					B.y=-B.speedY;
					B.speedY*=-friction;
				}
				
				//Limit them to a top speed - 
				if(B.speedX>maxSpeed){
					B.speedX = maxSpeed;
				}
				else if(B.speedX< -maxSpeed){
					B.speedX=-maxSpeed;
				}
				if(B.speedY>maxSpeed){
					B.speedY = maxSpeed;
				}
				else if(B.speedY< -maxSpeed){
					B.speedY=-maxSpeed;
				}		
				
				//Add friction?
				if(enableFriction){
					B.speedX*=friction;
					B.speedY*=friction;		
				}
				
				//Move them 
				B.x+=B.speedX;
				B.y+=B.speedY;
			
			}
			//Draw into the BMD

			BMD.draw(ballHolder);
			//Apply a blur?
			BMD.applyFilter(BMD,BMD.rect,new Point(0,0),BF);
		}
		
		private function reset():void{
			removeEventListener(Event.ENTER_FRAME, updateBoids);
			for (var i:int=0; i

OpenCV thoughts and Flash BitmapData fun

Following on from my first post about my new generative audio project, I’ve been delving deeper into some of the libraries avaliable for Processing. One that sounded really interesting and powerful was OpenCV (Computer Vision). Peter Kirn over at Create Digtal Motion had this to say about it –

It’s a relatively easy thing for computers to “see” video, but “computer vision” goes a step further, applying a wide range of techniques by which computers can begin to understand and process the content of a video input. These techniques tend toward the primitive, but they can also produce aesthetically beautiful results. The best place to start with computer vision has long been the standard library, OpenCV. A free (as in beer and freedom) library developed by Intel and with ongoing use in a variety of applications, OpenCV is a terrific, C/C++-based tool not just for things like motion tracking, but video processing in general. OpenCV gets a lot of support in the C++-based OpenFrameWorks, but that doesn’t mean Java and Processing have to be left out of the fun.

With loads of ideas for how to implement this into my generative audio project floating around, I started following Andy Best’s great tutorial here.

I had a few issues setting up the library – so let me offer a word of warning – Make sure you download version 1.0 if you want to use OpenCV with Processing, and not the feautred download – which is a later build.

Among the fun things I got running, was this terrifying image difference threshold thing –

It reminded me of a great bit of Code Zevan posted over at ActionSnippet – AS3 Frame Differencing. Which then in turn reminded me of a couple of BitmapData experiments I never put up on here. So here they are!

I’ve wrapped them up into 1 block of code, as they are essentially very similar. The code will produce pictures like those below, by drawing sections of the webcam image into a Bitmap – either in random rectangles, or in sequential lines. These produce different, interesting effects.

//Boolean var to draw either random rectangles, or consecutive lines
var drawRandom:Boolean = false;
//Differing framerate for each type.
if (drawRandom) {
	stage.frameRate = 120;
} else {
	stage.frameRate = 50;
}
//Set up the Camera
var camera:Camera = Camera.getCamera();
camera.setMode(550,400,60);
var video = new Video(camera.width, camera.height);
video.attachCamera(camera);
addChild(video);
//Determine the maximum dimensions of the random rectangles
var drawWidth:int  = 25;
var drawHeight:int = 25;
//Boolean var for if app is currently drawing
var drawIt:Boolean = false;
//Counter to make lines sequential.
var lineCount:int = 0;

var BMD:BitmapData = new BitmapData(550,400);
var B:Bitmap = new Bitmap(BMD);
addChild(B);
B.x=550;
//Start and pause the drawing on any keypress
stage.addEventListener(KeyboardEvent.KEY_UP, toggleSnap);

function snap(e:Event):void {

	var r1:int;
	var r2:int;
	var r3:int;
	var r4:int;

	if (drawRandom) {

		//Start X and Y
		r1 = Math.round(Math.random()*(550-drawWidth));
		r2 = Math.round(Math.random()*(400-drawHeight));
		//Width and height of clip
		r3 = Math.round(Math.random()*drawWidth);
		r4 = Math.round(Math.random()*drawHeight);

	} else {
		lineCount+=1;
		if (lineCount==stage.stageHeight) {
			toggleSnap(null);
		}
		r1 = 0;
		r2 = lineCount;
		r3 = 550;
		r4 = 1;
	}
	BMD.draw(video, null, null, null, new Rectangle( r1, r2, r3, r4 ), true );
}

function toggleSnap(e:KeyboardEvent):void {
	if (drawIt) {
		drawIt = false;
		removeEventListener(Event.ENTER_FRAME, snap);
	} else {
		drawIt = true;
		addEventListener(Event.ENTER_FRAME, snap);
	}
}

Cheers.

Flash Midi Server 0.1 released + Sonar source code and audio air apps.

The title says it all really. I’ve updated the project page, but I’ll add the info here too incase you’re reading this through an RSS reader.

Flash Midi Server v0.1

Lawrie Cape 2010
Download from the Google Projects Page.

WHAT IS IT?

Flash Midi Server is method for sending MIDI data out of Flash. Using an Actionscript 3 class and a Processing application, you can create generative,

dynamic, fun audio tools in Flash.

WHY?

Mainly just for fun. Flash Midi Server (FMS) started as an experiment to test communication between Processing and Flash. From there it developed into a

class I played around with a lot – seeing what fun things I could use it for.

As FMS is built in Flash, it allows developers to rapidly prototype audio tools, experiment with new input methods and acess to a huge public code base to

build on top of. There’s a huge amount of technical skill and creativity in the Flash scene and hopefully some of it will be applied to creating innovative

new audio apps using FMS.

HOW DOES IT WORK –

FMS sends data from Flash to the FMS server – which then sends the data as a Midi signal.

Firstly run the FMS app in the “Server App” folder.
Then run one of the Flash or Air apps. Note – you cannot run .swf files as they do not have the security permissions to access the midi server, unless you

set the permissions here – http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html

You can set which Midi Channel the audio is played through via the drop down on the FMS app.
Windows XP has “Microsoft Midi Mapper” which plays the notes back over the soundcard. Mac OSX has a similar default Midi Playback setting.

To use FMS with other audio apps, you must install virtual midi softward. For example – LoopBe http://nerds.de/en/loopbe1.html
These channels will then show up in the FMS settings drop down.

HOW DO I USE THE CLASS MYSELF? –

Place the uk.co.lawriecape.midi folder structure in you classes folder.
You can then check out the .Fla sources in the “Example FLAs” folder.
A basic setup can be seen below –

In flash –

//Import the Flash Midi Server class.
import uk.co.lawriecape.midi.flashMidiServer;
//Create an instance of the class.
var MS: flashMidiServer = new flashMidiServer();
//Add event listeners for the various Server events - (optional)
	MS.addEventListener("FLASH_MIDI_SERVER_ESTABLISHED", connectionEstablishedHandler);
	MS.addEventListener("FLASH_MIDI_SERVER_LOST",        connectionLostHandler);
	MS.addEventListener("FLASH_MIDI_SERVER_NOT_FOUND",   connectionNotFoundHandler);

function connectionEstablishedHandler(e:Event):void{
	trace("Flash midi server connected.");
	trace("You can start sending data now!");
	MS.sendNote(50);
	//or
	//MS.sendCC(50);
}

function connectionLostHandler(e:Event):void{
	trace("Flash midi server disconnected.");
}


function connectionNotFoundHandler(e:Event):void{
	trace("Flash midi server not found, please check the program is running and try again.");
}

WHAT COMES NEXT? –

There are quite a few limitations to the current system, which I’ll be trying to address in future releases. These include –
The ability to send CC data on specified CC numbers.
The ability to have audio output on multiple midi channels at once – to controll multiple instruments from a single server instance.
The ability to send multiple notes at once – eg. Chords or simultaneous drum hits.

If you have any suggestions, or make anything using FMS, please get in touch with me.
Cheers.
Lawrie.

Lawrie at LawrieCape.co.uk

See also –

Flash Midi Server – Sonar reproduction. from Lawrie Cape on Vimeo.

Download the source code for Sonar from the Google Projects Page.

Flash Midi Server – Processing + Flash + Webcam Instrument from Lawrie Cape on Vimeo.

Flash Midi Server – Sonar reproduction.

Sonar from Renaud Hallée on Vimeo.

I just watched the spectacular “Sonar” by Renaud Hallée – A piece he describes as “Rhythmic cycle w/ abstract animation. Basic keyframe animation using flash, without scripting.” You can see it above. Awesome eh?

Seeing as I was working on my Flash based Midi Server, I thought I’d try and reproduce the basic elements of it using Actionscript.

This is my homage to Sonar – Basic scripting in Flash, using FlashMidiServer and FruityLoops for dynamic audio. I’ll post the SWF and source soon, when I upload the full Flash Midi Server package – Source, Java App, Demos, Air apps etc coming soon.

Flash Midi Server – Sonar reproduction. from Lawrie Cape on Vimeo.

AS3 Quick Tip – Remove a specific item from an array.

I’ve been working on a project today and needed a function to remove a specific item from an array. This is what I came up with, so I thought I’d share it here.

var myArrayOfLetters:Array = ["a","b","c","c","d","e","f","g","c"];
removeItemArray(myArrayOfLetters,"c");
//This will remove all instances of "c" from your array - so you will end up with
//a,b,d,e,f,g
 
function removeItemArray(thearray, theItem):void{
	trace("Remove "+theItem+" from "+thearray);
	for(var i:int=0; i

This will remove all instances of theItem from your array. If you know there will only be one instance of the item in the array, you can add "break;" to the conditional in the loop to save CPU.

var myArrayOfLetters:Array = ["a","b","c","d","e","f","g"];
removeItemArray(myArrayOfLetters,"c");
//This will remove the first instance of "c" from your array - so you will end up with
//a,b,d,e,f,g

function removeItemArray(thearray , theItem):void{
	trace("Remove "+theItem+" from "+thearray );
	for(var i:int=0; i

Hope you find it useful.
Lawrie.