Download Comb Over Charlie Trial Now : On the Android Market

DOWNLOAD Comb Over Charlie Trial Now

AIR 2.6 Comb Over Charlie Android App

DOWNLOAD Comb Over Charlie Trial Now

Full story at Papervision2.com

Posted in AIR 2.6, Comb Over Charlie, Game Development | Tagged , , , | Leave a comment

AIR 2.6 Game Development : iOS included

Follow me on twitter @wovencharlie to be notified when Comb Over Charlie is available for download.

Coming soon to an iPad, iPhone, Android Tablet, Android Phone, Blackberry Playbook, and Google Chrome Store near you.

AIR 2.6 Game Development

Over the past few weeks I’ve had the privilege to work with the AIR 2.6 pre-release; I have to say I was completely shocked. The first time I used the AIR to iOS compiler that shipped with CS5, the frame-rates were poor enough that I disregarded it and never planned on using it again. About two months ago I decided to give it another go. I was shocked to say the least.

My application went from about 10 to 15 fps to a solid 40 fps. While I started off with the goal to create something with AIR for the sake of calling it an AIR app, I was able to forget about the technology and just focus on the game. Now, I spend more time creating new characters, backgrounds, and other game features instead of working around limitations.

The result is a smooth 40 fps game “Comb Over Charlie”:

AIR 2.6 Game Development

Here are a few things I learned while creating Comb Over Charlie:

  • Object Pool – Object Pool – Object Pool!
  • Use JPGs where you can instead of PNGs
  • Use CacheAsBitmap wherever possible
  • At least for iOS – set stage.stageQuality to StageQuality.LOW during heavy animations
  • With games similar these, make sure you enable GPU mode for iOS
  • Limit the number of cacheAsBitmapMatrix objects
  • Object Pool some more
  • Create images as small as possible and scale them up x 2. So instead of a 1200 x 600 image have use 600 x 300 image
  • Don’t have too many very large transparent layers overlapping
  • If you have vectors and can convert them to bitmaps, do it!
  • Profile your app to to catch memory leaks early
  • Did I mention Object Pooling?

There are a few reasons why object pooling is so important:

1) Object pooling allows you to keep the amount of objects created to a minimum.
2) When objects are created and destroyed this tends to cause bumps or hiccups in the visuals (very bad for a smooth side scrolling game) – with object pooling you’re not creating something new on the fly, you’re only re-using what you’ve already created.
3) The less objects you have, the less memory you use. Re-use of objects contributes to less memory consumed, better battery life, and better performance.

Whenever I run into performance issues, it’s usually because I am forgetting to destroy something properly. So, consistently profile your application to spot memory leaks as early as possible.

Check back in the coming weeks to see more in depth tutorials on how Comb Over Charlie was made.

For now check out these great sites for more info and resources:

Elad Elrom’s optimization classes – great BitmapCaching class!:
https://github.com/EladElrom/Flash-Optimizing-Tools

Awesome site with object pooling tutorials and classes:
http://lab.polygonal.de/2008/06/18/using-object-pools/

FriendsOfEd Flash Games : Great game book with loads of techniques / code:
http://friendsofed.com/book.html?isbn=1430226145

Jesse Freeman on Advanced Blitting:
http://www.developria.com/2010/08/advanced-blitting-bitmap-scrol.html

Come and learn more about AIR 2.6 iOS development at FATC June 9 – 12th – Flash And The City

Special thanks to Christian Croft for helping code the Score / Leader / Achievements board. – http://www.ecosquid.com

Posted in AIR 2.6, Game Development, Video | Tagged , , , , , , | 28 Comments

Reposition and Arrange Objects in 3D Space with Away3D

Away3D Tutorials

Download Away3D Tutorial Source

This tutorial is part of what I had the opportunity to present at RIA Unleashed in Boston just a few weeks ago. The basic premise of this tutorial is to arrange objects into different patterns as the whole group animates.

After the initial setup of our View3D we create a container to hold all of our card items. This container will allow us to animate the entire group as we animate it’s contents in a different way.

