forked from: Iosmetric projection
...
@author Motoki Matsumoto
/**
* Copyright mtok ( http://wonderfl.net/user/mtok )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/6OLg
*/
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Vector3D;
import flash.filters.GlowFilter;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
/**
* ...
* @author Motoki Matsumoto
*/
public class IsometricWorldTest extends Sprite
{
private var _world:IsometricWorld;
private var _size:Number = 20;
private var _currentObj:IsometricObject;
private var _dt:Number;
public function IsometricWorldTest()
{
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
private function addedToStageHandler(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
init();
}
private function init():void {
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
_world = buildWorld();
_world.x = stage.stageWidth * 0.5;
_world.y = 30;
//_world.y = stage.stageHeight * 0.5;
addChild(_world);
_world.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
_world.addEventListener(MouseEvent.CLICK, clickHandler);
_world.zsort();
_dt = 1 / stage.frameRate;
stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
}
private function clickHandler(e:MouseEvent):void
{
var box:IsometricBox = e.target as IsometricBox;
var v:Vector3D;
if (box) {
v = new Vector3D(
100 * Math.random() - 50,
0,
100 * Math.random() - 50);
box.velocity = v;
}
}
private function keyUpHandler(e:KeyboardEvent):void
{
if (_currentObj) {
_currentObj.velocity = new Vector3D(0, 0, 0);
}
}
private function keyDownHandler(e:KeyboardEvent):void
{
if (_currentObj) {
switch(e.keyCode) {
case Keyboard.LEFT:
_currentObj.velocity = _currentObj.velocity.add(new Vector3D( 0, 0, 1));
break;
case Keyboard.RIGHT:
_currentObj.velocity = _currentObj.velocity.add(new Vector3D( 0, 0, -1));
break;
case Keyboard.UP:
_currentObj.velocity = _currentObj.velocity.add(new Vector3D(-1, 0, 0));
break;
case Keyboard.DOWN:
_currentObj.velocity = _currentObj.velocity.add(new Vector3D(1, 0, 0));
break;
}
}
}
private function enterFrameHandler(e:Event):void
{
_world.step(_dt);
}
private function mouseDownHandler(e:MouseEvent):void
{
var box:IsometricBox;
box = e.target as IsometricBox;
if (box) {
if (_currentObj != null) {
_currentObj.filters = [];
}
box.filters = [new GlowFilter(0x00ffff, 1, 4, 4)];
_currentObj = box;
}
}
private function buildWorld():IsometricWorld {
var iw:IsometricWorld = new IsometricWorld();
var floor:IsometricFloor;
var s:int = _size;
for (var i:int = 0; i < 15; i++) {
for ( var j:int = 0; j < 15; j++) {
floor = new IsometricFloor(s);
floor.position = new Vector3D(i * s, 0, j * s);
iw.addChildObj(floor);
}
}
var box:IsometricBox;
box = new IsometricBox(s, 0xff0000);
box.x = s * 3;
box.z = s * 3;
box.height = s * 2 / Math.sqrt(3);
iw.addChildObj(box);
box = new IsometricBox(s, 0x00ff00);
box.x = s * 2;
box.z = s * 2;
box.height = s * 2 / Math.sqrt(3);
iw.addChildObj(box);
box = new IsometricBox(s, 0x0000ff);
box.x = s * 1;
box.z = s * 1;
box.height = s * 2 / Math.sqrt(3);
iw.addChildObj(box);
return iw;
}
}
}
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.display.Graphics;
import flash.events.Event;
import flash.geom.Rectangle;
import flash.geom.Vector3D;
import flash.geom.Point;
class IsometricWorld extends Sprite {
private var _floor:Sprite;
private var _world:Sprite;
private var _gravity:Number = 2;
private var _sortBuffer:Vector.<IsometricObject>;
private var _boundary:Rectangle;
public function IsometricWorld() {
super();
addChild(_floor = new Sprite());
addChild(_world = new Sprite());
_sortBuffer = new Vector.<IsometricObject>();
}
public function addChildObj(child:IsometricObject):IsometricObject
{
if ( child is IsometricFloor) {
_floor.addChild(child);
}else {
_world.addChild(child);
_sortBuffer.push(child);
}
return child;
}
public function step(dt:Number):void {
var i:int;
var len:int = _world.numChildren;
var isoObj:IsometricObject;
var bounce:Number = -0.8;
var maxX:Number = 280;
var minX:Number = 0;
var maxZ:Number = 280;
var minZ:Number = 0;
for ( i = 0; i < len; i++) {
isoObj = _world.getChildAt(i) as IsometricObject;
isoObj.velocity.y += _gravity;
isoObj.step(dt);
if (isoObj.x > maxX) {
isoObj.x = maxX;
isoObj.velocity.x *= bounce;
} else if (isoObj.x < minX) {
isoObj.y = minX;
isoObj.velocity.x *= bounce;
}
if ( isoObj.z > maxZ) {
isoObj.z = maxZ;
isoObj.velocity.z *= bounce;
}else if (isoObj.z < minZ) {
isoObj.z = minZ;
isoObj.velocity.z *= bounce;
}
if ( isoObj.y > 0) {
isoObj.y = 0;
isoObj.velocity.y *= bounce;
}
}
zsort();
}
public function zsort():void {
_sortBuffer = _sortBuffer.sort(
function(a:IsometricObject, b:IsometricObject):Number {
return a.depth - b.depth;
});
var len:int = _sortBuffer.length;
for (var i:int = 0; i < len; i++) {
_world.setChildIndex(_sortBuffer[i], i);
}
}
}
class IsometricObject extends Sprite {
private var _position:Vector3D;
private var _velocity:Vector3D;
private var _maxSpeed:Number;
private var _friction:Number = 1;
private var _bInvalidDisplay:Boolean;
private var _bInvalidPosition:Boolean;
private var _depth:Number;
public function IsometricObject() {
_position = new Vector3D();
_velocity = new Vector3D();
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
private function addedToStageHandler(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
addEventListener(Event.RENDER, renderHandler);
_draw();
_updateScreenPosition();
}
private function renderHandler(e:Event):void
{
if (_bInvalidDisplay) {
_draw();
}
if (_bInvalidPosition) {
_updateScreenPosition();
}
}
protected function invalidateDisplay():void {
_bInvalidDisplay = true;
if(stage) stage.invalidate();
}
protected function invalidatePosition():void {
_bInvalidPosition = true;
if(stage) stage.invalidate();
}
protected function _draw():void { }
public function step(dt:Number):void {
var v:Vector3D = _velocity.clone();
v.scaleBy(dt);
position = _position.add(v);
_velocity.scaleBy(_friction);
}
protected function _updateScreenPosition():void {
var p:Vector3D = IsoUtils.isoToScreen(_position);
super.x = p.x;
super.y = p.y;
_depth = p.z;
if(stage) stage.invalidate();
}
override public function get x():Number { return _position.x; }
override public function set x(value:Number):void
{
_position.x = value;
_updateScreenPosition();
};
override public function get y():Number { return _position.y; }
override public function set y(value:Number):void
{
_position.y = value;
_updateScreenPosition();
}
override public function get z():Number { return _position.z; }
override public function set z(value:Number):void
{
_position.z = value;
_updateScreenPosition();
}
public function get position():Vector3D { return _position; }
public function set position(value:Vector3D):void
{
_position = value;
_updateScreenPosition();
}
public function get depth():Number { return _depth; }
public function get velocity():Vector3D { return _velocity; }
public function set velocity(value:Vector3D):void
{
_velocity = value;
}
public function get vx():Number { return _velocity.x; }
public function set vx(value:Number):void
{
_velocity.x = value;
}
public function get vy():Number { return _velocity.y; }
public function set vy(value:Number):void
{
_velocity.y = value;
}
public function get vz():Number { return _velocity.z; }
public function set vz(value:Number):void
{
_velocity.z = value;
}
}
class IsometricFloor extends IsometricObject {
private var _size:Number;
private var _color:uint;
private var _walkable:Boolean = true;
public function IsometricFloor(size:Number, color:uint = 0xcccccc) {
_size = size;
_color = color;
super();
}
override protected function _draw():void
{
var g:Graphics = graphics;
g.lineStyle(1, 0, 0.8);
g.beginFill(color, 0.5);
g.moveTo( -_size, 0);
g.lineTo(0, -_size * 0.5);
g.lineTo(_size, 0);
g.lineTo(0, _size * 0.5);
g.lineTo( -_size, 0);
g.endFill();
}
public function get size():Number { return _size; }
public function set size(value:Number):void
{
_size = value;
}
public function get color():uint { return _color; }
public function set color(value:uint):void
{
_color = value;
}
public function get walkable():Boolean { return _walkable; }
public function set walkable(value:Boolean):void
{
_walkable = value;
}
}
class IsometricBox extends IsometricObject {
private var _size:Number;
private var _color:uint;
private var _height:Number;
private var _invalidDisplay:Boolean = true;
public function IsometricBox(size:Number, color:uint=0xcccccc) {
_size = size;
_height = size;
_color = color;
super();
}
override protected function _draw():void
{
var red:uint = _color >> 16;
var green:uint = _color >> 8 & 0xff;
var blue:uint = _color & 0xff;
var c:uint;
var g:Graphics = graphics;
var h:Number = _height;
var s:Number = _size;
//left
c = (red >> 1) << 16 | (green >> 1) << 8 | blue >> 1;
g.beginFill(c);
g.moveTo( -s, -h);
g.lineTo( 0, s * 0.5 - h);
g.lineTo( 0, s * 0.5);
g.lineTo( -s, 0);
g.lineTo( -s, -h);
g.endFill();
//right
c = (red * 0.75) << 16 | (green * 0.75) << 8 | blue * 0.75;
g.beginFill(c);
g.moveTo( s, -h);
g.lineTo( 0, s * 0.5 - h);
g.lineTo( 0, s * 0.5);
g.lineTo( s, 0);
g.lineTo( s, -h);
g.endFill();
//top
g.beginFill(color);
g.moveTo( -s, - h );
g.lineTo( 0, - h - s * 0.5);
g.lineTo( s, - h );
g.lineTo( 0, - h + s * 0.5);
g.lineTo( -s, - h );
g.endFill();
}
public function get color():uint { return _color; }
public function set color(value:uint):void
{
_color = value;
_invalidDisplay = true;
if (stage != null) {
stage.invalidate();
}
}
public function get size():Number { return _size; }
public function set size(value:Number):void
{
_size = value;
_invalidDisplay = true;
if (stage != null) {
stage.invalidate();
}
}
override public function get height():Number { return _height; }
override public function set height(value:Number):void
{
_height = value;
_invalidDisplay = true;
if (stage != null) {
stage.invalidate();
}
}
}
class IsoUtils {
public static const Y_CORRECT:Number = Math.cos( -Math.PI / 6) * Math.SQRT2;
private static const SQRT2_2:Number = Math.sqrt(2) * 0.5;
private static const SQRT3_2:Number = Math.sqrt(3) * 0.5;
public static function isoToScreen(pos:Vector3D):Vector3D {
var screenX:Number = pos.x - pos.z;
var screenY:Number = pos.y * Y_CORRECT + (pos.x + pos.z) * 0.5;
var depth:Number = SQRT3_2 * (pos.x + pos.y) - SQRT2_2 * pos.y;
return new Vector3D(screenX, screenY, depth);
}
public static function screenToIso(point:Point):Vector3D {
var xpos:Number = point.y + point.x * 0.5;
var ypos:Number = 0;
var zpos:Number = point.y - point.x * 0.5;
return new Vector3D(xpos, ypos, zpos);
}
}