3D Carousel AS3 Style && BOP Secrets Turns 10

Long long ago, I created a 3d circular menu thingie you can see here. It wasn’t much long after, that Lee Brimelow came up with his 3d carousel tutorial. Well, to be honest, I’ve never read Mr. Brimelow’s tutorial, but still I vowed then and there that I’d never make another one these things again – kinda like Bob Dylan vowing never to play “All Along the Watchtower” after hearing Hendrix’s version. Today, though, I’ve decided to renege on that vow. A freind over at ShavedPlatypus was asking how to make a carousel thing more similar to mine than Lee’s but in AS3, so I figured what the hell, why not update.

Below is an example of what I came up with:

Not many comments added, but the full script is below. In a nutshell, you just create a new instance of OBO_3DCarousel and pass it a few 3d properties (if you want). After that you add pictures to it using the addItem() method. Easy-peasy, man. Oh, and you can set the useBlur boolean property if you want a blur for more distant images.

The main class:

package com.onebyonedesign.td {
 
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.BlurFilter;
 
	/**
	* Creates a 3D Carousel when you add images (DisplayObjects) to an instance using the addItem() method.
	* @author Devon O.
	*/
 
	public class OBO_3DCarousel extends Sprite {
 
		private var _imageList:XMLList;
		private var _angleStep:Number;
		private var _fl:Number;
 
		private var _items:Array = [];
		private var _currentLoaded:int = 0;
		private var _blur:BlurFilter = new BlurFilter(0, 0, 2);
 
		private var _zRotation:Number;
		private var _targetRotation:Number;
		private var _numItems:int;
		private var _radius:Number;
		private var _zpos:Number;
 
		private var _useBlur:Boolean = false;
 
		public function OBO_3DCarousel(focalLength:int = 800, radius:int = 300, zpos:Number = 0):void {
			_fl = focalLength;
			_radius = radius;
			_zpos = zpos;
		}
 
		public function get zRotation():Number { return _zRotation; }
 
		public function set zRotation(value:Number):void {
			_zRotation = value;
		}
 
		public function get targetRotation():Number { return _targetRotation; }
 
		public function set targetRotation(value:Number):void {
			_targetRotation = value;
		}
 
		public function get zpos():Number { return _zpos; }
 
		public function set zpos(value:Number):void {
			var i:int = _items.length;
			while (i--) {
				_items[i].zpos = value;
				_items[i].updateDisplay();
			}
			_zpos = value;
		}
 
		public function get radius():Number { return _radius; }
 
		public function set radius(value:Number):void {
			var i:int = _items.length;
			while (i--) {
				_items[i].radius = value;
				_items[i].updateDisplay();
			}
			_radius = value;
		}
 
		public function get useBlur():Boolean { return _useBlur; }
 
		public function set useBlur(value:Boolean):void {
			_useBlur = value;
		}
 
		// READ-ONLY
		public function get numItems():int { return _numItems; }
 
		public function addItem(image:DisplayObject):void {
			_numItems = _items.length + 1;
			_targetRotation = -(90 - (360 / _numItems));
			_zRotation = _targetRotation;
			_angleStep = (2 * Math.PI) / _numItems;
			var item:TDCarouselItem = new TDCarouselItem(image);
			_items.push(item);
			var i:int = _items.length;
			while (i--) {
				var ci:TDCarouselItem = _items[i];
				ci.radius = _radius;
				ci.radians = _zRotation * Math.PI / 180;
				ci.angle = _angleStep * i;
				ci.focalLength = _fl;
				ci.zpos = _zpos;
				ci.ypos = y;
				ci.updateDisplay();
			}
			addChild(item);
 
			// if at least one item, go ahead and init the sucker
			if (_numItems == 1) initCarousel();
		}
 
		public function kill():void {
			removeEventListener(Event.ENTER_FRAME, frameHandler);
			var i:int = _items.length;
			while (i--) {
				var ci:TDCarouselItem = _items[i];
				ci.data.dispose();
				removeChild(ci);
				ci = null;
			}
		}
 
		private function initCarousel():void {
			addEventListener(Event.ENTER_FRAME, frameHandler);
		}
 
		private function frameHandler(event:Event):void {
			var rads:Number = _zRotation * Math.PI / 180;
			_items.sortOn("zpos", Array.NUMERIC);
			var i:int = _items.length;
			while (i--) {
				var item:TDCarouselItem = _items[i];
				item.radians = rads;
				if (_useBlur) {
					if (!isNaN(item.zpos)){
						// play with this blur amount - to taste
						_blur.blurX = _blur.blurY = int(((item.zpos - _zpos) + 200) / 40);
						item.filters = [_blur];
					}
				}
				item.updateDisplay();
				// need better z sorting
				addChild(item);
			}
		}
	}
}