private function createContainer():void 
{
	cardContainer = new ObjectContainer3D();
	view.scene.addChild(cardContainer);
}

Next we can create our cards (Plane objects), add them to our container object, apply a material, and store a reference to the card in an array so we can access it easily later.

private function createCards():void 
{
	var len:int = 6;
 
	for(var i:int = 0;i<len;i++)
	{
		var bitmapMaterial:BitmapFileMaterial = new BitmapFileMaterial("images/drawing.jpg");
		bitmapMaterial.smooth = true;
 
		var plane:Plane = new Plane( { material:bitmapMaterial, width:200, height:200 } );
		plane.bothsides = true;
		plane.yUp = false;
 
		cards.push(plane);
		cardContainer.addChild(plane);
	}
}

The next thing we do is create a few different arrangements for our items. I’ve created 3 here; random, carousel, and flat. You can really create as many as you like. Let’s review just the random arrangement.

public function setInRandom():void 
{
	cardPositions = [];
 
	var len:int = cards.length;
 
	for(var i:int = 0;i<len;i++)
	{
		var positionVO:PositionVO = new PositionVO();
 
		positionVO.x = Math.random() * 2000 - 1000;
		positionVO.y = Math.random() * 1000 - 500;
		positionVO.z = Math.random() * 200 - 200;
		positionVO.rotationY = Math.random() * 360 - 360;
		positionVO.rotationX = Math.random() * 360 - 360;
		cardPositions.push(positionVO);
	}
 
	arrageCards();
}

We start off by clearing our cardPositions array. We will use this array to store some value objects, a value object is nothing more than a class to store some properties like x, y, z, rotationX but if you’re using Flex or FlashDevelop you’ll get code hinting whenever you use it.

Next we loop through our total number of items we have on the stage and apply random numbers to all of our positionVO’s properties, and then push each of those items to our cardPositions array.

Finally we call arrangeCards()

private function arrageCards():void 
{
	TweenMax.killAll(false);
 
	var len:int = cards.length;
 
	for(var i:int = 0;i<len;i++)
	{
		var positionVO:PositionVO = cardPositions[i];
		var plane:Plane = cards[i];
 
		TweenMax.to(plane, 1,{
						x:positionVO.x,
						y:positionVO.y,
						z:positionVO.z,
						rotationY:positionVO.rotationY,
						ease:Quint.easeInOut
						});
	}
}

Inside of the arrangeCards method we loop through our total number of items again this time passing along the card we want to animate, along with the properties from the positionVO to TweenMax. For one glorious second these will animate to their next position.

Here is the full code:

PositionVO.as

package
{
	public class PositionVO
	{
		public var rotationX:Number = 0;
		public var rotationY:Number = 0;
		public var z:Number = 0;
		public var x:Number = 0;
		public var y:Number = 0;
	}
}

Main.as

