Human Theatre
One AWD2 file from max
Two animated model of man and woman on the same squeleton
Multy clone technique with self animation
Code, Model and map by LoTh
Blog : http://3dflashlo.wordpress.com
/**
* Copyright Loth2012 ( http://wonderfl.net/user/Loth2012 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/58I2
*/
package {
import away3d.animators.transitions.CrossfadeStateTransition;
import away3d.animators.SkeletonAnimationState;
import away3d.animators.SkeletonAnimationSet;
import away3d.animators.SkeletonAnimator;
import away3d.animators.data.Skeleton;
import away3d.lights.shadowmaps.NearDirectionalShadowMapper;
import away3d.materials.methods.FilteredShadowMapMethod;
import away3d.materials.methods.NearShadowMapMethod;
import away3d.core.managers.Stage3DManager;
import away3d.core.managers.Stage3DProxy;
import away3d.containers.ObjectContainer3D;
import away3d.events.Stage3DEvent;
import away3d.entities.Mesh;
import away3d.debug.AwayStats;
import away3d.primitives.SkyBox;
import away3d.lights.LightBase;
import away3d.loaders.Loader3D;
import away3d.lights.LightProbe;
import away3d.lights.PointLight;
import away3d.events.LoaderEvent;
import away3d.containers.View3D;
import away3d.events.AssetEvent;
import away3d.core.base.Geometry;
import away3d.events.MouseEvent3D;
import away3d.library.AssetLibrary;
import away3d.materials.LightSources;
import away3d.textures.BitmapTexture;
import away3d.materials.ColorMaterial;
import away3d.lights.DirectionalLight;
import away3d.library.assets.AssetType;
import away3d.loaders.parsers.AWD2Parser;
import away3d.materials.methods.FogMethod;
import away3d.materials.methods.OutlineMethod;
import away3d.materials.methods.CelDiffuseMethod;
import away3d.materials.methods.CelSpecularMethod;
import away3d.materials.methods.EnvMapMethod;
import away3d.materials.methods.LightMapMethod;
import away3d.materials.methods.FresnelSpecularMethod;
import away3d.materials.methods.TripleFilteredShadowMapMethod;
import away3d.materials.lightpickers.StaticLightPicker;
import away3d.cameras.lenses.PerspectiveLens;
import away3d.materials.DefaultMaterialBase;
import away3d.controllers.HoverController;
import away3d.materials.TextureMaterial;
import away3d.primitives.SphereGeometry;
import away3d.primitives.PlaneGeometry;
import org.flintparticles.integration.away3d.v4.A3D4Renderer;
import flash.filters.DropShadowFilter;
import flash.display.StageScaleMode;
import flash.display.StageQuality;
import flash.events.KeyboardEvent;
import flash.display.BitmapData;
import flash.display.StageAlign;
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.text.TextFormat;
import flash.text.TextField;
import flash.display.LoaderInfo;
import flash.display.Bitmap;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.Shape;
import flash.geom.Vector3D;
import flash.events.Event;
import flash.geom.Matrix;
import flash.ui.Keyboard;
import flash.net.URLRequest;
import flash.display.DisplayObject;
import flash.events.ProgressEvent;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.system.LoaderContext;
/**
*
* HUMAN THEATRE beta 0.1
*
* One AWD2 file from max
* Two animated model of man and woman on the same squeleton
* Multy clone technique with self animation
*
* Code, Model and map by LoTh
* Blog : http://3dflashlo.wordpress.com
*
*/
public class HumanTheatre extends Sprite {
private static const SCALE:Number = 16;
private static var COLOR:Object = {
sun : 0xFFFFEF, moon : 0x33FF80,
sky : 0xFFFFFF , ground : 0x6D6145,
background : 0x000000 , fog : 0xAEAEA8
}
private static var DemoAmbiant:Array = [0.85, 0.1];
private static var DemoDiffuse:Array = [1, 1];
private static var DemoSpecular:Array = [1, 0.5];
private static var _capture : Bitmap;
private static var _player:Mesh;
// mapping online
private static const MESH_PATH:String = 'http://3dflashlo.free.fr/wonderfl/assets/';
private static const PATH:String = "http://assets.wonderfl.net/images/related_images/"
private static const FILES:Array =[
'/f/f1/f1ad/f1ad270ccefb2f72a1a770c69e2003baf4c525ab', '/3/3a/3a97/3a97741efaeeb0f3a556cc39a305fe4278b73e94',
'/b/b3/b321/b3216c9e0d279b0103e17c780f1c62cfd7e44e6d', '/9/92/92ff/92ffe84a7ebdc2c8841337d9f0fe8cf9cc0e9efa',
];
// mapping Local
private static const PATH_LOCAL:String = 'assets/';
private static const FILES_LOCAL:Array = [ 'amphy.jpg', 'front.jpg', 'man.jpg', 'woman.jpg'];
private static var _local:Boolean = false;
// engine
protected static var _lightPicker:StaticLightPicker;
protected static var _hoverCtrl:HoverController;
protected static var _stage3DProxy:Stage3DProxy;
protected static var _manager:Stage3DManager;
protected static var _stats:AwayStats;
protected static var _skyBox:SkyBox;
protected static var _view:View3D;
// referency
private var _materialMan:Vector.<DefaultMaterialBase>;
private var _materialWoman:Vector.<DefaultMaterialBase>;
private var _materials:Vector.<DefaultMaterialBase>;
private var _mapList:Vector.<BitmapData>;
private var _light:Array;
private var _n:int;
private var _i:int;
// animation
//private var animator:SkeletonAnimator;
private var _squeleton:Skeleton;
private var _animationSet:SkeletonAnimationSet;
private var stateTransition:CrossfadeStateTransition = new CrossfadeStateTransition(0.5);
// character movement
private var currentRotationInc:Number = 0;
private var movementDirection:Number;
private var isRunning:Boolean;
private var isMoving:Boolean;
private var isJumping:Boolean;
private var currentAnim:String;
// animation constants
private static const SEQUENCE:Array = ['Breathe', 'Sit', 'SitWoman' , 'Walk', 'Run'];
private static const SEQUENCE_MAN:Array = ['Breathe', 'Sit', 'Walk', 'Run'];
private static const SEQUENCE_WOMEN:Array = ['Breathe', 'SitWoman', 'WalkWoman', 'Run'];
private static const SEQSPEED:Array = [0.5, 1, 1, 0.5, 0.5, 0.5, 0.5, 0.5];
private static const ROTATION_SPEED:Number = 10;
private static const XFADE_TIME:Number = 0.5;
// scene objects
private var _hero:Mesh;
private var _box:Mesh;
private var _deco:Mesh;
private var _decoFront:Mesh;
// Avatar referency
private var _skinMesh:Vector.<Mesh>;
private var _cloneAnim:Vector.<SkeletonAnimator>;
private var _cloneHair:Vector.<Mesh>;
private var _cloneStyleMan:Vector.<Mesh>;
private var _cloneStyleWoman:Vector.<Mesh>;
// Particule container
private var emitter:EmitterSmoke;
private var particleContainer:ObjectContainer3D;
private var particleRenderer:A3D4Renderer;
// navigation
private var _prevMouseX:Number;
private var _prevMouseY:Number;
private var _mouseMove:Boolean;
private var _cameraHeight:Number = 0;
private var _eyePosition:Vector3D;
private var _mapper:Mapper;
private var _text:TextField;
private var _fog:FogMethod;
private var _reflect:EnvMapMethod;
private var _specularMethod:FresnelSpecularMethod;
private var _shadowMethod:NearShadowMapMethod;
private var photoLoad:PhotoLoader;
/** Constructor */
public function HumanTheatre() {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
}
private function init(e:Event = null):void{
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.align = 'TL';
stage.scaleMode = 'noScale';
stage.quality = 'low';
stage.frameRate = 60;
stage.color = COLOR.background;
// ★ wonderfl capture
Wonderfl.disable_capture();
//_capture = addChild(new Bitmap(new BitmapData(465, 465, false, 0x000000))) as Bitmap ;
_manager = Stage3DManager.getInstance(stage);
_stage3DProxy = _manager.getFreeStage3DProxy();
_stage3DProxy.addEventListener(Stage3DEvent.CONTEXT3D_CREATED, onContextCreated);
}
private function onContextCreated(e:Stage3DEvent):void{
_stage3DProxy.color = COLOR.background;
_stage3DProxy.antiAlias = 4;
initEngine();
initText();
initLights();
initListeners();
// start by loading all bitmap
_mapList = new Vector.<BitmapData>();
loadBitmap();
// character mesh referency
_skinMesh = new Vector.<Mesh>();
// hair style clone referency
_cloneStyleMan = new Vector.<Mesh>();
_cloneStyleWoman = new Vector.<Mesh>();
}
//-------------------------------- AWAY3D
/** Initialise the engine */
private function initEngine():void {
_view = new View3D();
_view.stage3DProxy = _stage3DProxy;
_view.shareContext = true;
_view.backgroundColor = COLOR.background;
_view.camera.lens = new PerspectiveLens(80);
_view.camera.lens.far = 20000;
_view.camera.lens.near = 1;
_hoverCtrl = new HoverController(_view.camera, null, 180, 0, 100*SCALE, 6, 90);
_hoverCtrl.tiltAngle = 0;
_hoverCtrl.panAngle = 180;
_hoverCtrl.minTiltAngle = -60;
_hoverCtrl.maxTiltAngle = 60;
_hoverCtrl.autoUpdate = false;
addChild(_view);
//away3d stat
_stats = new AwayStats(_view, false, true);
_stats.alpha = 0.3;
addChild(_stats);
//material reference
_materials = new Vector.<DefaultMaterialBase>();
_materialMan = new Vector.<DefaultMaterialBase>();
_materialWoman = new Vector.<DefaultMaterialBase>();
//light referency
_light = [];
// hero content
_player = new Mesh(new Geometry());
_view.scene.addChild(_player);
_player.y = 0//20 * SCALE;
//auto map generator
_mapper = new Mapper();
}
//-------------------------------- PARTICULE
private function addParticule():void {
// flint
emitter = new EmitterSmoke(this);
emitter.start();
// Create Particle Container
particleContainer = new ObjectContainer3D();
particleContainer.visible = true;
_view.scene.addChild(particleContainer);
particleRenderer = new A3D4Renderer(particleContainer);
particleRenderer.addEmitter(emitter);
}
//-------------------------------- LOOP
/** Render loop */
private function onEnterFrame(event:Event):void {
//update character animation
_player.rotationY += currentRotationInc;
_hoverCtrl.lookAtPosition = new Vector3D(_player.x, _player.y + (30 * SCALE), _player.z);
updateClone();
//update camera controler
_hoverCtrl.update();
//update light
//_light[1].position = _view.camera.position;
//update view
_view.render();
// ★ wonderfl capture
if (_capture) _stage3DProxy.context3D.drawToBitmapData(_capture.bitmapData);
}
//-------------------------------- LISTENER
/** Initialise the listeners */
private function initListeners():void {
//add render loop
_stage3DProxy.addEventListener(Event.ENTER_FRAME, onEnterFrame, false, 0, true);
//add key listeners
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp, false, 0, true);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown, false, 0, true);
//navigation
stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown, false, 0, true);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove, false, 0, true);
stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseLeave, false, 0, true);
stage.addEventListener(MouseEvent.MOUSE_WHEEL, onStageMouseWheel, false, 0, true)
stage.addEventListener(Event.MOUSE_LEAVE, onStageMouseLeave, false, 0, true);
//add resize event
stage.addEventListener(Event.RESIZE, onResize, false, 0, true);
onResize();
}
//-------------------------------- LIGHT
/** Initialise the lights */
private function initLights():void {
//create a light for shadows that mimics the sun's position in the skybox
var sun:DirectionalLight = new DirectionalLight(0.1, -1, 0.35);
sun.castsShadows = true;
sun.shadowMapper = new NearDirectionalShadowMapper(0.3);
_view.scene.addChild(sun);
_light.push(sun);
//create a light for ambient effect that mimics the sky
var moon:PointLight = new PointLight();
moon.y = -600*SCALE;
moon.radius = 200;
moon.fallOff = 2500;
_view.scene.addChild(moon);
_light.push(moon);
makeSky();
}
//-------------------------------- SKY
/** sky change */
private function randomSky():void {
COLOR.ground = 0xFFFFFF * Math.random();
COLOR.fog = 0xFFFFFF * Math.random();
COLOR.sky = 0xFFFFFF * Math.random();
COLOR.sun = 0xFFFFFF * Math.random();
COLOR.moon = 0xFFFFFF * Math.random();
DemoAmbiant = [0.4, 0.3];
DemoAmbiant = [Math.random(), Math.random()];
DemoDiffuse = [Math.random(), Math.random()];
DemoSpecular = [Math.random() * 4, Math.random() * 2];
makeSky();
}
private function makeSky():void {
if (_light[2]) {
_view.scene.removeChild(_light[2]);
_light.pop();
}
if (_skyBox) {
_view.scene.removeChild(_skyBox);
_skyBox.dispose();
}
//generate vector degrade sky
_mapper.vectorSky([COLOR.ground, COLOR.fog, COLOR.sky], 8);
_skyBox = new SkyBox(_mapper.sky);
_view.scene.addChild(_skyBox);
//add new probe light
var probe:LightProbe = new LightProbe(_mapper.sky);
_view.scene.addChild(probe);
_light.push(probe);
//sun
_light[0].color = COLOR.sun;
_light[0].ambientColor = COLOR.fog;
_light[0].ambient = DemoAmbiant[0];
_light[0].diffuse = DemoDiffuse[0];
_light[0].specular = DemoSpecular[0];
// moon
_light[1].color = COLOR.moon;
_light[1].ambientColor = COLOR.ground;
_light[1].ambient = DemoAmbiant[1];
_light[1].diffuse = DemoDiffuse[1];
_light[1].specular = DemoSpecular[1];
_lightPicker = new StaticLightPicker(_light);
for each (var o:DefaultMaterialBase in _materials) {
o.lightPicker = _lightPicker;
}
if(_fog) _fog.fogColor = COLOR.fog;
}
//-------------------------------- MATERIAL
/** Initialise the material */
protected function initMaterial():void {
// global methode
_fog = new FogMethod(200*SCALE, 2000*SCALE, COLOR.fog);
//_reflect = new EnvMapMethod(_mapper.sky, 0.5)
_specularMethod = new FresnelSpecularMethod();
_specularMethod.normalReflectance = 0.3
// global shadow
_shadowMethod = new NearShadowMapMethod(new FilteredShadowMapMethod(_light[0]), 0.05);
_shadowMethod.epsilon = .0007;
var material:DefaultMaterialBase;
// 0 - ground
var grid:Shape = new Shape();
grid.graphics.beginFill(0x333333, 0.3);
grid.graphics.drawRect(0, 0, 4, 128);
grid.graphics.drawRect(0, 0, 128, 4);
var b:BitmapData = new BitmapData(128, 128, false, 0x91825F);
b.draw(grid);
material = materialFromBitmap('ground', [b, b, b], true, false);
material.ambient = 1;
material.gloss = 30;
material.specular = 1;
material.repeat = true;
// 1 - Hero
var bsize:int = 512;
/* grid.graphics.clear();
grid.graphics.beginFill(0xAAAAAA, 1);//full
grid.graphics.drawRect(0, 0, bsize, bsize);
grid.graphics.beginFill(0xAA8000, 1);//head
grid.graphics.drawRect(0, 0, bsize, 178);
grid.graphics.beginFill(0xEEEEEE, 1);//shirt
grid.graphics.drawRect(0, 178, bsize, 160);
grid.graphics.beginFill(0x333333, 1);//shoes
grid.graphics.drawRect(0, 472, bsize, 40);
var g:Bitmap = new Bitmap(_mapList[2]);
var f:Sprite = new Sprite();
f.addChild(g);
f.addChild(grid);
grid.blendMode = 'multiply';
var b:BitmapData = new BitmapData(512, 512, false, 0x606060);
b.draw(f);*/
material = materialFromBitmap('hero', [_mapList[2]], false, false, false, true);
material.gloss = 10;
material.specular = 0.2;
material.ambient = 1;
// 2 - Amphy
material = materialFromBitmap('amphy', [_mapList[0]], false, false, false, true);
material.ambient = 1;
material.gloss = 100;
material.specular = 0.1;
// 3 - Amphy front
material = materialFromBitmap('front', [_mapList[1]], false, false, false, true);
material.ambient = 1;
material.gloss = 30;
material.specular = 0.2;
// 4 _ hair
grid.graphics.clear();
grid.graphics.beginFill(0x333333, 1);//full
grid.graphics.drawRect(0, 0, bsize, bsize);
b = new BitmapData(512, 512, false, 0x202020);
b.draw(grid);
material = materialFromBitmap('hair', [b], false, false, false, true);
material.ambient = 1;
material.gloss = 10;
material.specular = 0.2;
// 5_woman
material = materialFromBitmap('hero', [_mapList[3]], false, false, false, true);
material.gloss = 10;
material.specular = 0.2;
material.ambient = 1;
}
/** Make Material from bitmap */
protected function materialFromBitmap(name:String, Bitmaps:Array, Norm:Boolean = false, Spec:Boolean = false, Occ:Boolean = false, cartoon:Boolean = false):DefaultMaterialBase {
var n:int;
var material:TextureMaterial = new TextureMaterial(new BitmapTexture(Bitmaps[0]));
// normal map
if (Norm) { n = 1; material.normalMap = new BitmapTexture(Bitmaps[n]); }
// specular map
if (Spec) { n = 2; material.specularMap = new BitmapTexture(Bitmaps[n]); }
// occlusion
if (Occ) { n = 3; material.addMethod(new LightMapMethod(new BitmapTexture(Bitmaps[n]))); }
material.name = name;
material.lightPicker = _lightPicker;
material.diffuseLightSources = LightSources.PROBES;
material.specularLightSources = LightSources.LIGHTS;
// material.specularMethod = _specularMethod;
material.shadowMethod = _shadowMethod;
if (cartoon) {
material.addMethod(new OutlineMethod(0x000000, 0.2, true));
// material.diffuseMethod = new CelDiffuseMethod(3);
// CelDiffuseMethod(material.diffuseMethod).smoothness = .3;
//material.specularMethod = new CelSpecularMethod(.2);
//CelSpecularMethod(material.specularMethod).smoothness = .3;
}
material.addMethod(_fog);
//push to reference
_materials.push(material);
return material;
}
//-------------------------------- BINARY LOADER
/** Global Load Binary file */
private function load(url:String):void {
var loader:URLLoader = new URLLoader();
var extention:String = url.substring(url.length - 3);
loader.dataFormat = URLLoaderDataFormat.BINARY;
if(extention == 'awd') loader.addEventListener(Event.COMPLETE, parseAWD, false, 0, true);
loader.addEventListener(ProgressEvent.PROGRESS, loadProgress, false, 0, true);
loader.load(new URLRequest(url));
}
/** Display current load */
private function loadProgress(e:ProgressEvent):void {
var P:int = int(e.bytesLoaded / e.bytesTotal * 100);
if (P != 100) log('Load : ' + P + ' % | ' + int((e.bytesLoaded / 1024) << 0) + ' ko\n');
else message();
}
//-------------------------------- BITMAP DISPLAY
/** load bitmap from WonderFl or Local */
public function loadBitmap():void {
_n = 0;
photoLoad = new PhotoLoader();
completeBitmap(); // start first
}
protected function completeBitmap(e:Event=null):void {
if (e) {
var f:Bitmap = new Bitmap(photoLoad.content);
_mapList.push(f.bitmapData);
_n++;
}
if (FILES[_n]){
log("image " + _n);
photoLoad = new PhotoLoader();
photoLoad.addEventListener(PhotoLoader.COMPLETE, completeBitmap, false, 0, true);
if (_local) photoLoad.load(PATH_LOCAL + FILES_LOCAL[_n]);
else photoLoad.load(PATH+FILES[_n]);
} else {
// create material
initMaterial();
// start Loading AWD
if (_local) load(PATH_LOCAL + "simple.awd");
else load(MESH_PATH+"simple.awd");
}
}
//-------------------------------- AWD DISPLAY
/** Load AWD */
private function parseAWD(e:Event):void {
var loader:URLLoader = e.target as URLLoader
var loader3d:Loader3D = new Loader3D(false);
loader3d.addEventListener(AssetEvent.ASSET_COMPLETE, onAssetComplete, false, 0, true);
loader3d.addEventListener(LoaderEvent.RESOURCE_COMPLETE, finalAWD, false, 0, true);
loader3d.loadData(loader.data, null, null, new AWD2Parser());
loader.removeEventListener(ProgressEvent.PROGRESS, loadProgress);
loader.removeEventListener(Event.COMPLETE, parseAWD);
loader = null;
}
/** Listener function for asset complete event on awd */
private function onAssetComplete(event:AssetEvent):void {
var mesh:Mesh;
var material:TextureMaterial;
var specularMethod:FresnelSpecularMethod;
// ++ Skeleton referency same for man and woman
if (event.asset.assetType == AssetType.SKELETON) {
_animationSet = new SkeletonAnimationSet(2);
_squeleton = event.asset as Skeleton;
// ++ Animations create state objects for each animation state encountered
} else if (event.asset.assetType == AssetType.ANIMATION_STATE) {
var animationState:SkeletonAnimationState = event.asset as SkeletonAnimationState;
_animationSet.addState(animationState.name, animationState);
// ++ Mesh
} else if (event.asset.assetType == AssetType.MESH) {
mesh = Mesh(event.asset);
// Character Men & Woman
if (mesh.name.substring(0, 4) == "Skin") {
mesh.scale(SCALE * 0.45);
if (mesh.name == 'Skin_Man') mesh.material = _materials[1];
if (mesh.name == 'Skin_Woman') mesh.material = _materials[5];
_skinMesh.push(mesh);
}
// Character hair no scale because hero child
if (mesh.name.substring(0, 8) == "Hair_Man") {
mesh.material = _materials[4];
_cloneStyleMan.push(mesh);
}
if (mesh.name.substring(0, 8) == "Hair_Wom") {
mesh.material = _materials[4];
_cloneStyleWoman.push(mesh);
}
// Scene decoration
if (mesh.name == "Deco") {
_deco = mesh;
_deco.material = _materials[2];
_deco.scale(SCALE);
}
if (mesh.name == "DecoFront") {
_decoFront = mesh;
_decoFront.material = _materials[3];
_decoFront.scale(SCALE);
}
if (mesh.name == "Box") {
_box = mesh;
_box.material = _materials[0];
_box.castsShadows = false;
_box.geometry.scaleUV(50, 50);
_box.scale(SCALE);
}
}
}
/** Check if all resourse loaded */
private function finalAWD(e:LoaderEvent):void {
var loader3d:Loader3D = e.target as Loader3D;
loader3d.removeEventListener(AssetEvent.ASSET_COMPLETE, onAssetComplete);
loader3d.removeEventListener(LoaderEvent.RESOURCE_COMPLETE, finalAWD);
_view.scene.addChild(_deco);
_view.scene.addChild(_decoFront);
_view.scene.addChild(_box);
// add people in theatre
populateTheatre();
// add player avatar
_hero = addAvatar({target:_player});
rest();
addParticule();
}
//-------------------------------- CLONE AVATAR
/** Duplicate Man or Woman into Avatar with self animation */
public function addAvatar(o:Object = null):Mesh {
if (o == null) o = new Object();
if(!_cloneAnim)_cloneAnim = new Vector.<SkeletonAnimator>();
if(!_cloneHair)_cloneHair = new Vector.<Mesh>();
var sex:int = o.sex || rand(1);// 0:man 1:woman
var hair:Mesh;
var skin:Mesh = Mesh((_skinMesh[sex]).clone());
// position & rotation
if(o.rot!=null)skin.yaw(o.rot.y || 0);
skin.position = o.pos || new Vector3D();
if (o.target!=null) o.target.addChild(skin);
else _view.scene.addChild(skin);
// choose random hair style;
if (o.hair==null) o.hair = true;
if(o.hair){
if (sex == 0) hair = Mesh((_cloneStyleMan[rand(_cloneStyleMan.length - 1)]).clone());
else hair = Mesh((_cloneStyleWoman[rand(_cloneStyleWoman.length - 1)]).clone());
_cloneHair.push(hair);
skin.addChild(hair);
}
// create new animator
var animatorX:SkeletonAnimator = new SkeletonAnimator(_animationSet, _squeleton);
animatorX.updateRootPosition = false;
if(o.hair)_cloneAnim.push(animatorX);
// play random animation
var num:int = o.anim || (int(Math.random() * 2));
var anim:String;
if (sex == 0) anim = SEQUENCE_MAN[num];
else anim = SEQUENCE_WOMEN[num];
animatorX.playbackSpeed = o.speed || -SEQSPEED[num];
animatorX.play(anim, stateTransition);
skin.animator = animatorX;
return skin;
}
/** Special populate for Theatre */
private function populateTheatre(n:int = 11):void {
var list:Vector.<Object> = new Vector.<Object>();
var r:int, d:int = 200, nh:int = 45, obj:Object;
for (var j:int = 1; j < n; j++) {
if (j == 1) { nh = 16; d = 80; }
if (j == 2) { nh = 22; d = 100; }
if (j == 3) { nh = 24; d = 120; }
if (j == 4) { nh = 26; d = 140; }
if (j == 5) { nh = 30; d = 160; }
if (j == 6) { nh = 35; d = 180; }
if (j == 7) { nh = 40; d = 200; }
for (_i = 1; _i < nh; _i++) {
r = -30 + ( _i * (240 / nh));
obj = new Object();
obj['rot'] = new Vector3D(0, 90 - r, 0);
if (j < 7) obj['pos'] = orbit( 90, r , (d + 5) * SCALE, (20 * SCALE) + (j * (20 * SCALE)));
else obj['pos'] = orbit( 90, r , (d + 5) * SCALE, (20 * SCALE) + (j * (20 * SCALE) ) + ((j - 7) * (40 * SCALE)) );
list.push(obj);
}
}
var avatar:Mesh;
for (_i = 0; _i < list.length; _i++ ) {
avatar = addAvatar(list[_i])
}
}
/** Update Hair animation to follow head bone */
private function updateClone():void {
var anim:SkeletonAnimator;
for (_i = 0; _i < _cloneAnim.length; _i++) {
anim = _cloneAnim[_i];
if (anim.globalPose.numJointPoses == 25)
_cloneHair[_i].transform = anim.globalPose.jointPoses[24].toMatrix3D();
}
}
//-------------------------------- ANIMATION
/** Character breath animation */
private function rest():void {
isMoving = false;
_hero.animator.playbackSpeed = SEQSPEED[0];
if (currentAnim == SEQUENCE[0]) return;
currentAnim = SEQUENCE[0];
_hero.animator.play(currentAnim, stateTransition);
}
/** Character fight animation */
private function fight():void {
if (currentAnim == SEQUENCE[3]) return;
currentAnim = SEQUENCE[3];
_hero.animator.playbackSpeed = SEQSPEED[3];
_hero.animator.play(currentAnim, stateTransition);
}
/** Character fight animation */
private function fight2():void {
if (currentAnim == SEQUENCE[4]) return;
currentAnim = SEQUENCE[4];
_hero.animator.playbackSpeed = SEQSPEED[4];
_hero.animator.play(currentAnim, stateTransition);
}
/** Character jump animation */
private function jump():void {
isJumping = false;
}
/** Get animation index in SEQUENCE */
private function getAnim(name:String):int {
var n:int;
for (_i = 0; _i < SEQUENCE.length; _i++)
if (SEQUENCE[_i] == name) n = _i;
return n;
}
/** Character Mouvement */
private function updateMovement(dir:Number):void {
isMoving = true;
var anim:String = isRunning ? 'Run' : 'Walk';
_hero.animator.playbackSpeed = dir * SEQSPEED[getAnim(anim)];
if (currentAnim == anim) return;
currentAnim = anim;
_hero.animator.play(currentAnim, stateTransition);
}
//-------------------------------- KEYBORD
/** Key down listener for player animation */
private function onKeyDown(event:KeyboardEvent):void {
switch (event.keyCode) {
case Keyboard.SHIFT:
isRunning = true;
if (isMoving)
updateMovement(movementDirection);
break;
case Keyboard.UP: case Keyboard.W: case Keyboard.Z: //fr
updateMovement(movementDirection = 1);
break;
case Keyboard.DOWN: case Keyboard.S:
updateMovement(movementDirection = -1);
break;
case Keyboard.LEFT: case Keyboard.A: case Keyboard.Q: //fr
currentRotationInc = -ROTATION_SPEED;
break;
case Keyboard.RIGHT: case Keyboard.D:
currentRotationInc = ROTATION_SPEED;
break;
case Keyboard.E:
fight2();
break;
case Keyboard.SPACE: case Keyboard.R:
fight();
break;
case Keyboard.N:
randomSky();
break;
case Keyboard.B:
// makeClone();
break;
}
}
/** Key up listener */
private function onKeyUp(event:KeyboardEvent):void {
switch (event.keyCode) {
case Keyboard.SHIFT:
isRunning = false;
if (isMoving) updateMovement(movementDirection);
break;
case Keyboard.UP: case Keyboard.W: case Keyboard.Z: //fr
case Keyboard.DOWN: case Keyboard.S: case Keyboard.SPACE:
case Keyboard.E: case Keyboard.R:
rest();
break;
case Keyboard.LEFT: case Keyboard.A: case Keyboard.Q: //fr
case Keyboard.RIGHT: case Keyboard.D:
currentRotationInc = 0;
break;
}
}
//-------------------------------- RESIZE
private function onResize(event:Event = null):void {
_view.width = _stage3DProxy.width = stage.stageWidth;
_view.height = _stage3DProxy.height = stage.stageHeight;
_stats.x = stage.stageWidth - _stats.width;
}
//-------------------------------- NAVIGATION
private function onStageMouseDown(ev:MouseEvent):void {
_prevMouseX = ev.stageX;
_prevMouseY = ev.stageY;
_mouseMove = true;
}
private function onStageMouseLeave(event:Event):void {
_mouseMove = false;
}
private function onStageMouseMove(ev:MouseEvent):void {
if (_mouseMove) {
_hoverCtrl.panAngle += (ev.stageX - _prevMouseX);
_hoverCtrl.tiltAngle += (ev.stageY - _prevMouseY);
}
_prevMouseX = ev.stageX;
_prevMouseY = ev.stageY;
}
private function onStageMouseWheel(ev:MouseEvent):void {
_hoverCtrl.distance -= ev.delta * (5*SCALE)
if (_hoverCtrl.distance < 500*SCALE) {
if (ev.delta > 0)
_cameraHeight += 5*SCALE;
else
_cameraHeight -= 5*SCALE;
}
if (_hoverCtrl.distance < 10*SCALE)
_hoverCtrl.distance = 10*SCALE;
else if (_hoverCtrl.distance > 1000*SCALE)
_hoverCtrl.distance = 1000*SCALE;
}
//-------------------------------- FLASH SIDE
/** Display simple text */
private function initText():void {
_text = new TextField();
_text.defaultTextFormat = new TextFormat("Verdana", 9, 0xAAAAAA);
_text.x=2;
_text.width = 300;
_text.height = 250;
_text.selectable = false;
_text.mouseEnabled = true;
_text.wordWrap = true;
_text.filters = [new DropShadowFilter(1, 45, 0x0, 1, 0, 0)];
addChild(_text);
}
/** final message */
protected function message():void {
_text.htmlText = "<b>Human Theatre</b> beta 0.1\n"
//_text.appendText("Cursor keys / WSAD / ZSQD - move\n");
//_text.appendText("SHIFT - hold down to run\n");
_text.appendText("N - random sky\n");
}
//-------------------------------- LOG DEBUG
/** log for display info */
private final function log(t:String):void {
_text.htmlText = t;
}
//-------------------------------- MATHEMATICS
private static function randomColor():Number {
return 0xFFFFFF * Math.random();
}
private static function rand(max:Number = 1, min:Number = 0):Number {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
private static function orbit(H:Number, V:Number, D:Number, extraY:Number=0):Vector3D {
var p:Vector3D = new Vector3D();
var phi:Number = radToDeg(H);
var theta:Number = radToDeg(V);
p.x = (D * Math.sin(phi) * Math.cos(theta));
p.z = (D * Math.sin(phi) * Math.sin(theta));
p.y = (D * Math.cos(phi))+extraY;
return p;
}
private static function radToDeg(d:Number):Number {
return (d * (Math.PI / 180));
}
}
}
//-------------------------------------o
// FLINT PARTICULE o
//-------------------------------------o
import org.flintparticles.integration.away3d.v4.initializers.A3D4CloneObject;
import org.flintparticles.common.initializers.Lifetime;
import org.flintparticles.threeD.initializers.Position;
import org.flintparticles.threeD.initializers.Velocity;
import org.flintparticles.common.actions.TargetScale;
import org.flintparticles.threeD.actions.RandomDrift;
import org.flintparticles.threeD.emitters.Emitter3D;
import org.flintparticles.threeD.actions.DeathZone;
import org.flintparticles.threeD.actions.Friction;
import org.flintparticles.common.counters.Steady;
import org.flintparticles.threeD.zones.BoxZone;
import org.flintparticles.threeD.actions.Move;
import org.flintparticles.common.actions.Fade;
import org.flintparticles.common.actions.Age;
import away3d.primitives.SphereGeometry;
import away3d.materials.ColorMaterial;
import away3d.entities.Mesh;
import flash.geom.Vector3D;
internal class EmitterSmoke extends Emitter3D
{
public function EmitterSmoke(O:Object = null)
{
counter = new Steady(10);
// test cloning character
// var sphere:Mesh = O.addAvatar({anim:2, speed:1, hair:false})
var sphere:Mesh = new Mesh(new SphereGeometry(10), new ColorMaterial(0xffffff, 0.3));
addInitializer(new Position(new BoxZone(100, 100, 1000, new Vector3D(1000, 0, 0))));
//addInitializer(new Lifetime(10));
addInitializer(new Velocity(new BoxZone(200, 20, 200, new Vector3D( -100, 0, 0))));
var clone:A3D4CloneObject = new A3D4CloneObject( sphere, true, 400 )
addInitializer( clone );
//addAction(new Age());
addAction(new Move());
addAction(new Friction(0.9));
addAction(new Fade(0.7, 1.0));
addAction(new TargetScale(10));
addAction(new RandomDrift(50, 10, 50));
addAction(new DeathZone(new BoxZone(2000, 1000, 2000), true));
}
}
//-------------------------------------o
// VECTOR MAPPER o
//-------------------------------------o
import flash.display.Stage;
import flash.filters.DisplacementMapFilter;
import away3d.textures.BitmapCubeTexture;
import flash.display.DisplayObject;
import flash.filters.ShaderFilter;
import flash.geom.ColorTransform;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Shader;
import flash.display.Sprite;
import flash.geom.Matrix;
import flash.geom.Point;
internal class Mapper extends Sprite {
private var _shaders:Vector.<Shader>;
private var _bitmap:Vector.<Bitmap>;
private var _bitdata:Vector.<BitmapData>;
private var _skydata:Vector.<BitmapData>;
private var _sky:BitmapCubeTexture;
//-------------------------------- REFERENCY
public function get bitdata():Vector.<BitmapData> { return _bitdata; }
public function get sky():BitmapCubeTexture { return _sky; }
//-------------------------------- VECTOR SKY
/** create vector sky */
public function vectorSky(C:Array, quality:uint=8):void {
var xl:uint = 128 * quality;
var pinch:uint = xl / 3.6;
// sky color from bottom to top;
var color:Array = [brighten(C[0], 50), darken(C[0], 25), darken(C[0], 5), darken(C[1], 0), C[1], C[2], darken(C[2], 25), darken(C[2], 50)];
var side:BitmapData = new BitmapData(xl, xl, false, color[1]);
var top:BitmapData = new BitmapData(xl, xl, false, color[6]);
var floor:BitmapData = new BitmapData(xl, xl, false, color[1]);
// side
var matrix:Matrix = new Matrix();
matrix.createGradientBox(xl, xl, -Math.PI / 2)
var g:Sprite = new Sprite();
g.graphics.beginGradientFill('linear', [color[1], color[2], color[3], color[4], color[5], color[6]], [1, 1, 1, 1, 1, 1], [90, 110, 120, 126, 180, 230], matrix);
g.graphics.drawRect(0, 0, xl, xl);
g.graphics.endFill();
var displacement_map:DisplacementMapFilter = new DisplacementMapFilter(pinchMap(xl, xl), new Point(0, 0), 4, 2, 0, pinch, "clamp")
g.filters = [displacement_map];
side.draw(g);
// top
matrix = new Matrix();
g.graphics.clear();
matrix.createGradientBox(xl, xl, 0, 0, 0);
g.graphics.beginGradientFill('radial', [color[7], color[6]], [1, 1], [0, 255], matrix);
g.graphics.drawEllipse(0, 0, xl, xl);
g.graphics.endFill();
top.draw(g);
// bottom
matrix = new Matrix();
matrix.createGradientBox(xl, xl, 0, 0, 0);
g.graphics.clear();
g.graphics.beginGradientFill('radial', [color[0], color[1]], [1, 1], [0, 255], matrix);
g.graphics.drawEllipse(0, 0, xl, xl);
g.graphics.endFill();
floor.draw(g);
_skydata = new Vector.<BitmapData>();
_skydata.push(side, top, floor);
if (_sky) _sky.dispose();
_sky = new BitmapCubeTexture(side, side, top, floor, side, side);
}
/** add some sphericale distortion */
private function pinchMap(w:int, h:int):BitmapData {
var i:int, BCol:Number, GCol:Number;
var b:BitmapData = new BitmapData(w, h, false, 0x000000)
var vx:int = w >> 1, vy:int = h >> 1;
for (var j:int = 0; j < h; j++) {
for ( i = 0; i < w; i++) {
BCol = 127 + (i - vx) / (vx) * 127 * (1 - Math.pow((j - vy) / (vy), 2));
GCol = 127 + (j - vy) / (vy) * 127 * (1 - Math.pow((i - vx) / (vx), 2));
b.setPixel(i, j, (GCol << 8) | BCol);
}
}
return b;
}
//-------------------------------- COLORS UTILS
/** brighten color */
public function brighten(hexColor:Number, percent:Number):Number {
if (isNaN(percent)) percent = 0;
if (percent > 100) percent = 100;
if (percent < 0) percent = 0;
var factor:Number = percent / 100, rgb:Object = hexToRgb(hexColor);
rgb.r += (255 - rgb.r) * factor; rgb.b += (255 - rgb.b) * factor; rgb.g += (255 - rgb.g) * factor;
return rgbToHex(Math.round(rgb.r), Math.round(rgb.g), Math.round(rgb.b));
}
/** darken color */
public function darken(hexColor:Number, percent:Number):Number {
if (isNaN(percent)) percent = 0;
if (percent > 100) percent = 100;
if (percent < 0) percent = 0;
var factor:Number = 1 - (percent / 100), rgb:Object = hexToRgb(hexColor);
rgb.r *= factor; rgb.b *= factor; rgb.g *= factor;
return rgbToHex(Math.round(rgb.r), Math.round(rgb.g), Math.round(rgb.b));
}
/** conversion */
public function rgbToHex(r:Number, g:Number, b:Number):Number { return (r << 16 | g << 8 | b); }
public function hexToRgb(hex:Number):Object { return {r: (hex & 0xff0000) >> 16, g: (hex & 0x00ff00) >> 8, b: hex & 0x0000ff}; }
/** apply color to object */
public function color(o:DisplayObject, c:int=0, a:Number=1):void {
if (!o) return;
var nc:ColorTransform = o.transform.colorTransform;
nc.color = c;
nc.alphaMultiplier = a;
if (c == 0) o.transform.colorTransform = new ColorTransform();
else o.transform.colorTransform = nc;
}
}
//-------------------------------------o
// LOADING BITMAP o
//-------------------------------------o
import flash.display.Sprite;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.system.LoaderContext;
internal class PhotoLoader extends Sprite {
private var loader:Loader;
public var content:BitmapData;
public static const COMPLETE:String = Event.COMPLETE;
public function PhotoLoader() {
loader = new Loader();
}
public function load(file:String):void {
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, complete, false, 0, true);
loader.load(new URLRequest(file), new LoaderContext(true));
}
private function complete(evt:Event):void {
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, complete);
content = Bitmap(loader.contentLoaderInfo.content).bitmapData;
dispatchEvent(new Event(PhotoLoader.COMPLETE));
loader.unload();
loader = null;
}
}