The item class (instances of this class are the pictures in the carousel):

package com.onebyonedesign.td {
 
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
 
	/**
	* 3D items for OBO_3DCarousel class
	* @author Devon O.
	*/
	public class TDCarouselItem extends Sprite {
 
		private var _radius:Number;
		private var _radians:Number;
		private var _angle:Number;
		private var _focalLength:int;
		private var _orgZPos:Number;
		private var _orgYPos:Number;
		private var _data:BitmapData;
 
		private var _zpos:Number;
 
		public function TDCarouselItem(image:DisplayObject):void {
			_data = new BitmapData(image.width, image.height, true, 0x00FFFFFF);
			_data.draw(image);
			var bmp:Bitmap = new Bitmap(_data, "auto", true);
			bmp.x -= bmp.width * .5;
			bmp.y -= bmp.height * .5;
			updateDisplay();
			addChild(bmp);
		}
 
		internal function updateDisplay():void {
			var angle:Number = _angle + _radians;
			var xpos:Number = Math.cos(angle) * _radius;
			_zpos = _orgZPos + Math.sin(angle) * _radius;
			var scaleRatio:Number = _focalLength / (_focalLength + _zpos);
			x = xpos * scaleRatio;
			y = _orgYPos * scaleRatio;
			scaleX = scaleY = scaleRatio;
		}
 
		internal function get angle():Number { return _angle; }
 
		internal function set angle(value:Number):void {
			_angle = value;
		}
 
		internal function get radius():Number { return _radius; }
 
		internal function set radius(value:Number):void {
			_radius = value;
		}
 
		internal function get focalLength():int { return _focalLength; }
 
		internal function set focalLength(value:int):void {
			_focalLength = value;
		}
 
		internal function get radians():Number { return _radians; }
 
		internal function set radians(value:Number):void {
			_radians = value;
		}
 
		// must remain public for Array.sortOn() method in OBO_3DCarousel instance.
		public function get zpos():Number { return _zpos; }
 
		public function set zpos(value:Number):void {
			_orgZPos = value;
		}
 
		internal function set ypos(value:Number):void {
			_orgYPos = value;
		}
 
		internal function get data():BitmapData { return _data; }
	}
}

And a quick document class that created the .swf file above:

package  {
 
	import caurina.transitions.Tweener;
	import com.onebyonedesign.td.OBO_3DCarousel;
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.MouseEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.text.TextField;
 
	/**
	* Just a test of the OBO_3DCarousel class
	* @author Devon O.
	*/
	public class CarouselTest extends MovieClip {
 
		// on stage of .fla
		public var right_mc:MovieClip;
		public var left_mc:MovieClip;
		public var loading_txt:TextField;
 
		public static const XML_URL:String = "images.xml";
 
		private var _carousel:OBO_3DCarousel;
		private var _imageList:XMLList;
		private var _numImages:int;
		private var _currentImage:int = 0;
 
		public function CarouselTest():void {
			_carousel = new OBO_3DCarousel(500, 250, 220);
			_carousel.useBlur = true;
			_carousel.y = 90;
			_carousel.x = 250;
			addChild(_carousel);
 
			right_mc.addEventListener(MouseEvent.CLICK, rightClickHandler);
			left_mc.addEventListener(MouseEvent.CLICK, leftClickHandler);
 
			loading_txt.text = "loading xml";
			var uloader:URLLoader = new URLLoader();
			uloader.addEventListener(Event.COMPLETE, xmlHandler);
			uloader.addEventListener(IOErrorEvent.IO_ERROR, xmlHandler);
			uloader.load(new URLRequest(XML_URL));
		}
 
		private function xmlHandler(event:*):void {
			event.currentTarget.removeEventListener(Event.COMPLETE, xmlHandler);
			event.currentTarget.removeEventListener(IOErrorEvent.IO_ERROR, xmlHandler);
			if (event is IOErrorEvent) {
				loading_txt.text = "could not load xml file";
			} else {
				var xml:XML = new XML(event.currentTarget.data);
				_imageList = xml..image;
				_numImages = _imageList.length();
				loadImage();
			}
		}
 
		private function loadImage():void {
			loading_txt.text = "loading image " + (_currentImage + 1).toString() + " / " + _numImages.toString();
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageHandler);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, imageHandler);
			loader.load(new URLRequest(_imageList[_currentImage].toString()));
		}
 
		private function imageHandler(event:*):void {
			event.currentTarget.removeEventListener(Event.COMPLETE, imageHandler);
			event.currentTarget.removeEventListener(IOErrorEvent.IO_ERROR, imageHandler);
			if (event is IOErrorEvent) {
				loading_txt.text = "could not load image no " + _currentImage;
			} else {
				var image:Loader = event.currentTarget.loader;
				_carousel.addItem(image);
			}
 
			if (++_currentImage < _numImages){
				loadImage();
			} else {
				loading_txt.text = "complete";
			}
		}
 
		private function rightClickHandler(event:MouseEvent):void {
			_carousel.targetRotation += 360 / _carousel.numItems;
			Tweener.addTween(_carousel, { zRotation:_carousel.targetRotation, time:1, transition:"easeOutBack" } );
		}
 
		private function leftClickHandler(event:MouseEvent):void {
			_carousel.targetRotation -= 360 / _carousel.numItems;
			Tweener.addTween(_carousel, { zRotation:_carousel.targetRotation, time:1, transition:"easeOutBack" } );
		}
	}
}

Go nuts and let me know what troubles you run into. It wasn’t too extensively tested.
EDIT:
Download a sample .fla (including script, xml, some pictures and all that crap) of the above application here.


In other news, The Bureau of Public Secrets website (a site dedicated to Situationist and related thought ramblings) turned ten years old today. Ken Knabb, creator, translator, and, I’m sure, all around fun guy, shares his thoughts on the subject here.