package
{
	import away3d.containers.ObjectContainer3D;
	import away3d.containers.View3D;
	import away3d.materials.BitmapFileMaterial;
	import away3d.primitives.Plane;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
 
	import flash.events.Event;
 
	import gs.TweenMax;
	import gs.easing.Quint;
 
	public class Main extends Sprite
	{
		private var cards:Array = [];
		private var cardContainer:ObjectContainer3D
		private var cardPositions:Array;
		private var view:View3D;
 
		private var toRandomButton:Sprite;
		private var toFlatButton:Sprite;
		private var toCarouselButton:Sprite;
 
		public static const CARD_SPACING:int = 210;
 
		public function Main()
		{
			super();
			addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
		}
 
		protected function onAddedToStage(event:Event):void 
		{
			createView();
			createContainer();
			createCards();
			createNavButtons();
			setInRandom();
			startRendering();
			view.camera.focus = 40;
		}
 
		private function createView():void 
		{
			view = new View3D( { x:stage.stageWidth / 2, y:stage.stageHeight / 2 } );
			addChild(view);
		}
 
		private function createContainer():void 
		{
			cardContainer = new ObjectContainer3D();
			view.scene.addChild(cardContainer);
		}
 
		private function createCards():void 
		{
			var len:int = 6;
 
			for(var i:int = 0;i<len;i++)
			{
				var bitmapMaterial:BitmapFileMaterial = new BitmapFileMaterial("images/drawing.jpg");
				bitmapMaterial.smooth = true;
 
				var plane:Plane = new Plane( { material:bitmapMaterial, width:200, height:200 } );
				plane.bothsides = true;
				plane.yUp = false;
 
				cards.push(plane);
				cardContainer.addChild(plane);
			}
		}
 
		public function setFlat():void 
		{
			cardPositions = [];
 
			var len:int = cards.length;
 
			//We use this offset to center the items in the scene
			var totalWidth:Number = len * CARD_SPACING;
			var offset:Number = totalWidth * .5 - CARD_SPACING *.5;
 
			for(var i:int = 0;i<len;i++)
			{
				var positionVO:PositionVO = new PositionVO();
				positionVO.x = CARD_SPACING * i - offset;
				cardPositions.push(positionVO);
			}
 
			arrageCards();
		}
 
		public function setInCarousel():void 
		{
			cardPositions = [];
 
			var len:int = cards.length;
			var radius:int = 400;
 
			for(var i:int = 0;i<len;i++)
			{
				var positionVO:PositionVO = new PositionVO();
				var angle:Number = Math.PI * 2 / len * i;
				positionVO.x = Math.cos(angle) * radius;
				positionVO.z = Math.sin(angle) * radius;
				positionVO.rotationY = -360 / len * i - 90;
				cardPositions.push(positionVO);
			}
 
			arrageCards();
		}
 
		public function setInRandom():void 
		{
			cardPositions = [];
 
			var len:int = cards.length;
 
			for(var i:int = 0;i<len;i++)
			{
				var positionVO:PositionVO = new PositionVO();
 
				positionVO.x = Math.random() * 2000 - 1000;
				positionVO.y = Math.random() * 1000 - 500;
				positionVO.z = Math.random() * 200 - 200;
				positionVO.rotationY = Math.random() * 360 - 360;
				positionVO.rotationX = Math.random() * 360 - 360;
				cardPositions.push(positionVO);
			}
 
			arrageCards();
		}
 
		private function createNavButtons():void 
		{
			toRandomButton = createButton();
			toCarouselButton = createButton();
			toFlatButton = createButton();
 
			toRandomButton.x = 20;
			toCarouselButton.x = 140;
			toFlatButton.x = 260
 
			toRandomButton.y = 20;
			toCarouselButton.y = 20;
			toFlatButton.y = 20
 
			toFlatButton.addEventListener(MouseEvent.CLICK, toFlatClick);
			toRandomButton.addEventListener(MouseEvent.CLICK, toRandomClick);
			toCarouselButton.addEventListener(MouseEvent.CLICK, toCarouselClick);
		}
 
		private function arrageCards():void 
		{
			TweenMax.killAll(false);
 
			var len:int = cards.length;
 
			for(var i:int = 0;i<len;i++)
			{
				var positionVO:PositionVO = cardPositions[i];
				var plane:Plane = cards[i];
 
				TweenMax.to(plane, 1,{
										x:positionVO.x,
										y:positionVO.y,
										z:positionVO.z,
										rotationY:positionVO.rotationY,
										ease:Quint.easeInOut
									});
			}
		}
 
		private function createButton():Sprite
		{
			var button:Sprite = new Sprite();
			button.graphics.beginFill(0x36414B);
			button.graphics.drawRect(0, 0, 100, 10);
			button.graphics.endFill();
			addChild(button);
			return button;
		}
 
		//Mouse Event handlers 
		private function toFlatClick(event:MouseEvent):void 
		{
			setFlat();
		}
 
		private function toRandomClick(event:MouseEvent):void 
		{
			setInRandom();
		}
 
		private function toCarouselClick(event:MouseEvent):void 
		{
			setInCarousel();
		}
 
		//Add an enterFrame for rendering the engine
		private function startRendering():void 
		{
			addEventListener(Event.ENTER_FRAME, onRenderTick);
		}
 
		protected function onRenderTick(event:Event=null):void
		{
			view.render();
			cardContainer.yaw(2);
		}
	}
}

