A faster version. Forked from: Alternativa3D 7.5で動くダンボー
Optimisations for simulating larger crowds. Custom bsp tree.
/**
* Copyright Glidias ( http://wonderfl.net/user/Glidias )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/yDKq
*/
// forked from GARENA123's Alternativa3D 7.5で動くダンボー
//【気ままに動くダンボー】
//ダンボーが動きまわります。
//BoxとPlaneの組み合わせで比較的簡単に作れそうなので作ってみました。
//
//ボタン操作でダンボーの増減と、カメラの動きを変更することができます。
//カメラモードをマニュアルにすると、カメラをキーボードとマウスで自由に操作することができます。
//カメラの角度:マウスドラッグ
//カメラ移動:WASDEC or カーソル
/**
* More optimisations. Custom BSP tree for crowd entities, etc.
*/
package {
import alternativ7.engine3d.containers.DistanceSortContainer;
import alternativ7.engine3d.core.Clipping;
import alternativ7.engine3d.core.Debug;
import alternativ7.engine3d.core.Object3D;
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.materials.TextureMaterial;
import flash.display.BitmapData;
import flash.display.StageQuality
import flash.display.Sprite;
import flash.events.Event;
//
//Alternativa3D
import alternativ7.engine3d.containers.*;
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.View;
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.primitives.Plane;
//
//ボタンやラベル
import com.bit101.components.PushButton;
import com.bit101.components.Label;
//
//ステータス表示
import net.hires.debug.Stats;
//
[SWF(width = 465, height = 465, frameRate = 60 , backgroundColor = "#FFF9E5")]
public class DangBoardCrowd extends Sprite {
private static var AREA_W:uint = 3000;
private static var AREA_H:uint = 3000;
private static var FPS:uint = 60;
//ステータス表示
private var stats:Stats;
//ボタン、ラベル
private var btnAdd:PushButton;
private var btnRemove:PushButton;
private var btnCamera:PushButton;
private var labelTotal:Label;
private var labelCamera:Label;
//3D関連
private var container:Object3DContainer; // container for entities
private var kageContainer:Object3DContainer; // container for blob shadows
private var rootContainer:Object3DContainer; // root container for scene
private var camera:Camera3D;
private var cameraMode:int;
private var cameraModeLabels:Vector.<String>;
private var cameraFrame:int = 0;
private var cameraChangeFrame:int = 300;
private var cameraR:Number;
private var cameraSp:Number;
private var controller:SimpleObjectController;
private var plane:Plane;
private var planeMat:TextureMaterial;
private var textures:Textures;
private var danbords:Vector.<Danbord>;
private var kages:Vector.<Object3D>;
private var addState:Boolean = true;
public function DangBoardCrowd():void {
//stage.quality = StageQuality.LOW;
danbords = new Vector.<Danbord>();
kages = new Vector.<Object3D>();
//rootContainer static draw order.
rootContainer = new Object3DContainer();
kageContainer = new Object3DContainer();
container = new DistanceSortContainer();
//カメラ設定
camera = new Camera3D();
cameraModeLabels = new Vector.<String>();
cameraModeLabels[0] = "Auto";
cameraModeLabels[1] = "Rotate 1";
cameraModeLabels[2] = "Rotate 2";
cameraModeLabels[3] = "Target 1";
cameraModeLabels[4] = "Target 2";
cameraModeLabels[5] = "Top";
cameraModeLabels[6] = "Manual";
cameraMode = 0;
cameraR = 0;
cameraFrame = 0;
/*
camera.debug = true;
camera.addToDebug(Debug.EDGES, Object3D);
camera.addToDebug(Debug.BOUNDS, Object3D);
*/
rootContainer.addChild(camera);
camera.view = new View(465, 465, false);
addChild(camera.view);
camera.y = -1000;
camera.z = 300
camera.rotationX = -Math.PI * 0.53;
controller = new SimpleObjectController(stage, camera, 500);
//
//床
planeMat = new TextureMaterial(new BitmapData(8,8,false,0xFF614F3E));
plane = new Plane(AREA_W, AREA_H, 1, 1, false, false, false, planeMat, planeMat);
plane.z = -1
plane.clipping = Clipping.FACE_CLIPPING;
rootContainer.addChild(plane);
// Establish draw order now
rootContainer.addChild(kageContainer);
rootContainer.addChild(container);
//テクスチャ
textures = new Textures();
//ボタン
btnAdd = new PushButton(this, 80, 5, "AddDanbord", addDanbord);
btnRemove = new PushButton(this, 80, 30, "RemoveDanbord", removeDanbord);
labelTotal = new Label(this, 80, 55, "TotalDanbord = " + String(danbords.length));
btnCamera = new PushButton(this, 210, 5, "CameraChange", cameraModeChange);
labelCamera = new Label(this, 210, 30, "CameraMode = " + cameraModeLabels[cameraMode]);
stats = new Stats();
addChild(stats);
//ダンボー追加
for (var i:int = 0; i < 10; i++) {
addDanbord();
}
danbords[0].setupRenderer(camera);
//イベント
addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}
//ダンボー追加
private function addDanbord(_e:Event = null):void {
var mySc:Number = Math.random() * 1 + 0.5;
var myDanbord:Danbord = new Danbord(textures);
myDanbord.x = Math.random() * AREA_W - AREA_W * 0.5;
myDanbord.y = Math.random() * AREA_H - AREA_H * 0.5;
myDanbord.scaleX = myDanbord.scaleY = myDanbord.scaleZ = mySc;
container.addChild(myDanbord)
danbords.push(myDanbord);
var myKage:Kage = new Kage(textures);
myKage.x = myDanbord.x
myKage.y = myDanbord.y
myKage.scaleX = myKage.scaleY = myKage.scaleZ = mySc;
kageContainer.addChild(myKage);
myKage.calculateBounds();
myDanbord.boundMinZ = 0;
myDanbord.boundMaxZ = 290 * mySc;
myDanbord.boundMinX = myKage.boundMinX + mySc*32;
myDanbord.boundMaxX = myKage.boundMaxX - mySc*32;
myDanbord.boundMinY = myKage.boundMinY + mySc*32;
myDanbord.boundMaxY = myKage.boundMaxY - mySc*32;
kages.push(myKage);
//
labelTotal.text = "TotalDanbord = " + String(danbords.length);
}
//ダンボー消去
private function removeDanbord(_e:Event = null):void {
var myNum:int = danbords.length - 1;
if (myNum > 0) {
var myDanbord:Danbord = danbords[myNum];
container.removeChild(myDanbord);
danbords[myNum] = null;
danbords.pop();
var myKage:Object3D = kages[myNum];
kageContainer.removeChild(myKage);
kages[myNum] = null;
kages.pop();
labelTotal.text = "TotalDanbord = " + String(danbords.length);
}
}
//カメラモードの変更
private function cameraModeChange(_e:Event = null):void {
cameraMode++;
cameraR = 0;
cameraFrame = 0;
if (cameraMode >= cameraModeLabels.length) {
cameraMode = 0;
}
if (cameraMode == 6) {
controller.enable();
controller.setObjectPosXYZ(0, -1000, 200);
controller.lookAtXYZ(0, 0, 200);
}else {
controller.disable();
}
labelCamera.text = "CameraMode = " + cameraModeLabels[cameraMode];
}
//毎フレーム実行
private function onEnterFrameHandler(_e:Event):void {
//ダンボーのモーション
var myDanbord:Danbord
var myLength:int = danbords.length;
for (var i:int = 0; i < myLength; i++) {
myDanbord= danbords[i];
//ジャンプしていないときに、一定確率でモーションをランダムに変更
if (Math.random() < 0.01 && myDanbord.ground == true) {
myDanbord.setMotionRandom();
}
//移動
myDanbord.x += Math.sin(-myDanbord.bodyR) * myDanbord.sp;
myDanbord.y += Math.cos(-myDanbord.bodyR) * myDanbord.sp;
//画面端に移動したら反射
if (myDanbord.x < -AREA_W * 0.5) {
myDanbord.x = -AREA_W * 0.5 - (AREA_W * 0.5 + myDanbord.x);
myDanbord.bodyR = Math.PI - myDanbord.bodyR + Math.PI;
}else if (myDanbord.x > AREA_W * 0.5) {
myDanbord.x = AREA_W * 0.5 + (AREA_W * 0.5 - myDanbord.x);
myDanbord.bodyR = Math.PI - myDanbord.bodyR + Math.PI;
}
if (myDanbord.y < -AREA_H * 0.5) {
myDanbord.y = -AREA_H * 0.5 - (AREA_H * 0.5 + myDanbord.y);
myDanbord.bodyR = Math.PI - myDanbord.bodyR;
}else if (myDanbord.y > AREA_H * 0.5) {
myDanbord.y = AREA_H * 0.5 + (AREA_H * 0.5 - myDanbord.y);
myDanbord.bodyR = Math.PI - myDanbord.bodyR;
}
//ジャンプ時の挙動
if (myDanbord.ground == false) {
myDanbord.spZ -= 9.8 / FPS;
myDanbord.z += myDanbord.spZ;
if (myDanbord.z <= 0) {
myDanbord.z = 0;
myDanbord.spZ = 0;
myDanbord.ground = true;
myDanbord.setMotionRandom(false);
}
}
//パーツのモーション
myDanbord.enterFrameEvent();
//影を足元に移動
var myKage:Object3D = kages[i];
myKage.x = myDanbord.x;
myKage.y = myDanbord.y;
}
//
//オートカメラモードの管理
var myCameraMode:int = cameraMode;
if (myCameraMode == 0) {
cameraFrame++;
myCameraMode = Math.floor(cameraFrame / cameraChangeFrame) + 1;
if (myCameraMode >= cameraModeLabels.length - 1) {
cameraFrame = 0;
myCameraMode = 1
}
}
//
//カメラを移動
switch(myCameraMode) {
case 0:
break;
case 1:
//回転1
cameraR += 0.007;
controller.setObjectPosXYZ(Math.cos(cameraR)*1200, Math.sin(cameraR)*1200, 300);
controller.lookAtXYZ(Math.cos(cameraR + Math.PI * 0.6)*700, Math.sin(cameraR + Math.PI * 0.6)*700, 100);
break;
case 2:
//回転2
cameraR += 0.005;
controller.setObjectPosXYZ(Math.cos(cameraR)*1800, Math.sin(cameraR)*1800, 1500);
controller.lookAtXYZ(0, 0, 0);
break;
case 3:
//ターゲット1
myDanbord = danbords[danbords.length - 1];
cameraR += 0.01;
controller.setObjectPosXYZ(Math.cos(cameraR)*600 + myDanbord.x, Math.sin(cameraR)*600 + myDanbord.y, 300);
controller.lookAtXYZ(myDanbord.x, myDanbord.y, myDanbord.z + 200);
break;
case 4:
//ターゲット2
myDanbord = danbords[danbords.length - 1];
var targetR:Number = myDanbord.bodyR + Math.PI * 0.5;
while (targetR > cameraR + Math.PI) {
targetR -= Math.PI * 2;
}
while (targetR < cameraR - Math.PI) {
targetR += Math.PI * 2;
}
cameraR += (targetR - cameraR) * 0.03;
controller.setObjectPosXYZ(Math.cos(cameraR)*400+myDanbord.x, Math.sin(cameraR)*400+myDanbord.y, myDanbord.z + 300);
controller.lookAtXYZ(myDanbord.x, myDanbord.y, myDanbord.z + 200);
break;
case 5:
//トップ
controller.setObjectPosXYZ(0, 0, 3000);
controller.lookAtXYZ(0, 0, 0);
break;
case 6:
//マニュアル
controller.update();
break;
default:
break;
}
camera.render();
}
}
}
//Texture.as
//テクスチャを一括読み込み
//package {
import alternativ7.engine3d.containers.BSPContainer;
import alternativ7.engine3d.containers.ConflictContainer;
import alternativ7.engine3d.containers.KDContainer;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.Canvas;
import alternativ7.engine3d.core.Face;
import alternativ7.engine3d.core.Object3D;
import alternativ7.engine3d.materials.Material;
import alternativ7.engine3d.objects.Mesh;
import alternativ7.engine3d.primitives.Box;
import flash.system.LoaderContext;
import flash.utils.Dictionary;
//
//Alternativa3D
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.loaders.MaterialLoader;
import alternativ7.engine3d.materials.TextureMaterial;
//public
class Textures {
//3D関連
private var loaderContext:LoaderContext;
private var materialLoader:MaterialLoader;
private var textureMats:Vector.<TextureMaterial>;
public var txMatDanboTop:TextureMaterial;
public var txMatDanboBottom:TextureMaterial;
public var txMatDanboFront:TextureMaterial;
public var txMatDanboLeft:TextureMaterial;
public var txMatDanboBack:TextureMaterial;
public var txMatDanboRight:TextureMaterial;
public var txMatDanboFace:TextureMaterial;
public var txMatDanboHeadTop:TextureMaterial;
public var txMatDanboBodyFront:TextureMaterial;
public var txMatKage:TextureMaterial;
public function Textures():void {
//テクスチャの読み込み
txMatDanboTop = new TextureMaterial(); txMatDanboTop.name = "top";
txMatDanboBottom = new TextureMaterial(); txMatDanboBottom.name = "bottom";
txMatDanboFront = new TextureMaterial(); txMatDanboFront.name = "front";
txMatDanboLeft = new TextureMaterial(); txMatDanboLeft.name = "left";
txMatDanboBack = new TextureMaterial(); txMatDanboBack.name = "back";
txMatDanboRight = new TextureMaterial(); txMatDanboRight.name = "right";
txMatDanboFace = new TextureMaterial(); txMatDanboFace.name = "face";
txMatDanboHeadTop = new TextureMaterial(); txMatDanboHeadTop.name = "headTop";
txMatDanboBodyFront = new TextureMaterial(); txMatDanboBodyFront.name = "bodyFront";
txMatKage = new TextureMaterial();
txMatDanboTop.diffuseMapURL = "http://garena.sakura.ne.jp/wonderfl/danbord/danbo_tx_top.png";
txMatDanboBottom.diffuseMapURL = "http://garena.sakura.ne.jp/wonderfl/danbord/danbo_tx_bottom.png";
txMatDanboFront.diffuseMapURL = "http://garena.sakura.ne.jp/wonderfl/danbord/danbo_tx_front.png";
txMatDanboLeft.diffuseMapURL = "http://garena.sakura.ne.jp/wonderfl/danbord/danbo_tx_left.png";
txMatDanboBack.diffuseMapURL = "http://garena.sakura.ne.jp/wonderfl/danbord/danbo_tx_back.png";
txMatDanboRight.diffuseMapURL = "http://garena.sakura.ne.jp/wonderfl/danbord/danbo_tx_right.png";
txMatDanboFace.diffuseMapURL = "http://garena.sakura.ne.jp/wonderfl/danbord/danbo_tx_face.png";
txMatDanboHeadTop.diffuseMapURL = "http://garena.sakura.ne.jp/wonderfl/danbord/danbo_tx_headtop.png";
txMatDanboBodyFront.diffuseMapURL = "http://garena.sakura.ne.jp/wonderfl/danbord/danbo_tx_bodyfront.png";
txMatKage.diffuseMapURL = "http://garena.sakura.ne.jp/wonderfl/danbord/tx_kage.png";
textureMats = new Vector.<TextureMaterial>();
textureMats.push(txMatDanboTop);
textureMats.push(txMatDanboBottom);
textureMats.push(txMatDanboFront);
textureMats.push(txMatDanboLeft);
textureMats.push(txMatDanboBack);
textureMats.push(txMatDanboRight);
textureMats.push(txMatDanboFace);
textureMats.push(txMatDanboHeadTop);
textureMats.push(txMatDanboBodyFront);
textureMats.push(txMatKage);
//
//MaterialLoaderに読み込むテクスチャのリストを投げて、読み込み開始
loaderContext = new LoaderContext(true);
materialLoader = new MaterialLoader();
materialLoader.load(textureMats, loaderContext);
}
}
//}
//Danbord.as
//ダンボーの生成とモーション
//package {
//Alternativa3D
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.materials.TextureMaterial;
import alternativ7.engine3d.primitives.Box;
import alternativ7.engine3d.primitives.Plane;
import alternativ7.engine3d.alternativa3d;
use namespace alternativa3d;
//public
class Danbord extends Object3D {
private static var AREA_W:uint = 4000;
private static var AREA_H:uint = 4000;
private static var FPS:uint = 60;
//3D関連
private var boxHead:Box;
private var boxBody:Box;
private var boxSldL:Box;
private var boxSldR:Box;
private var boxArmL:Box;
private var boxArmR:Box;
private var boxKneL:Box;
private var boxKneR:Box;
private var boxLegL:Box;
private var boxLegR:Box;
private var planeSktL:Plane;
private var planeSktR:Plane;
private var planeSktF:Plane;
private var planeSktB:Plane;
private var danHead:Object3DContainer;
private var danBody:Object3D;
private var danSldL:Object3D;
private var danSldR:Object3D;
private var danArmL:Object3D;
private var danArmR:Object3D;
private var danKneL:Object3D;
private var danKneR:Object3D;
private var danLegL:Object3D;
private var danLegR:Object3D;
private var danSktL:Object3D;
private var danSktR:Object3D;
private var danSktF:Object3D;
private var danSktB:Object3D;
private var motionR:Number = 0;
private var motionType:String = "stand";
private var motionTypes:Vector.<String>;
//
private var textures:Textures;
public var bodyR:Number = 0;
public var sp:Number = 0;
public var spZ:Number = 0;
public var ground:Boolean = true;
private var brushes:Vector.<Object3D>;
private static var RENDERER:BSPTreeRendererI;
// Must call this method once to setup renderer!
public function setupRenderer(camera:Camera3D):void {
RENDERER = new BSPTreeRendererI(camera, new BSPXMLNode(getBSPXML(), this, brushes) );
}
override alternativa3d function draw(camera:Camera3D, parentCanvas:Canvas):void {
calculateInverseMatrix();
danBody.composeAndAppend(this);
boxBody.composeAndAppend(danBody); boxBody.calculateInverseMatrix();
danHead.composeAndAppend(danBody);
boxHead.composeAndAppend(danHead); boxHead.calculateInverseMatrix();
danSldL.composeAndAppend(danBody);
boxSldL.composeAndAppend(danSldL); boxSldL.calculateInverseMatrix();
danArmL.composeAndAppend(danSldL);
boxArmL.composeAndAppend(danArmL); boxArmL.calculateInverseMatrix();
danSldR.composeAndAppend(danBody);
boxSldR.composeAndAppend(danSldR); boxSldR.calculateInverseMatrix();
danArmR.composeAndAppend(danSldR);
boxArmR.composeAndAppend(danArmR); boxArmR.calculateInverseMatrix();
danKneL.composeAndAppend(danBody);
boxKneL.composeAndAppend(danKneL); boxKneL.calculateInverseMatrix();
danLegL.composeAndAppend(danKneL);
boxLegL.composeAndAppend(danLegL); boxLegL.calculateInverseMatrix();
danKneR.composeAndAppend(danBody);
boxKneR.composeAndAppend(danKneR); boxKneR.calculateInverseMatrix();
danLegR.composeAndAppend(danKneR);
boxLegR.composeAndAppend(danLegR); boxLegR.calculateInverseMatrix();
danSktL.composeAndAppend(danBody);
planeSktL.composeAndAppend(danSktL); planeSktL.calculateInverseMatrix();
danSktR.composeAndAppend(danBody);
planeSktR.composeAndAppend(danSktR); planeSktR.calculateInverseMatrix();
danSktF.composeAndAppend(danBody);
planeSktF.composeAndAppend(danSktF); planeSktF.calculateInverseMatrix();
danSktB.composeAndAppend(danBody);
planeSktB.composeAndAppend(danSktB); planeSktB.calculateInverseMatrix();
RENDERER.draw(parentCanvas, brushes);
}
public function getBSPXML():XML {
boxHead._parent = danHead;
return <bsp>
<back>{_(boxHead)}</back>
<front>
<front>
<front>{_(planeSktL)}</front>
<back>
<back>{_(boxSldL)}</back>
<front>{_(boxArmL)}</front>
{planeOf(boxSldL, "bottom")}
</back>
{planeOf(planeSktL, "bottom")}
</front>
<back>
<front>
<front>{_(planeSktR)}</front>
<back>
<back>{_(boxSldR)}</back>
<front>{_(boxArmR)}</front>
{planeOf(boxSldR, "bottom")}
</back>
{planeOf(planeSktR, "bottom")}
</front>
<back>
<front>{_(planeSktF)}</front>
<back>
<front>{_(planeSktB)}</front>
<back>
<front>
<front>{_(boxLegL)}</front>
<back>{_(boxLegR)}</back>
{planeOf(boxLegR, "left")}
</front>
<back>{_(boxBody)}</back>
{planeOf(boxBody, "bottom")}
</back>
{planeOf(boxBody, "back")}
</back>
{planeOf(boxBody, "bodyFront")}
</back>
{planeOf(boxBody, "right")}
</back>
{planeOf(boxBody, "left")}
</front>
{planeOf(boxHead, "bottom")}
</bsp>
}
/**
* Gets face from mesh using material id
* @param mesh
* @param matId
* @return
*/
private static function getFaceOf(mesh:Mesh, matId:String):Face {
var face:Face = mesh.faceList;
while ( face) {
if (face.material && face.material.name === matId) {
return face;
}
face = face.next;
}
throw new Error("could not find face by matId:"+matId);
return null;
}
public function planeOf(mesh:Mesh, matId:String, animated:Boolean=true):XML {
var face:Face = getFaceOf(mesh, matId);
return <plane animated={animated}>
<nx>{face.normalX}</nx>
<ny>{face.normalY}</ny>
<nz>{face.normalZ}</nz>
<offset>{face.offset}</offset>
<brush>{brushes.indexOf(mesh)}</brush>
</plane>;
}
/**
* Gets brush index of brush for bsp xml node
* @param searchBrush
* @return The brush index xml node
*/
private function _(searchBrush:Object3D):XML {
return <brush>{brushes.indexOf(searchBrush)}</brush>;
}
//ダンボー
public function Danbord(_textures:Textures):void {
textures = _textures;
//
//パーツを埋め込むコンテナの作成(回転軸を中心以外の場所にしたいためコンテナに埋め込んでます)
// 14 dans
danHead = new Object3DContainer();
danBody = new Object3D();
danSldL = new Object3D();
danSldR = new Object3D() ;
danArmL = new Object3D();
danArmR = new Object3D();
danKneL = new Object3D();
danKneR = new Object3D();
danLegL = new Object3D();
danLegR = new Object3D() ;
danSktL = new Object3D();
danSktR = new Object3D();
danSktF = new Object3D();
danSktB = new Object3D();
/*
danBody:体
-danHead:頭
-danSldL:左肩
--danArmL:左腕
-danSldR:右肩
--danArmR:右腕
-boxKneL:左膝
--boxLegL:左足
-boxKneR:右膝
--boxLegR:右足
-danSktL:スカート右
-danSktR:スカート左
-danSktF:スカート前
-danSktB:スカート後
*/
boundMinX = 0;
boundMaxX = 0;
boundMinY = 0;
boundMaxY = 0;
boundMinZ = 0;
boundMaxZ = 0;
// 10 box
//パーツを作成
boxBody = new Box(76, 60, 102, 1, 1, 1, false, false, textures.txMatDanboLeft, textures.txMatDanboRight, textures.txMatDanboBack, textures.txMatDanboBodyFront, textures.txMatDanboBottom, textures.txMatDanboTop);
boxHead = new Box(160, 102, 102, 1, 1, 1, false, false, textures.txMatDanboLeft, textures.txMatDanboRight, textures.txMatDanboBack, textures.txMatDanboFace, textures.txMatDanboBottom, textures.txMatDanboHeadTop);
boxSldL = new Box(20, 20, 20, 1, 1, 1, false, false, textures.txMatDanboLeft, textures.txMatDanboRight, textures.txMatDanboBack, textures.txMatDanboFront, textures.txMatDanboBottom, textures.txMatDanboTop);
boxSldR = new Box(20, 20, 20, 1, 1, 1, false, false, textures.txMatDanboLeft, textures.txMatDanboRight, textures.txMatDanboBack, textures.txMatDanboFront, textures.txMatDanboBottom, textures.txMatDanboTop);
boxArmL = new Box(106, 26, 26, 1, 1, 1, false, false, textures.txMatDanboLeft, textures.txMatDanboRight, textures.txMatDanboBack, textures.txMatDanboFront, textures.txMatDanboBottom, textures.txMatDanboTop);
boxArmR = new Box(106, 26, 26, 1, 1, 1, false, false, textures.txMatDanboLeft, textures.txMatDanboRight, textures.txMatDanboBack, textures.txMatDanboFront, textures.txMatDanboBottom, textures.txMatDanboTop);
boxKneL = new Box(20, 20, 20, 1, 1, 1, false, false, textures.txMatDanboBottom, textures.txMatDanboBottom, textures.txMatDanboBottom, textures.txMatDanboBottom, textures.txMatDanboBottom, textures.txMatDanboTop);
boxKneR = new Box(20, 20, 20, 1, 1, 1, false, false, textures.txMatDanboBottom, textures.txMatDanboBottom, textures.txMatDanboBottom, textures.txMatDanboBottom, textures.txMatDanboBottom, textures.txMatDanboTop);
boxLegL = new Box(30, 56, 66, 1, 1, 1, false, false, textures.txMatDanboLeft, textures.txMatDanboRight, textures.txMatDanboBack, textures.txMatDanboFront, textures.txMatDanboBottom, textures.txMatDanboTop);
boxLegR = new Box(30, 56, 66, 1, 1, 1, false, false, textures.txMatDanboLeft, textures.txMatDanboRight, textures.txMatDanboBack, textures.txMatDanboFront, textures.txMatDanboBottom, textures.txMatDanboTop);
// 4 plane
planeSktL = new Plane(60, 30, 1, 1, true, false, false, textures.txMatDanboLeft, textures.txMatDanboBottom);
planeSktR = new Plane(60, 30, 1, 1, true, false, false, textures.txMatDanboRight, textures.txMatDanboBottom);
planeSktF = new Plane(76, 30, 1, 1, true, false, false, textures.txMatDanboFront, textures.txMatDanboBottom);
planeSktB = new Plane(76, 30, 1, 1, true, false, false, textures.txMatDanboBack, textures.txMatDanboBottom);
//ステージに追加(パーツごとに親子関係になっています)
brushes = new Vector.<Object3D>(14, true);
brushes[0] = boxBody; boxBody.sorting = 0;
brushes[1] = boxHead; boxHead.sorting = 0;
brushes[2] = boxSldL; boxSldL.sorting = 0;
brushes[3] = boxSldR; boxSldR.sorting = 0;
brushes[4] = boxArmL; boxArmL.sorting = 0;
brushes[5] = boxArmR; boxArmR.sorting = 0;
brushes[6] = boxKneL; boxKneL.sorting = 0;
brushes[7] = boxKneR; boxKneR.sorting = 0;
brushes[8] = boxLegL; boxLegL.sorting = 0;
brushes[9] = boxLegR; boxLegR.sorting = 0;
brushes[10] = planeSktL; planeSktL.sorting = 0;
brushes[11] = planeSktR; planeSktR.sorting = 0;
brushes[12] = planeSktF; planeSktF.sorting = 0;
brushes[13] = planeSktB; planeSktB.sorting = 0;
//座標・角度設定
boxBody.z = 137
boxHead.z = 51;
boxArmL.x = -63;
boxArmR.x = 63;
boxLegL.z = -38;
boxLegR.z = -38;
danArmL.rotationY = -1.3;
danArmR.rotationY = 1.3;
planeSktL.rotationX = Math.PI * 0.5;
planeSktL.rotationZ = Math.PI * 0.5;
planeSktL.z = -15;
planeSktR.rotationX = Math.PI * 0.5;
planeSktR.rotationZ = Math.PI * -0.5;
planeSktR.z = -15
planeSktF.rotationX = Math.PI * 0.5;
planeSktF.rotationZ = Math.PI * 0;
planeSktF.z = -15
planeSktB.rotationX = Math.PI * 0.5;
planeSktB.rotationZ = Math.PI * 1;
planeSktB.z = -15
danBody.z = 0;
danHead.z = 188;
danSldL.x = -48;
danSldL.z = 178;
danSldR.x = 48;
danSldR.z = 178;
danKneL.x = -17;
danKneL.z = 76;
danKneR.x = 17;
danKneR.z = 76;
danSktL.x = -38;
danSktL.z = 86;
danSktL.rotationY = 0.5;
danSktR.x = 38;
danSktR.z = 86;
danSktR.rotationY = -0.5;
danSktF.y = 30;
danSktF.z = 86;
danSktF.rotationX = 0.5;
danSktB.y = -30;
danSktB.z = 86;
danSktB.rotationX = -0.5;
//
motionTypes = new Vector.<String>();
motionTypes[0] = "stand";
motionTypes[1] = "walk";
motionTypes[2] = "dash";
motionTypes[3] = "jump";
bodyR = Math.random() * Math.PI * 2;
danBody.rotationZ = bodyR;
//setMotionRandom();
}
//モーションを設定
public function setMotion(_motion:String):void {
if(motionType != _motion){
motionType = _motion;
motionR = 0;
danBody.rotationX = 0;
danBody.rotationY = 0;
switch(_motion) {
case "stand":
sp = 0;
break;
case "walk":
bodyR = Math.random() * Math.PI * 2;
danBody.rotationZ = bodyR
sp = (2 + Math.random() * 2) * scaleX;
break;
case "dash":
bodyR = Math.random() * Math.PI * 2;
danBody.rotationZ = bodyR
sp = (6 + Math.random() * 4) * scaleX;
break;
case "jump":
spZ = (8 + Math.random() * 8) * scaleX;
ground = false;
break;
default :
break;
}
}
}
//ランダムにモーションを設定(ジャンプの有無)
public function setMotionRandom(_jump:Boolean = true):void {
if (_jump) {
setMotion(motionTypes[Math.floor(Math.random() * motionTypes.length)])
}else {
setMotion(motionTypes[Math.floor(Math.random() * (motionTypes.length - 1))])
}
}
//モーション
public function enterFrameEvent() :void{
danBody.rotationZ = bodyR;
switch(motionType) {
case "stand":
motionR += 0.03;
danBody.y = 0;
danBody.z = 0;
danHead.rotationX = Math.sin(-motionR) * 0.04;
danArmL.rotationY = Math.sin(-motionR) * 0.1 + -1.3;
danArmR.rotationY = Math.sin(motionR) * 0.1 + 1.3;
danSldL.rotationX = 0;
danSldR.rotationX = 0;
danLegL.rotationX = 0;
danLegR.rotationX = 0;
danKneL.rotationY = 0;
danKneR.rotationY = 0;
break;
case "walk":
motionR += 0.1;
danBody.z = Math.sin(motionR * 2) * 3 + 3;
danHead.rotationX = Math.cos(motionR*2) * 0.03;
danArmL.rotationY = -1.3;
danArmR.rotationY = 1.3;
danSldL.rotationX = Math.sin(-motionR) * 0.3;
danSldR.rotationX = Math.sin(motionR) * 0.3;
danLegL.rotationX = Math.sin(motionR) * 0.4;
danLegR.rotationX = Math.sin( -motionR) * 0.4;
danKneL.rotationY = 0;
danKneR.rotationY = 0;
break;
case "dash":
motionR += 0.23;
danBody.z = Math.sin(motionR * 2) * 8 + 8;
danHead.rotationX = Math.cos(motionR*2) * 0.05;
danArmL.rotationY = -1.3;
danArmR.rotationY = 1.3;
danSldL.rotationX = Math.sin(-motionR) * 0.6;
danSldR.rotationX = Math.sin(motionR) * 0.6;
danLegL.rotationX = Math.sin(motionR) * 0.6;
danLegR.rotationX = Math.sin( -motionR) * 0.6;
danKneL.rotationY = 0;
danKneR.rotationY = 0;
break;
case "jump":
motionR += 0.23;
danBody.z = 0;
danHead.rotationX = Math.max(Math.min(spZ * 0.1, 0.8), -0.5);
danArmL.rotationY = -Math.max(Math.min(spZ * 0.2, 1.4), -0.2);
danArmR.rotationY = Math.max(Math.min(spZ * 0.2, 1.4), -0.2);
danSldL.rotationX = 0;
danSldR.rotationX = 0;
danKneL.rotationY = -Math.max(Math.min(spZ * 0.2, 0), -0.2);
danKneR.rotationY = Math.max(Math.min(spZ * 0.2, 0), -0.2);
danLegL.rotationX = 0;
danLegR.rotationX = 0;
break;
default :
break;
}
}
}
//}
//Kage.as
//影
//package {
//Alternativa3D
import alternativ7.engine3d.primitives.Plane;
//public
class Kage extends Plane {
public function Kage(textures:Textures):void {
super(200, 200, 1, 1, true, false, false, textures.txMatKage, textures.txMatKage);
}
}
//}
//package bsp
//{
/**
* Generic cross-platform BSP node construct for any engine
* @author Glenn Ko
*/
//public
class BSPNode
{
public var front:BSPNode;
public var back:BSPNode;
public var brushIndex:int = -1;
public var normalX:Number;
public var normalY:Number;
public var normalZ:Number;
public var offset:Number;
public function BSPNode()
{
}
/** Recursively counts the number of nodes in this tree (including this). */
public function size():int
{
var c:int = 1;
if (front) {
// assumption made both available
c += front.size();
c += back.size();
}
return c;
}
}
//}
//package bsp
//{
import alternativ7.engine3d.core.Object3D;
import alternativ7.engine3d.alternativa3d;
import alternativ7.engine3d.core.Object3DContainer;
use namespace alternativa3d;
/**
* Custom xml parsing construct of BSPNode for Alternativa3D on animatable brush-based entities
* @author Glenn Ko
*/
//public
class BSPXMLNode extends BSPNode
{
public function BSPXMLNode(xml:XML, rootBrush:Object3D, brushContext:Vector.<Object3D>)
{
var planeXML:XML;
// Node validation
//#if debug
///*
if ( xml.hasOwnProperty("front") || xml.hasOwnProperty("back") ) {
if (!(xml.hasOwnProperty("front") && xml.hasOwnProperty("back"))) {
throw new Error("Do not have both front and back!");
}
planeXML = xml.hasOwnProperty("plane") ? xml.plane[0] : null;
if (planeXML == null) throw new Error("Could not find split plane node <plane>!");
if ( !planeXML.hasOwnProperty("nx") || !planeXML.hasOwnProperty("ny") || !planeXML.hasOwnProperty("nz") || !planeXML.hasOwnProperty("offset") ) {
throw new Error("Do not have valid plane variables!");
}
}
else if (!xml.hasOwnProperty("brush")) {
throw new Error("No leaf node brush reference found!!");
}
//*/
//#end
if (xml.hasOwnProperty("front")) {
planeXML = xml.plane[0];
normalX = Number(planeXML.nx[0]);
normalY = Number(planeXML.ny[0]);
normalZ = Number(planeXML.nz[0]);
offset = Number(planeXML.offset[0]);
brushIndex = planeXML.hasOwnProperty("brush") ? int(planeXML.brush[0]) : -1;
front = new BSPXMLNode(xml.front[0], rootBrush, brushContext);
back = new BSPXMLNode(xml.back[0], rootBrush, brushContext);
}
else {
brushIndex = int(xml.brush[0]);
}
}
}
//}
//package bsp
//{
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.Canvas;
import alternativ7.engine3d.core.Object3D;
import alternativ7.engine3d.alternativa3d;
use namespace alternativa3d;
/**
* @author Glenn Ko
*/
//public
class BSPTreeRendererI
{
public var rootNode:BSPNode;
public var camera:Camera3D;
private var stack:Vector.<BSPNode>;
private var stackResults:Vector.<BSPNode>;
/**
*
* @param camera The camera for rendering
* @param rootNode Reference bsp model node to use for rendering.
*/
public function BSPTreeRendererI(camera:Camera3D, rootNode:BSPNode )
{
this.camera = camera;
this.rootNode = rootNode;
stack = new Vector.<BSPNode>( rootNode.size(), true );
stackResults = new Vector.<BSPNode>( stack.length, true );
}
/**
* Draw brushes onto canvas through iterative bsp traversal
* @param canvas The canvas being
* @param rootBrush Usually the entity being drawn // rootBrush:Object3D,
* @param brushContext Any related brushes for the entity to be drawn/referenced
* for split-planes/leafs.
*/
public function draw(canvas:Canvas, brushContext:Vector.<Object3D>):void {
// drawing vars
var brush:Object3D;
// node vars
var node:BSPNode;
var top:int = 0;
var prev:BSPNode;
var prevResult:BSPNode;
stack[top++] = rootNode;
while (top != 0) {
node = stack[top - 1];
if (!node.front) { // No more children, so spit leaf out for drawing
top--;
// todo: inline drawing of faces if rootNode is BSPNodeNiva
brush = brushContext[node.brushIndex];
if (brush.cullingInCamera(camera, 63) >= 0) brush.draw(camera, canvas);
prev = node;
continue;
}
// got children to recurse into
if (!prev || prev.front === node || prev.back === node) { // if curr node is child of previous
//brush = node.brushIndex >= 0 ? brushContext[node.brushIndex] : rootBrush;
brush = brushContext[node.brushIndex];
stackResults[top - 1] = prevResult = brush.imd * node.normalX + brush.imh * node.normalY + brush.iml * node.normalZ > node.offset ? node.front : node.back;
stack[top++] = prevResult;
prev = node;
continue;
}
else if ( (prevResult = stackResults[top - 1]) === prev ) { // if curr node's initial result was the previous, recurse other side as well
stack[top++] = prevResult === node.back ? node.front : node.back;
prev = node;
continue;
}
top--;
prev = node;
}
}
}
//}