Airpaper - parte 2
Mais um dia sem muita demanda no trabalho, muita coisa sujeita à aprovação. Então… Vamos à mais uma parte do nosso jogo.
SEGUNDA PARTE. Cenário criado! E como surgiu a curiosidade de usar anáglifo - aquilo que chamam de 3d nos cinemas, novamente popularizado pelo filme Avatar - em Flash, decidi implementar para dar uma maior noção de pespectiva. Nada complicado e nada que não seja entendido depois de uma busca no google por “como fazer anáglifo”.
Usem óculos red-cyan! =P
NOTA 1. Nada refatorado, nada documentado, postergar isso sempre dá problema. #ficadica.
package {
// TWEENER
import caurina.transitions.Tweener;
import caurina.transitions.properties.CurveModifiers;
// SANDY
import sandy.core.data.Point3D;
import sandy.core.Scene3D;
import sandy.core.scenegraph.Camera3D;
import sandy.core.scenegraph.Group;
import sandy.core.scenegraph.Shape3D;
import sandy.core.scenegraph.TransformGroup;
import sandy.events.QueueEvent;
import sandy.events.SandyEvent;
import sandy.materials.Appearance;
import sandy.materials.attributes.CelShadeAttributes;
import sandy.materials.attributes.LightAttributes;
import sandy.materials.attributes.MaterialAttributes;
import sandy.materials.attributes.PhongAttributes;
import sandy.materials.BitmapMaterial;
import sandy.parser.IParser;
import sandy.parser.Parser;
import sandy.parser.ParserStack;
import sandy.util.LoaderQueue;
import sandy.view.ViewPort;
// DEBUGGER
import nl.demonsters.debugger.MonsterDebugger;
// MIC
import flash.media.Microphone;
import flash.system.Security;
import flash.system.SecurityPanel;
// OTHERS
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.errors.IllegalOperationError;
import flash.events.Event;
import flash.net.URLRequest;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
// ANAGLYPH
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.ColorTransform;
import sandy.core.scenegraph.Camera3D;
import sandy.core.scenegraph.Group;
import sandy.materials.Appearance;
import sandy.materials.BitmapMaterial;
import sandy.primitive.Box;
import sandy.primitive.Plane3D;
import sandy.materials.ColorMaterial;
/**
* ...
* @author contato [at] andrecaribe [dot] com [dot] br
* @since 2010-02-25
* @release 0
* @revision 2
*/
public class Airplane extends MovieClip {
// Public properties
public var d:MonsterDebugger = new MonsterDebugger(this);
// Private properties
private var _mic:Microphone;
private var _timer:Timer;
private var _scene:Scene3D;
private var _camera:Camera3D;
private var _propeller:Shape3D;
private var _airplane:Shape3D;
private var _plane1:Plane3D;
private var _plane2:Plane3D;
private var _cloud1:Plane3D;
private var _cloud2:Plane3D;
private var _parserStack:ParserStack = null;
private var _queue:LoaderQueue = null;
private var _transformGroup:TransformGroup;
private var _airplanePosition:Object = { x:0, y:0, z:-200,
rotateX:0, rotateY:180, rotateZ:0,
roll:0, tilt:0, time:0 };
private var bmScreen:Bitmap = new Bitmap (new BitmapData (500, 500, true, 0));
private var mcBuffer:Sprite = new Sprite ();
private var ctLeft:ColorTransform = new ColorTransform (1, 0, 0);
private var ctRight:ColorTransform = new ColorTransform (0, 1 - 0.125, 1 - 0.05);
/**
* ...
*/
public function Airplane():void {
MonsterDebugger.trace(trace, "Airplane");
// MIC
Security.showSettings(SecurityPanel.MICROPHONE);
_mic = Microphone.getMicrophone();
_mic.setLoopBack(true);
_mic.setUseEchoSuppression(true);
CurveModifiers.init();
loadModels();
}
/**
* ...
*/
private function loadModels():void {
MonsterDebugger.trace(trace, "loadModels");
var parserPropeller:IParser = Parser.create("helice.ASE", Parser.ASE);
var parserAirplane:IParser = Parser.create("aviao.ASE", Parser.ASE);
_parserStack = new ParserStack();
_parserStack.add("propeller", parserPropeller);
_parserStack.add("airplane", parserAirplane);
_parserStack.addEventListener(ParserStack.COMPLETE, parserComplete);
_parserStack.start();
}
/**
* ...
* @param event:Event
*/
private function parserComplete(event:Event):void {
MonsterDebugger.trace(trace, "parserComplete");
_parserStack.removeEventListener(ParserStack.COMPLETE, parserComplete);
_propeller = _parserStack.getGroupByName("propeller").children[0] as Shape3D;
_airplane = _parserStack.getGroupByName("airplane").children[0] as Shape3D;
loadTextures();
}
/**
* ...
*/
private function loadTextures():void {
MonsterDebugger.trace(trace, "loadTextures");
_queue = new LoaderQueue();
_queue.add("propellerTexture", new URLRequest("helice.png") );
_queue.add("airplaneTexture", new URLRequest("aviao.png") );
_queue.addEventListener(SandyEvent.QUEUE_COMPLETE, loadComplete);
_queue.start();
}
/**
* ...
* @param event:QueueEvent
*/
private function loadComplete(event:QueueEvent):void {
MonsterDebugger.trace(trace, "loadComplete");
_queue.removeEventListener(SandyEvent.QUEUE_COMPLETE, loadComplete);
_camera = new Camera3D(500,500, 45, 50, 10000);
_camera.viewport = new ViewPort(500, 500);
var root:Group = createScene();
var canvas:Sprite = new Sprite();
this.addChild(canvas);
_scene = new Scene3D("scene", canvas, _camera, root);
_scene.container = mcBuffer;
// CLICK TO START
addEventListener(MouseEvent.CLICK, clickToStart);
reset();
}
/**
* ...
* @param event:MouseEvent
*/
function clickToStart(event:MouseEvent):void {
removeEventListener(MouseEvent.CLICK, clickToStart);
addEventListener(MouseEvent.CLICK, clickToStop);
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
_timer = new Timer(5000);
_timer.addEventListener(TimerEvent.TIMER, moveToSide);
_timer.start();
moveToSide();
}
/**
* ...
* @param event:MouseEvent
*/
function clickToStop(event:MouseEvent):void {
addEventListener(MouseEvent.CLICK, clickToStart);
removeEventListener(MouseEvent.CLICK, clickToStop);
removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
_timer.stop();
_timer.removeEventListener(TimerEvent.TIMER, moveToSide);
_timer = null;
}
/**
* ...
* @return Group
*
* @see sandy.core.scenegraph.Group
*/
private function createScene():Group {
MonsterDebugger.trace(this, "createScene");
var g:Group = new Group();
_plane1 = new Plane3D( "back", 500, 500, 1, 1 );
var planeApp1:Appearance = new Appearance (
new BitmapMaterial (new BackgroundBack(1, 1), null, 0));
//new ColorMaterial(0x7CBEF2, 1, null));
//
_plane1.appearance = planeApp1;
_plane1.z = 200;
g.addChild(_plane1);
_plane2 = new Plane3D( "front", 500, 500, 1, 1 );
var planeApp2:Appearance = new Appearance (
new BitmapMaterial (new BackgroundFront(1, 1), null, 0));
//new ColorMaterial(0x7CBEF2, 1, null));
_plane2.appearance = planeApp2;
_plane2.y = 100;
_plane2.z = 0;
g.addChild(_plane2);
_cloud1 = new Plane3D( "cloud1", 70, 140, 1, 1 );
var _cloudApp1:Appearance = new Appearance (
new BitmapMaterial (new Cloud_PNG(1, 1), null, 0));
//new ColorMaterial(0x7CBEF2, 1, null));
_cloud1.appearance = _cloudApp1;
_cloud1.x = 30
_cloud1.y = -30;
_cloud1.z = 200;
g.addChild(_cloud1);
_cloud2 = new Plane3D( "cloud2", 70, 140, 1, 1 );
_cloud2.appearance = _cloudApp1;
_cloud2.x = -40;
_cloud2.y = 40;
_cloud2.z = 0;
g.addChild(_cloud2);
// ILUMINATION
// Cel-Shader
//var ilumination:CelShadeAttributes = new CelShadeAttributes();
// Phong
//var ilumination:PhongAttributes = new PhongAttributes (true, 0.2, 15);
//ilumination.diffuse = .8;
//ilumination.specular = .8;
//ilumination.gloss = 100;
// Normal
var ilumination:LightAttributes = new LightAttributes (true, 0.3);
ilumination.diffuse = 0.5;
ilumination.specular = 1;
ilumination.gloss = 5;
// TEXTURES
var propellerMaterial:BitmapMaterial = new BitmapMaterial(_queue.data["propellerTexture"].bitmapData);
var propellerApp:Appearance = new Appearance(propellerMaterial);
_propeller.appearance = propellerApp;
var airplaneMaterial:BitmapMaterial = new BitmapMaterial(_queue.data["airplaneTexture"].bitmapData, new MaterialAttributes(ilumination));
var airplaneApp:Appearance = new Appearance( airplaneMaterial );
airplaneApp.lightingEnable = true;
_airplane.appearance = airplaneApp;
// GROUP
_transformGroup = new TransformGroup('airplaneGroup');
_transformGroup.addChild(_propeller);
_transformGroup.addChild(_airplane);
_transformGroup.enableBackFaceCulling = true;
g.addChild(_transformGroup);
// ANAGLYPH
this.addChild (bmScreen);
return g;
}
/**
* ...
*/
private function reset():void {
MonsterDebugger.trace(this, "reset");
_transformGroup.resetCoords();
Tweener.addTween(_transformGroup, _airplanePosition);
enterFrameHandler(null);
}
/**
* ...
* @param event:Event = null
*/
private function enterFrameHandler(event:Event = null):void {
// Airplane and propeller
_propeller.rotateZ += 50;
_transformGroup.y += (_mic.activityLevel-20)/32;
// Plane
_plane1.z -= .03;
_plane2.y -= .05;
_plane2.z -= .05;
// Cloud
_cloud1.z -= 10;
if(_cloud1.z < -300) {
_cloud1.z = 0;
}
_cloud2.z -= 8;
if(_cloud2.z < -300) {
_cloud2.z = 0;
}
// Screen
bmScreen.bitmapData.fillRect (bmScreen.bitmapData.rect, 0);
_scene.camera.moveSideways(+4);
_scene.render();
bmScreen.bitmapData.draw (mcBuffer, null, ctRight, BlendMode.ADD);
_scene.camera.moveSideways(-4);
_scene.render();
bmScreen.bitmapData.draw (mcBuffer, null, ctLeft, BlendMode.ADD);
}
/**
* ...
* @param event:TimerEvent
*/
private function moveToSide(event:TimerEvent = null):void {
if(_timer.currentCount % 2 == 0) {
Tweener.addTween(_transformGroup, {x:5, roll:-5, time:5, transition:"easeOutInQuad"} );
} else {
Tweener.addTween(_transformGroup, {x:-5, roll:5, time:5, transition:"easeOutInQuad"} );
}
if(_timer.currentCount % 4 == 0) {
Tweener.addTween(_transformGroup, {z:-210, time:5, transition:"easeOutInQuad"} );
} else {
Tweener.addTween(_transformGroup, {z:-190, time:5, transition:"easeOutInQuad"} );
}
}
}
}