Download Away3D Tutorial Source

Posted in Away3D, Away3D Carousel, Away3D Tutorials | Tagged , , | 7 Comments

Loading Complex Models with Away3D

Away3D Loading Complex Models

Download Away3D Tutorial Source

When working with Away3D you’ll eventually need to load a complex model. In my experience, the issues with loading and rendering models has been with the model itself. You’ll want to work closely with a 3D modeling expert in the creation of the models you’ll be using with Away3D.

Hopefully you are one of the few blessed enough to have an resource available to modify and create Away3D ready models for you. If not, just know you’re not alone.

Those issues aside, the code for loading a 3D model into Away3D is fairly easy. It is almost as simple as loading a plane, cube, or cone.

This is just one way to work with models and Away3D. You can also embed the models into your files, I’ll reserve that for another tutorial.

1) Load your model

var loader3D:Loader3D = Collada.load("daeModel/cow.dae");
loader3D.addEventListener(Loader3DEvent.LOAD_SUCCESS, onModelLoadSuccess);

Papervision to Away3D Tip:
You’ll notice here that we are using a Loader3D. If you’re coming from Papervision this was done slightly different. With Papervision you could pass the reference to the model path in the constructor of the Colloda object. example: cow = new Collada("daeModel/cow.dae",materialList);.

2) Handle the load success

protected function onModelLoadSuccess(event:Loader3DEvent):void 
{
	cow = event.loader.handle as ObjectContainer3D;
	view.scene.addChild(cow);
}

Now that we have successfully loaded our model we need to get it from our Loader3D and add it to the scene. We do this by using event.loader.handle and casting the object returned as an ObjectContainer3D.

From the docs, here is what handle is doing:
Once the file has been loaded and is ready to view, the handle returns the parsed 3d object file

Here is the full code for your review:

package  
{
	import away3d.containers.ObjectContainer3D;
	import away3d.containers.View3D;
	import away3d.events.Loader3DEvent;
	import away3d.loaders.Collada;
	import away3d.loaders.Loader3D;
	import flash.display.Sprite;
	import flash.events.Event;
 
	public class Main extends Sprite 
	{
		protected var cow:ObjectContainer3D;
		protected var view:View3D;
 
		public function Main() 
		{
			super();
			this.addEventListener(Event.ADDED_TO_STAGE,onAddedToStage);	
		}
 
		protected function onAddedToStage(event:Event):void 
		{
			createChildren();
			loadModel();
			startRendering();
		}
 
		protected function createChildren():void 
		{
			view = new View3D({x:stage.stageWidth/2, y:stage.stageHeight/2});
			addChild(view);
		}
 
		protected function loadModel():void 
		{
			var loader3D:Loader3D = Collada.load("daeModel/cow.dae");
			loader3D.addEventListener(Loader3DEvent.LOAD_SUCCESS, onModelLoadSuccess);
		}
 
		protected function onModelLoadSuccess(event:Loader3DEvent):void 
		{
			cow = event.loader.handle as ObjectContainer3D;
			cow.scale(100);
			cow.moveDown(1);
			view.scene.addChild(cow);
		}
 
		protected function startRendering():void 
		{
			addEventListener(Event.ENTER_FRAME, onRenderTick);
		}
 
		protected function onRenderTick(event:Event = null):void 
		{
			//Render View
			view.render();
 
			//If our cow is ready - spin
			if (cow)
			{
				cow.yaw(2);
			}	
		}
	}
}

Download Away3D Tutorial Source

Posted in Away3D, Away3D Loading Complex Models | Tagged , , , , , | 3 Comments

A Simple Away3D Carousel

Away3D Carousel

Download Away3D Tutorial Source

