depth sort
use depth index table to sort.
the collision detect using math round so it not so perfect which might impact the sorting result.
/**
* Copyright andyshang ( http://wonderfl.net/user/andyshang )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/yebs
*/
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Rectangle;
import flash.ui.Keyboard;
[SWF(width="465", height="465")]
public class Main extends Sprite
{
private var keyManager:KeyManager = new KeyManager();
public function Main()
{
var canvas:Canvas = new Canvas();
drawDebugRect = function(x:int, y:int):void
{
graphics.clear();
graphics.lineStyle(2,0xAB0000);
graphics.drawRect(
x * Tile.tileSize + canvas.viewPort.x,
y*Tile.tileSize + canvas.viewPort.y
, Tile.tileSize, Tile.tileSize);
};
addChild(canvas);
canvas.viewPort = new Rectangle(0,0,stage.stageWidth, stage.stageHeight);
canvas.pan(canvas.role.x * 32, canvas.role.y*32);
keyManager.listen(stage);
addEventListener(Event.ENTER_FRAME, function(event:Event):void
{
if(keyManager.isDown(Keyboard.UP))
{
canvas.role.move(0,-1)
}
if(keyManager.isDown(Keyboard.DOWN))
{
canvas.role.move(0,1)
}
if(keyManager.isDown(Keyboard.LEFT))
{
canvas.role.move(-1,0)
}
if(keyManager.isDown(Keyboard.RIGHT ))
{
canvas.role.move(1,0)
}
})
}
}
}
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.KeyboardEvent;
import flash.geom.Matrix;
import flash.geom.Rectangle;
class Canvas extends Sprite
{
public static var mapWidth:int = 12;
private var _viewPort:Rectangle;
public function set viewPort(viewPort:Rectangle):void
{
_viewPort = viewPort;
draw();
}
public function get viewPort():Rectangle
{
return _viewPort;
}
public var role:Role;
private var tiles:Vector.<Tile> = new Vector.<Tile>;
private var depthIndexTable:Array = []
public function Canvas()
{
var tile:Tile;
for(var i:int=0;i<pathMap.length;i++)
{
if(pathMap[i] == "x")
{
tile = new Block();
}
else if(pathMap[i] == "A")
{
role = new Role();
tile = role;
}
else
{
continue;
}
tile.x = i % mapWidth;
tile.y = i / mapWidth;
tile.container = this;
tiles.push(tile);
if(isNaN(depthIndexTable[tile.y]))
{
depthIndexTable[tile.y] = 0;
}
depthIndexTable[tile.y]++;
}
}
public function updateDepth(object:Tile, from:int, to:int):void
{
//look up depth table first
var depth:int = 0;
depthIndexTable[from] --;
depthIndexTable[to] ++;
for(var i:int;i<=to;i++)
{
depth += depthIndexTable[i];
}
setChildIndex(object.asset, depth);
if(depth == 0 || depth == numChildren)
{
return;
}
if(object.asset.y < getChildAt(depth-1).y)
{
depth -= depthIndexTable[i-1];
setChildIndex(object.asset, depth);
}
//now the object's depth is highest in the same line.
//adjust by asset.y , to see if it should be put to next line.
//for the map is closed, we do not check out of range.
if(object.asset.y > getChildAt(depth+1).y)
{
depth += depthIndexTable[i];
setChildIndex(object.asset, depth);
}
}
public function pan(x:int ,y:int):void
{
_viewPort.x -= x;
_viewPort.y -= y;
draw();
}
public function panTo(x:int ,y:int):void
{
_viewPort.x = x;
_viewPort.y = y;
draw();
}
public function draw():void
{
for each(var tile:Tile in tiles)
{
tile.render(_viewPort);
}
}
}
class Tile
{
public static var tileSize:int = 64;
public var x:int;
public var y:int;
public var container:Canvas;
public var asset:Shape;
protected var rect:Rectangle;
public function render(rect:Rectangle):void
{
this.rect = rect;
if(!container.contains(asset))
{
container.addChild(asset);
}
asset.x = x * tileSize + rect.x;
asset.y = y * tileSize + rect.y;
}
}
class Role extends Tile
{
public static const SPEED:Number = 3;
public function Role():void
{
asset = new Shape();
asset.graphics.beginFill(0x0, 0.7);
asset.graphics.drawRect(1,-tileSize,tileSize,2*tileSize);
}
public function move(dx:int, dy:int):void
{
moved = true
container.pan(dx * SPEED, dy * SPEED);
var lastY:int = y;
x = Math.round((asset.x - rect.x) / tileSize);
y = Math.round((asset.y - rect.y) / tileSize);
//swap depth if y changed
if(pathMap[y*Canvas.mapWidth + x] == "x")
{
container.pan(-dx * SPEED, -dy * SPEED);
return;
}
if(dy != 0)
{
container.updateDepth(this, lastY, y);
}
drawDebugRect(x,y);
}
private var moved:Boolean = false;
override public function render(rect:Rectangle):void
{
if(!moved)
{
super.render(rect);
}
}
}
class Block extends Tile
{
private var colors:Array = [0xFF0000, 0xFFFF00, 0x00FF00, 0x00FFFF, 0x0000FF, 0xFF00FF, 0xFF0000];
private var alphas:Array = [100, 100, 100, 100, 100, 100, 100];
private var ratios:Array = [0x00, 0x2A, 0x55, 0x7F, 0xAA, 0xD4, 0xFF];
public function Block()
{
asset = new Shape();
asset.graphics.beginFill(0xABCDEF, 1);
asset.graphics.lineStyle(1);
asset.graphics.drawRect(1,-.5*tileSize,tileSize-2,tileSize);
asset.graphics.beginFill(0x345678, 1);
asset.graphics.drawRect(8,0,tileSize-16,tileSize-4);
// asset.graphics.beginGradientFill("linear", colors, alphas, ratios);
// asset.graphics.drawRect(1,-1.5*tileSize,tileSize,2.5*tileSize);
}
}
interface IKeyboard
{
function actPress(keyCode:int, shift:Boolean):void;
function actRelease(keyCode:int, shift:Boolean):void;
}
class KeyManager
{
private var _isDownFunc:Function;
private var downKeys:Vector.<int> = new Vector.<int>(256);
private var keyboards:Vector.<IKeyboard> = new Vector.<IKeyboard>;
private var isLocked:Boolean = false;
public function addKeyboard(keyboard:IKeyboard):void
{
keyboards.push(keyboard);
}
public function lock():void
{
isLocked = true;
}
public function unlock():void
{
isLocked = false;
}
public function listen(stage:Stage):void
{
stage.addEventListener(KeyboardEvent.KEY_UP, function(event:KeyboardEvent):void
{
actRelease(event.keyCode, Boolean(downKeys[event.keyCode] & 0x100));
downKeys[event.keyCode] = 0;
})
stage.addEventListener(KeyboardEvent.KEY_DOWN, function(event:KeyboardEvent):void
{
if(isDown(event.keyCode))
{
return;
}
actPress(event.keyCode, event.shiftKey);
downKeys[event.keyCode] = 1;
})
_isDownFunc = function(keyCode:int):Boolean
{
return downKeys[keyCode] > 0;
}
}
public function isDown(keyCode:int):Boolean
{
return _isDownFunc(keyCode);
}
public function actPress(keyCode:int, shift:Boolean):void
{
for each(var k:IKeyboard in keyboards)
{
k.actPress(keyCode, shift);
}
}
public function actRelease(keyCode:int, shift:Boolean):void
{
for each(var k:IKeyboard in keyboards)
{
k.actRelease(keyCode, shift);
}
}
}
var pathMap:Array =
"\
xxxxxxxxxxxx\
x0000000000x\
x00x0000000x\
xx0000A000xx\
x00000x00x0x\
xxxx0000xx0x\
x0000000000x\
xxxxxxxxxxxx\
".
split("");
var drawDebugRect:Function;