42 Comments »

  1. Pradeek says:

    I made a 3D carousel in Flex 4 and Flash Player 10 , acouple of days ago. Here is the link:
    http://pradeekonflex.wordpress.com/2008/08/04/3d-carousel-in-flash-player-10/

  2. Shoom says:

    Devon… man, thank you. You needn’t…

  3. Devon O. says:

    looks good, Pradeek, but the z sorting is a bit off. I know it’s a pain in AS3 FP 9 or 10.. I’m still looking for a better method than I used here. Open to suggestions..

  4. Pradeek says:

    Thanks, I’m working on a more cleaner and easy to use method. I’ll let you know if it works.

  5. luciano says:

    Yes, this is just a newbie stupid question…
    …but I’m an AS3 newbie, and was 37 yo… so I don’t will be ashamed to question….PLEASEEE… write two lines to make the example running with flash…

    ((After a few years sellin’n riding bycicles (and a couple of IronMan(s) too), I’m back in the arena. I spent my summer holidays trying to understand AS3 and I’m only a few ephiphany from “the programmer’s dawn”, as defined by my programming teacher @ school 20 years ago (remember Peek 33,33?)

  6. Devon O. says:

    Hey Luciano, I’d be happy to help if I can, but can you describe what you’d like to see it do. Not sure what you mean by “running with flash”. And I haven’t heard “peek” in years.. There used to be a whole lot of peeking and poking going on 20 years ago..

  7. Luciano says:

    Hi Devon,
    your gallery is fast and clean, I’d like to use it for my site building. With click-on-image feature to show before-after slider effects on photos. But I did not installed FLEX yet, and having some trouble with class assignment in FLASH and stage composing. I’ll appreciate very much a simple .fla AS3 script that refers to Class OBO_3DCarousel. Not much explanation…. just to let me understand…. thanx a lot!
    Luciano

    ps Just for fun a little story, referring to your “coffee for coder”…In Naples, Italy, my city, there’s the habit for those don’t have money, to go to the famous “Caffè Gambrinus” and have an espresso coffee for free, that someone unknown payed for him just telling the barman: “someone payed coffee for me??” ;-)

  8. Devon O. says:

    Hey Luciano,
    I just edited my post and included a download of the .fla and all the trimmings. I hope that might help you out.
    That free Italian coffee sounds great. I lived in Sicily for a couple years and miss the cappuccino the most. You wouldn’t happen to be related to “Lucky” would you? (Just kidding.. :) )

  9. luciano says:

    Ciao Devon!
    great job! now I’m trying to add some click-on-image feature… a long night awaits me (probably more than one night!)
    Grazie!
    LL

  10. Devon O. says:

    Prego! Good luck with the image interaction. Not sure how I would do that myself.

  11. Skye says:

    Hi Devon, nice work on the site. I noticed that if I click a “subject” in the right column of this blog (Actionscript, Flash, AIR, etc) I get the category results “one by one”. That is, one page at a time. Is that by design? I was hoping I might click a category and browse all your posts on a subject.

    Cheers,

    Skye

  12. Devon O. says:

    Interesting.. I’ve never actually clicked on one before.. :) It may because I have it set up to only display one blog post per page and that gets carried over to subject browsing as well. I’ll play around and see if I can change that.

  13. Pradeek says:

    Made the carousel as a gumbo skin. Not the best of ways, but… pl. check it out here

    http://pradeekonflex.wordpress.com/2008/08/29/3d_carousel_as_flex_skin/

  14. Devon O. says:

    Cool, Pradeek.. I’ve downloaded the SDK, but haven’t began playing with Gumbo yet.. Might have to play around this weekend.

  15. luciano says:

    Ciao Devon!
    I worked hard on my project with your 3D Gallery (www.digitalmakeup.it), a sort of training-on-job (addicted to script!)… but now there’s a problem: I can’t really understand how the carousel is building. I placed a new tag in the XML to recover (using an XMLLIST class) an alternative address and open High res images on click. Tracking each left or right click I got an index to read XML, but the carousel’s items was not placed with the same XML’s order and wrong image is opening.
    I know that one simple way is changing order of the XML’s tag of the High res images, but I’m still trying to understand HOW the _carousel build itself by add(ing)Items.There’s something in the way it builds that I don’t understand…. please can you explain in “blocks” how it works? I missed the “kill” function!
    thanks devon!
    luciano

  16. Deirdre says:

    I use a custom query string to display categories, archives etc in a complete list .. overriding front page settings.

    http://moshublog.com/2007/10/30/custom-query-string-reloaded-for-wordpress-23-with-tag-support/

  17. Devon O. says:

    Luciano, it looks good so far. I’ll try to put together a more commented version when I get some time. I’m not altogether sure how I’d go about doing what you want though. Maybe finding the angle increment to present a new picture and keeping track of what’s up front that way.. Or maybe just starting from scratch and creating a new one with that purpose in mind.

    DEIRDRE! I can’t download that thing. Don’t know if that’s site or my browser.. If I use it will mess up previous posts?

  18. Thanks for sharing this – I am trying to use it.

    I downloaded the zip and compiled it to baseline that I had everything in place.

    I get

    caurina\transitions\Tweener.as:1054:

    1046: Type was not found or was not a compile-time constant: TweenListObj.

    line 1054 is handleError function of Tweener, so might be a side effect?

  19. Never mind – I put tweener in my com folder

    doh!

    Hopefully a better comment/question: how can I change the orientation of this carousel to make it into an upright wheel?

  20. Answer: Switch x and y values in the CarouselItem class

  21. Devon O. says:

    Glad you got that sorted, David.. Hope it helps you out..

  22. Chris says:

    Hi I am playing with this class and making buttons to load a specific item in the carousel and it works good, the only problem I have is that the order of images in the carousel does not correspond with the ones in the xml file.. after like 4 items it gets a different order.

    Is there a way to keep the same order of files from the xml in the carousel ?

  23. fred says:

    how do we send the carousel to lowest level layer so that other movie clips are on top of it?

  24. Devon O. says:

    Hey Chris, I would simply watch the order in which the images appear and plan accordingly. The images are loaded in order but then positioned according to the logic in the addItem() method.

    Fred, the carousel inherits from the Sprite class and can be handled like any other Sprite. Using addItemAt(0, myCarousel) will always push it below anything else already on the Display List.

  25. wobi says:

    Hello Devon, I was wondering how can i add the reflection for the items… I tried different ways but couldn’t get it right. can you help me out ?

  26. knottyDJ says:

    Tite! thanks for sharing.

    trying to add button functionality to the images so I could click on them and bring them forward or run another function or …..

    wondering if you have any suggestions for turning the images into clickable items?

  27. Nick says:

    Wow… WOW… OMG WOW!

    You have NO idea how long I have been looking for someone that coded this in AS3, CORRECTLY, WITH all the appropriate handlers and linked it to an xml list of images. I don’t know how many resources exactly, but in the past 48hrs, this is the FIRST that has what I was looking for!

    THANK YOU!

    Nick

  28. Nick says:

    Devon,

    Not sure how often you check this blog anymore, but if you could let me know if you could answer a few questions about the code, it’d be appreciated. Just trying to add some nifty things to it :)

    Nick

  29. Devon O. says:

    Hey, Nick. Been crazily busy of late, having just changed jobs and countries, but I still read comments. What kind of questions you got? And thank you for the kind words..

  30. Nick says:

    Hey man,

    Thank you for taking the time out of your schedule first off. Secondly, I’m having issues (though I’m close to the solution) importing the swf of the carousel into a movie clip. The issue is that even though the movie clip is the same size as the the carousel was in it’s file, it’s being displayed at like 3-4 times the size, and there doesn’t seem to be a way to resize it.

    The code I have thus far for the movie clip looks like this atm:

    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.events.*;
    import flash.net.URLRequest;

    var movieLoader:Loader = new Loader();
    var movieURL:URLRequest = new URLRequest(“carousel.swf”);
    movieLoader.load(movieURL);
    carousel_mc.addChild(movieLoader);
    trace(carousel_mc.height, carousel_mc.width);
    var a:Number = carousel_mc.height;
    var b:Number = carousel_mc.width;

    movieLoader.contentLoaderInfo.addEventListener(Event.INIT, initHandler);

    function initHandler(event:Event):void {
    var movieLoader:Loader = Loader(event.target.loader);
    var info:LoaderInfo = LoaderInfo(movieLoader.contentLoaderInfo);
    movieLoader.height = a;
    movieLoader.width = b;
    }

    Any hints you could throw my way? I’m not new to actionscript, but I am definitely new to doing something so complicated.

  31. Floyd says:

    Thanks devon.
    I’ve tried to modify this source to make look smaller and to fit on my purpose onto revising my company’s website.
    The image modification was nothing, but it is very hard to find the place of initial location of the images and hence, hard to find to contracting the images the main file is displaying.
    Anyway, it’s nice to see the codes insides of folders which were developed by MIT guys. It’s very very hard to understand and I actually dropped it off :)

    Well, thanks for your devotion.

  32. Nick says:

    Devon,
    Thanks a lot for a great carousel. As other people have commented it is easy to use and seems to be built well.

    I have been working with it and had a quick question.. Is there a way to add more info to each of the carousel items? ie: add text about the items that would also come from the xml file (think file card)

    Ive been playing around with it and so far havent had any luck. Im assuming i would create the text fields in the code area where the _data bitmap is created?

    Thanks again and I appreciate any additional insight!

    NIck

  33. Wonderful Job Devon! I like your style of coding and got a chuckle about the side story on Lee’s carousel. :)

    I’ve played with Lee’s in Flex but gave yours a try with a platform called Koolmoves and added a few bits just to test the KM compiler (it just recently added AS3 support) which is running here:

    http://krazyaboutpizza.co.uk/?p=90

    We’re ramping up to evangelize for KM’s new version so the domain will change to KM-CODEX.com in the next few days and I’ll be sure to send KM users your way to learn from your expertise. Thanks for being so generous and I look forward to your future offerings!

    Chris

  34. Tom Nguyen says:

    first off, great carousel. I’m actually trying to figure out how to tilt the angle of the carousel slightly, as though you can see the carousel more at a top view looking down. Anyway you could help me with it? I’m not a coder as you can tell, but any help would be appreciated. Thanks in advance.

    Tom

  35. Christian Basler says:

    hi devon,
    i have no idea how to sort the images correctly. i have the same problem chris had bevor, but cant finid any solution. maybe you can give me one more hint how to manage this problem.

    thank you
    christian

  36. Boris says:

    Hi Devon,
    really cool one – but how can i change the cirlce into an elliptical movement

  37. peter says:

    what are the settings so that the main item is not scalled?

  38. Brandon says:

    Hello I’m knew to this whole thing and I’m trying to get this carousel to work without using xml and loading the movie clips from the library as carousel items. Any suggestions on how to do this. I’ve tried scaling back the code to make it work this way but I haven’t been successful.

  39. Jake says:

    Is there anyway to make the far back two blurred images be on the corresponding sides of the first two images? [][] [] [][]? Almost like a card stack?

    Loving this!

  40. san says:

    this is the most amazing carousel component i’ve seen done in flash/flex.. very well done! thank you :)

  41. Robert says:

    Hello Devon, nice work! Have you the solution for the problem with the sort the images in correctly order?

    Thanks in advance!