Continuing the series of converting Papervision tutorials to Away3D tutorials I’m moving to the 3D Carousel. As with the original Papervision tutorial the heart of this carousel is a simple “for” loop / math which places the items in a circle in 3D space as follows

for (var i:int = 0; i < planes.length; i++) 
{
	var angle:Number = Math.PI * 2 / numItems * i;
	var plane:Plane = planes[i];
	plane.yUp = false;
	plane.bothsides = true;
	plane.x = Math.cos(angle) * radius;
	plane.z = Math.sin(angle) * radius;
	plane.rotationY = -360 / numItems * i - 90;
}

If you had created the original Papervision version you’ll notice two differences with this code as it’s converted to work with Away3D.

1) We need to set plane.yUp to false. Otherwise the plane would be laying flat.
2) We also are setting plane.bothsides to true so that the material will be painted on both sides of the plane

Papervision to Away3D TIP:
In papervision the material is what we would set to doublesided (material.doubleSided = true). In Away3D we use the object itself, in this example the Plane (plane.bothsides = true)

Then to rotate our carousel we apply some similar math

var rotateTo:Number = (-360 / numItems) * currentItem + 90;
TweenLite.to(planesHolder, 1, { rotationY:rotateTo, ease:Quint.easeInOut } );

This code allows us to increment currentItem and rotate our carousel.

Let’s now take a look at the full source code:

package 
{
	import away3d.containers.ObjectContainer3D;
	import away3d.containers.View3D;
	import away3d.materials.BitmapFileMaterial;
	import away3d.primitives.Plane;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import gs.easing.Quint;
	import gs.TweenLite;
 
	/**
	 * ...
	 * @author Charlie Schulze, charlie[at]woveninteractive[dot]com
	 */
 
	public class Main extends Sprite 
	{
		protected var planes:Array = [];
		protected var numItems:Number = 14;
		protected var radius:Number = 500;
		protected var currentItem:Number = 0;
 
		protected var bitmapMaterial:BitmapFileMaterial;
		protected var planesHolder:ObjectContainer3D;
		protected var rightBtn:Sprite;
		protected var leftBtn:Sprite;
		protected var view:View3D;
 
		public function Main():void 
		{
			super();
			this.addEventListener(Event.ADDED_TO_STAGE,onAddedToStage);	
		}
 
		protected function onAddedToStage(event:Event):void 
		{
			createChildren();
			createButtons();
			arrangePlanes();
			adjustCamera();
			startRendering();
		}
		protected function createChildren():void 
		{
			//Create your View3D
			view = new View3D({x:stage.stageWidth/2, y:stage.stageHeight/2});
			addChild(view);
 
			planesHolder = new ObjectContainer3D();
 
			//Create Material
			bitmapMaterial = new BitmapFileMaterial("images/drawing.png");
			bitmapMaterial.smooth = true;
 
			for (var i:int = 0; i < numItems; i++) 
			{
				var plane:Plane = new Plane({material:bitmapMaterial, width:150, height:234});
				planes.push(plane);
 
				//Add plane to the scene
				planesHolder.addChild(plane);
			}
 
			view.scene.addChild(planesHolder);
		}
 
		protected function arrangePlanes():void 
		{ 
			//Set properties of our planes
			for (var i:int = 0; i < planes.length; i++) 
			{
				var angle:Number = Math.PI * 2 / numItems * i;
				var plane:Plane = planes[i];
				plane.yUp = false;
				plane.bothsides = true;
				plane.x = Math.cos(angle) * radius;
				plane.z = Math.sin(angle) * radius;
				plane.rotationY = -360 / numItems * i - 90;
			}
 
			//Rotate once
			rotate();
		}
 
		protected function adjustCamera():void 
		{
			//Adjust camera
			view.camera.zoom = 10;
			view.camera.focus = 40;
			view.camera.y = 50;
		}
 
		//Rotates the carousel
		protected function rotate():void 
		{
			var rotateTo:Number = (-360 / numItems) * currentItem + 90;
			TweenLite.to(planesHolder, 1, { rotationY:rotateTo, ease:Quint.easeInOut } );
		}
 
		protected function startRendering():void 
		{
			addEventListener(Event.ENTER_FRAME, onRenderTick);
		}
 
		protected function onRenderTick(event:Event):void 
		{
			view.render();
		}
 
		/*
		 * Everything below this point is just for creating the buttons and
		 * setting button events for controlling the carousel. 
		 */
 
		protected function createButtons():void 
		{
			//Create Buttons
			rightBtn = createButton();
			leftBtn = createButton();
 
			addChild(leftBtn);
			addChild(rightBtn);
 
			//Add button listeners
			rightBtn.buttonMode = true;
			leftBtn.buttonMode = true;
			rightBtn.addEventListener(MouseEvent.CLICK, buttonClick);
			leftBtn.addEventListener(MouseEvent.CLICK, buttonClick);
 
			//Place buttons on stage
			rightBtn.x = stage.stageWidth - 110;
			leftBtn.x = 110;
			rightBtn.y = stage.stageHeight / 2;
			leftBtn.y = (stage.stageHeight / 2) + 20;
			leftBtn.rotation = 180;
		}
 
		//Button actions
		protected function buttonClick(event:MouseEvent):void 
		{
			switch (event.target)
			{
				case rightBtn:
				currentItem --;
				break;
 
				case leftBtn:
				currentItem ++;
				break;
			}
			rotate();
		}
 
		//Creates a simple arrow shape / returns the sprite
		protected function createButton():Sprite
		{
			var btn:Sprite = new Sprite();
 
			btn.graphics.beginFill(0x333333);
			btn.graphics.moveTo(0, 0);
			btn.graphics.lineTo(0, 20);
			btn.graphics.lineTo(10, 10);
			btn.graphics.lineTo(0, 0);
			btn.graphics.endFill();
			return btn;
		}
	}
}

