flash on 2011-11-30
/**
* Copyright heymichsaywhat ( http://wonderfl.net/user/heymichsaywhat )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/mrU4
*/
package
{
import flash.display.*;
import flash.events.*;
[SWF(width="600", height="600", frameRate="60")]
public class Main extends Sprite
{
private const NUM_X:int = 8;
private const NUM_Y:int = 8;
private const NODE_INFINITY:int = 1000000;
private var nodes:Array = null;
private var doneButton:Sprite = null;
private var jeje:Jeje = null;
public function Main()
{
nodes = [];
for (var gridX:int = 0; gridX < NUM_X; gridX++)
{
var column:Array = [];
nodes.push(column);
for (var gridY:int = 0; gridY < NUM_Y; gridY++)
{
var node:Node = new Node(gridX, gridY);
column.push(node);
addChild(node);
}
}
doneButton = new DoneButton();
addChild(doneButton);
doneButton.addEventListener(MouseEvent.CLICK, doneButtonClickListener);
addEventListener(Event.ENTER_FRAME, _enterFrameListener);
}
private function _enterFrameListener(e:Event):void
{
if (jeje) jeje.update();
}
private function doneButtonClickListener(e:MouseEvent):void
{
for (var gridX:int = 0; gridX < NUM_X; gridX++)
{
for (var gridY:int = 0; gridY < NUM_Y; gridY++)
{
var node:Node = (nodes[gridX][gridY] as Node);
node.stopOccupy();
if (node.occupied) continue;
for (var neighborIndex:int = 0; neighborIndex < 4; neighborIndex++)
{
var dx:int = 0;
var dy:int = 0;
switch (neighborIndex)
{
case 0:
dx = 1;
break;
case 1:
dy = -1;
break;
case 2:
dx = -1;
break;
case 3:
dy = 1;
break;
}
var neighborX:int = node.gridX + dx;
var neighborY:int = node.gridY + dy;
if (neighborX < 0) continue;
if (neighborY < 0) continue;
if (neighborX >= NUM_X) continue;
if (neighborY >= NUM_Y) continue;
var neighborNode:Node = nodes[neighborX][neighborY];
if (neighborNode.occupied) continue;
node.connectWith(neighborNode);
graphics.lineStyle(3, 0);
graphics.moveTo(node.x, node.y);
graphics.lineTo(neighborNode.x, neighborNode.y);
}
node.addEventListener(MouseEvent.CLICK, aStarWithInitialNode);
}
}
createJeje();
}
private function aStarWithInitialNode(e:Event):void
{
var initialNode:Node = jeje.node as Node;
var finalNode:Node = e.target as Node;
initialNode.g = 0;
initialNode.h = Math.abs(initialNode.gridX - finalNode.gridX) + Math.abs(initialNode.gridY - finalNode.gridY);
initialNode.f = initialNode.g + initialNode.h;
var openList:Array = [initialNode];
var closedList:Array = [];
while (openList.length > 0)
{
var currentNode:Node = openList.pop();
if (currentNode == finalNode)
{
// TODO: path was found, do something about it
throw new Error();
break;
}
for each (var neighborNode:Node in currentNode.neighbors)
{
var g:Number = currentNode.g + 1;
var h:Number = Math.abs(neighborNode.gridX - neighborNode.gridX) + Math.abs(neighborNode.gridY - neighborNode.gridY);
var f:Number = neighborNode.g + neighborNode.h;
// check if the neighbor is on the open or closed list
var isOnOpenList:Boolean = openList.indexOf(neighborNode) >= 0;
var isOnClosedList:Boolean = closedList.indexOf(neighborNode) >= 0;
if ((!(isOnOpenList || isOnClosedList)) || (f < neighborNode.f))
{
neighborNode.g = g;
neighborNode.h = h;
neighborNode.f = f;
// neighborNode.parent = currentNode;
if (isOnClosedList)
{
closedList.splice(closedList.indexOf(neighborNode), 1);
}
// TODO: put the element in the open list
throw new Error("you're supposed to put the element in the open list");
}
}
closedList.push(currentNode);
}
var unvisitedSet:Array = [];
for (var gridX:int = 0; gridX < NUM_X; gridX++)
{
for (var gridY:int = 0; gridY < NUM_Y; gridY++)
{
var node:Node = (nodes[gridX][gridY] as Node);
if (node.occupied) continue;
if (node == initialNode)
{
node.distanceFromInitial = 0;
}
else
{
node.distanceFromInitial = NODE_INFINITY;
}
unvisitedSet.push(node);
}
}
var currentNode:Node = initialNode;
while (currentNode != null)
{
for each (var neighborNode:Node in currentNode.neighbors)
{
if (unvisitedSet.indexOf(neighborNode) < 0) continue;
var tentativeDistanceFromInitial:int = currentNode.distanceFromInitial + 1;
if (tentativeDistanceFromInitial < neighborNode.distanceFromInitial)
{
neighborNode.distanceFromInitial = tentativeDistanceFromInitial;
}
}
unvisitedSet.splice(unvisitedSet.indexOf(currentNode), 1);
currentNode = null;
for each (var unvisitedNode:Node in unvisitedSet)
{
if ((currentNode == null) || (unvisitedNode.distanceFromInitial < currentNode.distanceFromInitial))
{
currentNode = unvisitedNode;
}
}
}
}
private function createJeje():void
{
var allNodes:Array = [];
for (var gridX:int = 0; gridX < NUM_X; gridX++)
{
for (var gridY:int = 0; gridY < NUM_Y; gridY++)
{
var node:Node = nodes[gridX][gridY] as Node;
if (node.hasJeje) continue;
if (node.occupied) continue;
allNodes.push(node);
}
}
if (allNodes.length == 0) return;
var randomNode:Node = allNodes[Math.floor(Math.random() * allNodes.length)];
jeje = new Jeje(randomNode);
addChild(jeje);
}
}
}
import flash.display.*;
import flash.events.*;
import flash.text.*;
class DoneButton extends Sprite
{
public function DoneButton()
{
graphics.lineStyle(2, 0xff0000);
graphics.beginFill(0xffffff);
graphics.drawCircle(0, 0, 36);
graphics.endFill();
x = 550;
y = 550;
}
}
class Jeje extends Sprite
{
private const FRAMES_TRAVEL:int = 30;
private var _previousNode:Node = null;
private var _node:Node = null;
private var _countdown:int = 0;
public function get node():Node
{
return _node;
}
public function Jeje(startingNode:Node)
{
_previousNode = startingNode;
_node = startingNode;
_node.hasJeje = true;
graphics.lineStyle(3, uint(Math.random() * 0xffffff));
graphics.drawCircle(0, 0, 12);
_placeJeje();
}
public function update():void
{
if (_countdown == 0)
{
for each (var neighbor:Node in _node.neighbors)
{
if ((neighbor.distanceFromInitial < _node.distanceFromInitial) && (!neighbor.hasJeje))
{
_previousNode = _node;
_previousNode.hasJeje = false;
_node = neighbor;
_node.hasJeje = true;
_countdown = FRAMES_TRAVEL;
break;
}
}
}
else
{
_countdown--;
}
_placeJeje();
}
private function _placeJeje():void
{
x = _node.x + (_countdown / FRAMES_TRAVEL) * (_previousNode.x - _node.x);
y = _node.y + (_countdown / FRAMES_TRAVEL) * (_previousNode.y - _node.y);
}
}
class Node extends Sprite
{
public var f:Number;
public var g:Number;
public var h:Number;
public var nodeParent:Node;
public var hasJeje:Boolean = false;
public var gridX:Number = 0;
public var gridY:Number = 0;
public var occupied:Boolean = false;
public var neighbors:Array = null;
private var _distanceFromInitial:int = 0;
private var textField:TextField = null;
public function Node(newGridX:Number, newGridY:Number)
{
neighbors = [];
gridX = newGridX;
gridY = newGridY;
x = 36 + 64 * gridX;
y = 36 + 64 * gridY;
addEventListener(MouseEvent.CLICK, clickListener);
drawMyself();
textField = new TextField();
addChild(textField);
}
public function set distanceFromInitial(value:int):void
{
_distanceFromInitial = value;
textField.text = _distanceFromInitial.toString();
}
public function get distanceFromInitial():int
{
return _distanceFromInitial;
}
public function stopOccupy():void
{
removeEventListener(MouseEvent.CLICK, clickListener);
}
private function clickListener(e:MouseEvent):void
{
occupied = !occupied;
drawMyself();
}
private function drawMyself():void
{
graphics.clear();
graphics.lineStyle(2, 0x660099);
graphics.beginFill(occupied ? 0xcc99ff : 0xffffff);
graphics.drawCircle(0, 0, 24);
graphics.endFill();
}
public function connectWith(node:Node):void
{
neighbors.push(node);
}
}