RSS feed for comments on this post. / TrackBack URI

Leave a Reply

Devon O. Wolfgang

Technical Reviewer of “The Essential Guide to Flash CS4 AIR Development”

Contributing Author of “Flash AS3 for Interactive Agencies”

Senior Software Developer in Dublin, Ireland

Portfolio

Bayer Pixel Bender Filter

Bayer Mosaic Filter in Pixel Bender


Now, seeing as how I’ve been trying to learn some Pixel Bender coding lately[...]

Liquitext

Liquid Text Effect


Haven’t been too active around here lately due to a major on going project at work lately as well as the fact that my wife and I are in the slow process of moving homes. Really, the only free time it seems I have these days is during the lunch hour. So, over the past two days, I came up with this fun little toy during lunches[...]

Google’s Text To Speech Engine in Flash

I’m not sure how I managed to miss this, but I just happened to run across a ‘new’ (well, newish), albeit still unofficial, offering of Google today: text-to-speech. You can see what few details there are on this Techcrunch post. Basically, it just boils down to this though – you send your phrase to be [...]

Quick Sound Effects Generator


Need some beeps, boops, or bops, to go with your UI or games [...]

Quick QuickBox2D Tip II – Collision Detection

Custom collision detection/handling in QuickBox2D [...]

None of This Runs Eternal