Download Away3D Tutorial Source

Posted in Away3D Carousel, Away3D Tutorials | Tagged , , , , | 1 Comment

A Simple Away3D Coverflow

Away3D Coverflow

Download Away3D Tutorial Source

When I originally wrote this tutorial for papervision2.com there were plenty of AS3 coverflows either for sale or for download. The one thing I felt most were lacking was simplicity. This once again is a no bells and whistles, stripped down coverflow with just the core functionality.

The heart of the coverflow is identical to the one on papervision2.com.

for (var i:int = 0; i < planes.length; i++) 
{
	var plane:Plane = planes[i];
 
	//Each if statement will adjust these numbers as needed
	var planeX:Number = 0;
	var planeZ:Number = -50;
	var planeRotationY:Number = 0
 
	//Place  & Animate Center Item
	if (i == currentItem) 
	{
		planeZ = -300
 
		TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } );
	} 
 
	//Place & Animate Right Items
	if(i > currentItem)  
	{
		planeX = (i - currentItem + 1) * 120;
		planeRotationY = angle + 10 * (i - currentItem);
 
		TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } );
	}
 
	//Place & Animate Left Items
	if (i < currentItem) 
	{
		planeX = (currentItem - i + 1) * -120;
		planeRotationY = -angle - 10 * (currentItem - i);
 
		TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } );
	}
}

I’ve setup two ways to navigate this particular coverflow.

1) By clicking on the planes

plane.addEventListener(MouseEvent3D.MOUSE_DOWN, onPlaneClick);
 
protected function onPlaneClick(evt:MouseEvent3D):void 
{
	currentItem = Number(evt.target.name);
	animate();
}

2) By using a left / right arrow navigation

rightBtn.addEventListener(MouseEvent.CLICK, buttonClick);
leftBtn.addEventListener(MouseEvent.CLICK, buttonClick);
 
protected function buttonClick(evt:MouseEvent):void 
{
	switch (evt.target)
	{
		case rightBtn:
		currentItem ++
		break;
 
		case leftBtn:
		currentItem --;
		break;
	}
 
	//Don't allow any number lower than 0 or past max so there
	//is always a center item
 
	if (currentItem < 0)
	{
		currentItem = 0;
	}
	if (currentItem > (planes.length - 1))
	{
		currentItem = planes.length - 1;
	}
 
	//Call animation
	animate();
}

