DOWNLOAD Comb Over Charlie Trial Now
DOWNLOAD Comb Over Charlie Trial Now
Full story at Papervision2.com
DOWNLOAD Comb Over Charlie Trial Now
DOWNLOAD Comb Over Charlie Trial Now
Full story at Papervision2.com
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.
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”:
Here are a few things I learned while creating Comb Over Charlie:
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
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); } } } |
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
handleis doing:
Once the file has been loaded and is ready to view, thehandlereturns 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); } } } } |
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; } } } |
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; } } } |
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(); } } } |