No Flash/Actionscript stuff here. Just me rambling about the upcoming Current 93 concert [...]

Playing Around with the New UndoManager

Included in the Flex 4.0 SDK and the, just released, Flash Professional CS5 lies a new hidden little gem of a class: flashx.undo.UndoManager (although the Flex 4.0 SDK’s been out for awhile, I have to admit I didn’t even notice this until I installed Flash CS5 and started poking around the documentation looking for new [...]

Making Waves

In a previous post, “Digging into the Microphone in Flash Player 10.1″, reader David Law asked in the comments how it would be possible to save .wav files to the server. I wasn’t sure right offhand, but thought I’d spend my lunch hour yesterday looking into it. Well, after reading this quick tutorial on Adobe [...]

Some Drawing Fun and a Bad Movie You’ll Never See

Earlier today, Dave Gillem posted a link on Facebook to an incredible Processing based drawing application. Thought I’d have a go at reproducing something similar in Flash. Well, I failed miserably, but the results were still interesting enough to check out. You can play around with it below. Just mouse down to draw in the [...]

Animating Bezier Curves


The other day I got the notion in my head that I wanted to draw some bezier curves in an animated fashion. I’m sure this has been done a million times before, but sometimes reinventing the wheel can be a good learning experience [...]

My God, It’s Full of Stars…


Just a quick little thing I got an idea for (i.e. pretty much ripped off) while browsing Processing examples.

Another Year, Another Look

As a few folks may have noticed, the blog is looking a little bit different as of today [...]

The Webcam Warholizer


Just a little bit of quick Friday fun with webcam and bitmapata…

More With the JiglibFlash Terrain

Playing around a bit more with the animated JiglibFlash terrain idea from my last post, I wanted to see how it would work in conjunction with a webcam. So, needless to say, you’ll need a webcam to check out the results below.

Rockin and Rollin with the JiglibFlash Terrain


Finally got the chance to play around with the new JiglibFlash height map terrain, today, and have to say I am very impressed [...]