Here is the full source code to look over. Feel free to leave a comment with any questions.

package 
{
	import away3d.containers.View3D;
	import away3d.events.MouseEvent3D;
	import away3d.materials.BitmapFileMaterial;
	import away3d.primitives.Plane;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.GlowFilter;
	import gs.easing.Quint;
	import gs.TweenLite;
 
	import away3d.events.MouseEvent3D
 
	/**
	 * ...
	 * @author Charlie Schulze, charlie[at]woveninteractive[dot]com
	 * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
	 */
 
	public class Main extends Sprite 
	{
		protected var planes:Array = [];
		protected var numItems:Number = 7;
		protected var currentItem:Number = 3;
		protected var angle:Number = 25;		
		protected var bitmapMaterial:BitmapFileMaterial;
		protected var rightBtn:Sprite;
		protected var leftBtn:Sprite;
		protected var view:View3D;
 
		public function Main():void 
		{
			super();
			this.addEventListener(Event.ADDED_TO_STAGE,onAddedToStage);	
		}
 
		protected function onAddedToStage(event:Event):void 
		{
			createChildren();
			createNavigation();
			animate();
			addEventListener(Event.ENTER_FRAME, onRenderTick);
		}
 
		protected function createChildren():void 
		{
			//Create your View3D
			view = new View3D({x:stage.stageWidth/2, y:stage.stageHeight/2});
			addChild(view);
 
			//Create Material
			bitmapMaterial = new BitmapFileMaterial("images/plane-art.png");
			bitmapMaterial.smooth 	= true;
 
			for (var i:int = 0; i < numItems; i++) 
			{
				var plane:Plane = new Plane({material:bitmapMaterial, width:177, height:334, segmentsH:4, segmentsW:4});
				planes.push(plane);
 
				//We need to set yUp otherwise the plane is defualt laying flat
				plane.yUp = false;
 
				//MouseEvent3D added to each of the planes
				plane.addEventListener(MouseEvent3D.MOUSE_DOWN, onPlaneClick);
 
				//Shortcut so that we can save a reference to the location of our plane
				plane.name = String(i);
 
				//Add plane to the scene
				view.scene.addChild(plane);
			}
 
			view.camera.zoom = 6;
		}
 
 
		protected function onPlaneClick(evt:MouseEvent3D):void 
		{
			currentItem = Number(evt.target.name);
			animate();
		}
 
 
		//Animate the coverflow left / right based off of currentItems
		protected function animate():void 
		{
			for (var i:int = 0; i < planes.length; i++) 
			{
				var plane:Plane = planes[i];
 
				//Each if statement will adjust these numbers as needed
				var planeX:Number = 0;
				var planeZ:Number = -50;
				var planeRotationY:Number = 0
 
				//Place  & Animate Center Item
				if (i == currentItem) 
				{
					planeZ = -300
 
					TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } );
				} 
 
				//Place & Animate Right Items
				if(i > currentItem)  
				{
					planeX = (i - currentItem + 1) * 120;
					planeRotationY = angle + 10 * (i - currentItem);
 
					TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } );
				}
 
				//Place & Animate Left Items
				if (i < currentItem) 
				{
					planeX = (currentItem - i + 1) * -120;
					planeRotationY = -angle - 10 * (currentItem - i);
 
					TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } );
				}
			}
		}
 
		protected function onRenderTick(event:Event):void 
		{
			view.render();
		}
 
		/*
		 * Everything below this point is just for creating the buttons and
		 * setting button events for controlling the coverflow. 
		 */
 
		protected function createNavigation():void 
		{
			//Create / Add Buttons
			rightBtn = createButton();
			leftBtn = createButton();
 
			addChild(leftBtn);
			addChild(rightBtn);
 
			//Add button listeners
			rightBtn.buttonMode = true;
			leftBtn.buttonMode = true;
			rightBtn.addEventListener(MouseEvent.CLICK, buttonClick);
			leftBtn.addEventListener(MouseEvent.CLICK, buttonClick);
 
			//Place buttons on stage
			rightBtn.x = stage.stageWidth - 20;
			leftBtn.x = 20;
			rightBtn.y =  stage.stageHeight / 2;
			leftBtn.y =  (stage.stageHeight / 2) + 20;
			leftBtn.rotation 	= 180;
		}
 
		//Button actions
		protected function buttonClick(evt:MouseEvent):void 
		{
			switch (evt.target)
			{
				case rightBtn:
				currentItem ++
				break;
 
				case leftBtn:
				currentItem --;
				break;
			}
 
			//Don't allow any number lower than 0 or past max so there
			//is always a center item
 
			if (currentItem < 0)
			{
				currentItem = 0;
			}
			if (currentItem > (planes.length - 1))
			{
				currentItem = planes.length - 1;
			}
 
			//Call animation
			animate();
		}
 
		//Creates a simple arrow shape / returns the sprite
		protected function createButton():Sprite
		{
			var btn:Sprite = new Sprite();
 
			btn.graphics.beginFill(0x333333);
			btn.graphics.moveTo(0, 0);
			btn.graphics.lineTo(0, 20);
			btn.graphics.lineTo(10, 10);
			btn.graphics.lineTo(0, 0);
			btn.graphics.endFill();
			btn.filters = [new GlowFilter(0xFFFFFF,1,10,10,3)]
			return btn;
		}
	}
}

