forked from: wonderflで音楽♪カニテーマ from:蟹さん from:from:なんとかディウス
Trying to convert Nemesis 1D/2D to 2D/3D, but how to prevent limping spider leg gears (both legs moving up together at the same time, like hopping) since there's no longer an actual linear "moving left/right" timeline?
Click on plane to move spider to direction.
/**
* Copyright Glidias ( http://wonderfl.net/user/Glidias )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/vSUw
*/
// forked from keim_at_Si's wonderflで音楽♪カニテーマ from:蟹さん from:from:なんとかディウス
// forked from nemu90kWw's なんとかディウスっぽい蟹さん forked from: なんとかディウスっぽい背景
// forked from gyuque's なんとかディウスっぽい背景
// 左右キーとスペースで操作できます
package
{
import alternativ7.engine3d.containers.ConflictContainer;
import alternativ7.engine3d.core.MouseEvent3D;
import alternativ7.engine3d.core.Object3D;
import alternativ7.engine3d.core.RayIntersectionData;
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.primitives.Plane;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Vector3D;
/**
* How to avoid limping spider when converting 1D/2D Nemesis to 2D/3D???
* @author Glidias
*/
public class Nemesis3D extends Sprite
{
private var kani:Kani3D;
private var conflict:ConflictContainer;
private var template:AlternativaTemplate;
public function Nemesis3D()
{
super( );
template = new AlternativaTemplate(this, "none", stage.stageWidth, stage.stageHeight, true);
addChild(template);
template.onPreRender = preRenderUpdate;
var plane:Plane = new Plane(4000, 4000, 1,1,false);
template.container.addChild(plane);
plane.clipping = 2;
plane.setMaterialToAllFaces( new FillMaterial(0xCCCCCC) );
plane.addEventListener(MouseEvent3D.CLICK, onEnvClick);
conflict = new ConflictContainer();
var legs:Vector.<Leg> = new <Leg>[
new Leg( new Vector3D( 0, -80), -1 ),
new Leg( new Vector3D(-80, 0), -1 ),
new Leg( new Vector3D(80, 0), -1 ),
new Leg( new Vector3D(0, 80), -1 )
];
kani = new Kani3D( legs
);
conflict.addChild(kani);
template.camera.z = 1000;
template.camera.y = -1000;
template.camera.rotationX = -.7 * Math.PI;
template.cameraController.updateObjectTransform();
for each( var leg:Leg in legs) {
conflict.addChild(leg.sprite);
}
template.container.addChild(conflict);
template.startRendering();
}
private function onEnvClick(e:MouseEvent3D):void
{
var data:RayIntersectionData = (e.target as Object3D).intersectRay(e.localOrigin, e.localDirection);
if (data != null) {
kani.setTargetLocation(data.point.x, data.point.y);
}
}
protected function preRenderUpdate():void
{
kani.update();
}
}
}
import alternativ7.engine3d.containers.BSPContainer;
import alternativ7.engine3d.containers.ConflictContainer;
import alternativ7.engine3d.containers.DistanceSortContainer;
import alternativ7.engine3d.containers.KDContainer;
import alternativ7.engine3d.containers.LODContainer;
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.Object3D;
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.core.View;
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.objects.Mesh;
import alternativ7.engine3d.primitives.Box;
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Vector3D;
class Kani3D extends Object3DContainer {
private var body:Body3D;
public var direction:Vector3D = new Vector3D();
public var tarLocation:Vector3D = new Vector3D();
public var tarDisplacement:Vector3D = new Vector3D();
public var legs:Vector.<Leg>;
public var auto:Boolean;
public var dir:String = "none";
public var timer:int;
public var dance:int;
public var speed:Number = 3;
public var offset:Number;
public function Kani3D(legs:Vector.<Leg>) {
this.legs = legs;
auto = false;
timer = 100;
x = 200;
z = 120;
for each(var leg:Leg in legs)
{
leg.parent = this;
leg.sprite.x = x + leg.offsetPos.x - 20 + Math.random() * 40;
leg.sprite.y = y+leg.offsetPos.y - 20+Math.random()*40;
leg.sprite.z = 120 + 100*leg.invert;
}
addChild ( body = new Body3D() );
}
public function setTargetLocation(xer:Number, yer:Number):void {
//yer = 0; // test along x axis only
tarLocation.x = xer;
tarLocation.y = yer;
tarDisplacement.x = (xer - x);
tarDisplacement.y = (yer - y);
direction.x = xer -x ;
direction.y = yer- y;
direction.normalize();
direction.w = direction.x * x + direction.y * y + direction.z * z;
}
public function update():void
{
var leg:Leg;
// move to target location if needed and update legs
// /*
if ( tarDisplacement.lengthSquared < 2 ) {
return;
}
// */
offset = x * direction.x + y * direction.y;
x += speed * direction.x;
y += speed * direction.y;
for each( leg in legs) {
leg.move();
leg.hitflag = leg.sprite.z <= 4;
}
}
}
class Body3D extends Box // ie. more like the "brain" head actually
{
public function Body3D() {
super( 20, 20, 20);
setMaterialToAllFaces( new FillMaterial(0xFFFF00, 1) );
}
}
class Leg
{
public var parent:Kani3D;
public var sprite:Object3D;
public var x:Number;
public var y:Number;
public var offsetPos:Vector3D;
private var returnVector:Vector3D = new Vector3D();
public var invert:int;
public var hitflag:Boolean;
public var moveflag:Boolean = true;
public var gear:int = 0;
private static const UP:Vector3D = new Vector3D(0, 0, 1);
function Leg(offsetPos:Vector3D, invert:int) // todo: offset hsould be an offset vector
{
this.offsetPos = offsetPos;
this.invert = invert;
sprite = new Box(8, 8, 8); // todo, form leg
(sprite as Mesh).setMaterialToAllFaces(new FillMaterial(0xFF0000));
}
public function move():void
{
var right:Vector3D = parent.direction.crossProduct(UP);
var offset:Number; var scaler:Number
returnVector.x = offsetPos.x - (sprite.x - parent.x);
returnVector.y = offsetPos.y - (sprite.y - parent.y);
// remove component along direction of movement
offset = returnVector.x * parent.direction.x + returnVector.y * parent.direction.y;
returnVector.x -= offset * parent.direction.x;
returnVector.y -= offset * parent.direction.y;
offset = offsetPos.x * parent.direction.x + offsetPos.y * parent.direction.y;
x = parent.direction.x * sprite.x + parent.direction.y * sprite.y;
y = sprite.z;
var totalOffset:Number = (parent.x + offsetPos.x) * parent.direction.x + (parent.y + offsetPos.y) * parent.direction.y;
var threshold_l:Number =totalOffset + 30;
var threshold_r:Number = totalOffset - 30;
if(!moveflag) {
if(threshold_l < x || threshold_r > x)
{
moveflag = true; // using a random offset hack will prevent hopping legs, but i don't think this may be the right way to go about it??
gear = -12; // + Math.random()*6
}
if(threshold_r > x)
{
moveflag = true;
gear = 12; // - Math.random()*6
}
}
if(moveflag)
{
if (threshold_r+50 > x) // if moving "right"
{
x += 4;
if(gear > 0) {
y -= 4 * invert;
}
else {
y += 4 * invert;
if(hitflag) {
moveflag = false;
}
if(y < 0 || y > 240) { //
gear = 12;
}
}
gear--;
returnVector.scaleBy(.6);
// Map back to 3D
scaler = right.dotProduct( new Vector3D(sprite.x, sprite.y).add(returnVector) );
sprite.x = scaler * right.x;
sprite.y = scaler * right.y;
sprite.x += parent.direction.x * x;
sprite.y += parent.direction.y * x;
sprite.z = y;
}
/*
else if ( threshold_l-50 < x) // if moving "left"
{
x -= 4; // move regardless?
if(gear < 0) {
y -= 4 * invert;
}
else {
y += 4 * invert;
if(hitflag == true) {
moveflag = false;
}
if(y < 0 || y > 240) {
gear = -12;
}
}
gear++;
returnVector.scaleBy(.6);
// Map back to 3D
scaler = right.dotProduct( new Vector3D(sprite.x, sprite.y).add(returnVector) );
sprite.x = scaler * right.x;
sprite.y = scaler * right.y;
sprite.x += parent.direction.x * x;
sprite.y += parent.direction.y * x;
sprite.z = y;
}
*/
}
}
}
class AlternativaTemplate extends Sprite
{
//----------------------------------------------------------
//
// Static Property
//
//----------------------------------------------------------
/**
* 子オブジェクトを最適な方法でソートするコンテナ
* (ConflictContainer)
*/
public static const CONFLICT:String = 'conflict';
/**
* 子オブジェクトをBSP(バイナリ空間分割法)によってソートするコンテナ
* (BSPContainer)
*/
public static const BSP:String = 'bsp';
/**
* 子オブジェクトをカメラからのZ値でソートするコンテナ
* (DistanceSortContainer)
*/
public static const ZSORT:String = 'zsort';
/**
* KDツリー(http://ja.wikipedia.org/wiki/Kd%E6%9C%A8)によってソートするコンテナ
* (KDContainer)
*/
public static const KD:String = 'kd';
/**
* detalizationと子オブジェクトの距離でソートするコンテナ(詳細は調査中)
* (LODContainer)
*/
public static const LOD:String = 'lod';
//----------------------------------------------------------
//
// Constructor
//
//----------------------------------------------------------
/**
* 新しい Alternativa3DTemplate インスタンスを作成します。
* @param mc
* @param containerType
* @param viewWidth
* @param viewHeight
* @param scaleToStage
*/
public function AlternativaTemplate(mc:DisplayObjectContainer, containerType:String = CONFLICT, viewWidth:int = 640, viewHeight:int = 480, scaleToStage:Boolean = true)
{
_mc = mc
_mc.addChild(this)
_containerType = containerType
_viewWidth = viewWidth;
_viewHeight = viewHeight;
_scaleToStage = scaleToStage;
if (stage)
init();
else
addEventListener(Event.ADDED_TO_STAGE, init);
}
//----------------------------------------------------------
//
// Property
//
//----------------------------------------------------------
/**
* カメラインスタンスです。
*/
public var camera:Camera3D;
/**
* カメラコントローラーです。
*/
public var cameraController:SimpleObjectController
/**
* 3dオブジェクト格納するコンテナインスタンス。
*/
public var container:Object3DContainer;
//--------------------------------------
// onPostRender
//--------------------------------------
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング後に実行したい処理を記述します。
*/
private var _onPostRender:Function = function():void{};
public function get onPostRender():Function
{
return _onPostRender;
}
public function set onPostRender(value:Function):void
{
_onPostRender = value;
}
//--------------------------------------
// onPreRender
//--------------------------------------
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング前に実行したい処理をオーバーライドして記述します。
*/
private var _onPreRender:Function = function():void{};
public function get onPreRender():Function
{
return _onPreRender;
}
public function set onPreRender(value:Function):void
{
_onPreRender = value;
}
/**
* ビューインスタンスです。
*/
public var view:View
private var _containerType:String
private var _mc:DisplayObjectContainer
private var _scaleToStage:Boolean;
private var _viewHeight:int;
private var _viewWidth:int;
//----------------------------------------------------------
//
// Function
//
//----------------------------------------------------------
/**
* レンダリングを開始します。
*/
public function startRendering():void
{
addEventListener(Event.ENTER_FRAME, onRenderTick);
}
/**
* レンダリングを停止します。
*/
public function stopRendering():void
{
removeEventListener(Event.ENTER_FRAME, onRenderTick);
}
/**
* シングルレンダリング(レンダリングを一回だけ)を実行します。
*/
public function singleRender():void
{
onRenderTick();
}
/**
* 初期化されたときに実行されるイベントです。
* 初期化時に実行したい処理をオーバーライドして記述します。
*/
protected function atInit():void
{
}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング前に実行したい処理をオーバーライドして記述します。
*/
protected function atPreRender():void
{
}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング後に実行したい処理をオーバーライドして記述します。
*/
protected function atPostRender():void
{
}
/**
* @private
*/
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.HIGH;
//Root objectの作成
if (_containerType == CONFLICT)
{
container = new ConflictContainer();
}
else if (_containerType == BSP)
{
container = new BSPContainer();
}
else if (_containerType == ZSORT)
{
container = new DistanceSortContainer();
}
else if (_containerType == KD)
{
container = new KDContainer();
}
else if (_containerType == LOD)
{
container = new LODContainer();
}
else {
container = new Object3DContainer();
}
//Viewの作成
view = new View(stage.stageWidth, stage.stageHeight);
_mc.addChild(view);
//cameraの作成
camera = new Camera3D();
camera.view = view;
camera.x = 0;
camera.y = -500;
camera.z = 0;
container.addChild(camera);
// Camera controller
cameraController = new SimpleObjectController(stage, camera, 400);
// cameraController.mouseSensitivity = 0
// cameraController.unbindAll()
// cameraController.lookAtXYZ(0, 0, 0)
onResize();
stage.addEventListener(Event.RESIZE, onResize);
atInit();
}
/**
* @private
*/
private function onResize(e:Event = null):void
{
if (_scaleToStage)
{
view.width = stage.stageWidth;
view.height = stage.stageHeight;
}
else
{
view.width = _viewWidth;
view.height = _viewHeight;
}
}
/**
* @private
*/
private function onRenderTick(e:Event = null):void
{
atPreRender();
_onPreRender()
cameraController.update();
camera.render();
atPostRender();
_onPostRender();
}
}