Download Away3D Tutorial Source

Posted in Away3D Tutorials | Tagged , , , , , | Leave a comment

Basic Texturing with Away3D

Away3D Flash 3D Basic Texturing

Download Away3D Tutorial Source

In Away3D some of the objects you have to work with are (planes, cubes, cones, 3D Models, etc) and then you have the textures or materials that you add to these objects. Think of it as getting a brand new car and then painting that car another color or adding decals. We are essentially doing the same thing in principle – we have our object a cone (the car) and a material a bitmapMaterial (the paint / decals).

If you’re coming from Papervision3D you’ll notice a few differences

1) When you create an object such as a Cone you can set the properties with an object

cone = new Cone({material:bitmapMaterial, radius:20, height:200, smooth:true});
//vs papervision3d
//cone = new Cone(bitmapMaterial, 20, 200);

2) Your scene is not automatically centered for you. When you create your View3D, depending on your needs you may want the view to be centered on the stage.

view = new View3D( { x:320, y:240 } );
package
{
	import away3d.containers.View3D;
	import away3d.materials.BitmapFileMaterial;
	import away3d.primitives.Cone;
	import flash.display.Sprite;
	import flash.events.Event;
 
	public class Main extends Sprite
	{
		protected var cone:Cone
		protected var bitmapMaterial:BitmapFileMaterial;
		protected var view:View3D;
 
		public function Main()
		{
			super();
			this.addEventListener(Event.ADDED_TO_STAGE,onAddedToStage);
		}
 
		private function onAddedToStage(event:Event):void
		{
			createChildren();
		}
 
		public function createChildren():void
		{
			//Create your view3D
			view = new View3D( { x:stage.stageWidth/2, y:stage.stageHeight/2 } );
			addChild(view);
 
			//Create a new 3D object
			bitmapMaterial = new BitmapFileMaterial("images/ourtex.jpg")
			cone = new Cone({material:bitmapMaterial, radius:20, height:200, smooth:true});
 
			//Set some properties
			cone.pitch( -10);
 
			//Add to scene
			view.scene.addChild(cone);
 
			//Add a loop for rendering
			addEventListener(Event.ENTER_FRAME, onRenderTick);
		}
 
		protected function onRenderTick(event:Event = null):void
		{
			//Rotate
			cone.yaw(3);
 
			//Make sure you set your view to render each frame
			view.render();
		}
	}
}

Download Away3D Tutorial Source

Posted in Away3D Tutorials | Tagged , , , , , , , , , | 2 Comments