Implementasi Algoritma A Berbasis Pathfinding Dalam Pengembangan Game Menanam Pohon

A-1

LISTING PROGRAM

GuardianTree.cs
package com.vuseon.guardiantree
{
import com.vuseon.guardiantree.screen.MainMenu;
import flash.desktop.NativeApplication;
...
import com.vuseon.guardiantree.properties.GameProperties;
public class GuardianTree extends Sprite
{
private
private
private
private

var
var
var

var

stats:Stats;
starling:Starling;
s:String;
tf:TextField;

public function GuardianTree()
{
initScreen();
Starling.handleLostContext = true;
var viewPort:Rectangle = new Rectangle(0, 0,
stage.fullScreenWidth, stage.fullScreenHeight)
starling = new Starling(Game, stage, viewPort);
s = starling.stage.stageWidth + " " +
starling.stage.stageHeight + " " + starling.stage.stageWidth + " " +
starling.stage.stageHeight;
starling.stage.stageWidth = GameProperties.stageW;
starling.stage.stageHeight = GameProperties.stageH;
starling.antiAliasing = 1;

starling.start();
Starling.current.nativeStage.addEventListener(KeyboardEvent.KEY_DOWN
, keyPressed);
}
private function initScreen():void
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.addEventListener(Event.RESIZE, stageResize);
}
private function stageResize(e:Event):void
{
removeEventListener(Event.RESIZE, stageResize);
}
private function deactivate(e:Event):void
{
NativeApplication.nativeApplication.exit();
}

Universitas Sumatera Utara


A-2

private function keyPressed(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.BACK)
{
e.preventDefault();
e.stopImmediatePropagation();
trace("Back button is pressed");
}
}
}
}

Game.as
package com.vuseon.guardiantree
{
import com.vuseon.guardiantree.events.NavigationEvent;
import com.vuseon.guardiantree.properties.GameProperties;

...
import starling.events.Event;
public class Game extends Sprite
{
private var screenMainMenu:MainMenu;
private var screenInGame:InGame;
...
private var currentState:Sprite;
public function Game()
{
new MetalWorksMobileTheme();
this.addEventListener(Event.ADDED_TO_STAGE,
onAddedToStage);
}
private function onAddedToStage(event:Event):void
{

this.removeEventListener(starling.events.Event.ADDED_TO_STAGE,
onAddedToStage);
Starling.current.showStats = true;

this.addEventListener(NavigationEvent.CHANGE_SCREEN,
onChangeScreen);
addChild(new Intro());
}
private function onChangeScreen(event:NavigationEvent):void
{
switch (event.params.id)
{
case "intro":
break;
case "main_menu":
if (screenAboutGame != null)

Universitas Sumatera Utara

A-3

screenAboutGame.disposeTemporarily();
if (screenInGame != null)
{

removeChild(screenInGame);
screenInGame = null;
}
if (screenMainMenu == null) {
screenMainMenu = new MainMenu();
screenMainMenu.initialize();
this.addChild(screenMainMenu);
}else{
screenMainMenu.visible = true;
}
addChild(new Transition(this));
break;
case "about":
trace("ABOUT");
if (screenAboutGame == null)
screenAboutGame = new AboutGame();
screenAboutGame.initialize();
this.addChild(screenAboutGame);
screenMainMenu.disposeTemporarily();
addChild(new Transition(this));

break;
case "help":
if (screenHelp == null)
screenHelp = new Help();
screenHelp.initialize();
this.addChild(screenHelp);
screenMainMenu.disposeTemporarily();
addChild(new Transition(this));
break;
case "level":
screenMainMenu.disposeTemporarily();
if (screenInGame != null)
{
removeChild(screenInGame);
screenInGame = null
}
if (screenLevel == null)
screenLevel = new LevelSelection();
else{
screenLevel.revive();

}
screenLevel.initialize();
this.addChild(screenLevel);
screenMainMenu.disposeTemporarily();
addChild(new Transition(this));
break;
case "play":
if (screenInGame != null)

Universitas Sumatera Utara

A-4

{
removeChild(screenInGame);
screenInGame = null
}
if (screenInGame == null)
screenInGame = new InGame();
screenInGame.initialize();

this.addChild(screenInGame);
screenLevel.disposeTemporarily();
addChild(new Transition(this));
break;
}
}
}
}

MainMenu.cs
package com.vuseon.guardiantree.screen
{
import com.vuseon.guardiantree.Assets;
import com.vuseon.guardiantree.events.NavigationEvent;
...
import starling.events.Event;
public class MainMenu extends Sprite
{
private var _bg:Image;
private var _btnOption:Button;

...
private var _btnQuit:Button;
public function MainMenu()
{
super();
}
public function initialize():void
{
this.visible = true;
this.addEventListener(starling.events.Event.ADDED_TO_STAGE,
onAddedToStage);
}
public function disposeTemporarily():void
{
this.visible = false;
}
private function onAddedToStage(event:Event):void
{

Universitas Sumatera Utara


A-5

this.removeEventListener(starling.events.Event.ADDED_TO_STAGE,
onAddedToStage);
trace("welcome screen initialized");
_bg = new Image(Assets.getTexture("MainMenuBmp"));
addChild(_bg);
_btnPlay = new
Button(Assets.getAtlas().getTexture("menu_play"));
_btnPlay.x = GameProperties.stageW / 4 - 30;
_btnPlay.y = 300;
_btnPlay.addEventListener(Event.TRIGGERED,
onTriggered);
addChild(_btnPlay);
/*_btnOption = new
Button(Assets.getAtlas().getTexture("main_options"));
_btnOption.x =
GameProperties.stageW/4+_btnOption.width+60;
_btnOption.y = 300;
addChild(_btnOption);*/
_btnHelp = new
Button(Assets.getAtlas().getTexture("menu_help"));
_btnHelp.x = GameProperties.stageW / 4 + _btnHelp.width
* 2.5 - 50;
_btnHelp.y = 300;
_btnHelp.addEventListener(Event.TRIGGERED,
onTriggered);
addChild(_btnHelp);
_btnAbout = new
Button(Assets.getAtlas().getTexture("menu_information"));
_btnAbout.x = GameProperties.stageW / 4 +
_btnAbout.width * 5 - 50;
_btnAbout.y = 300;
_btnAbout.addEventListener(Event.TRIGGERED,
onTriggered);
addChild(_btnAbout);
_btnQuit = new
Button(Assets.getAtlas().getTexture("menu_xcross"));
_btnQuit.x = GameProperties.stageW / 4 +
_btnAbout.width * 7.5 - 50;
_btnQuit.y = 300;
_btnQuit.addEventListener(Event.TRIGGERED,
onTriggered);
addChild(_btnQuit);
_btnOption = new
Button(Assets.getAtlas().getTexture("menu_menu"));
_btnOption.x = GameProperties.stageW / 10 +
_btnAbout.width * 7.5 - 50;
_btnOption.y = 0;
_btnOption.addEventListener(Event.TRIGGERED,
onTriggered);
addChild(_btnOption);

Universitas Sumatera Utara

A-6

//
_btnOption.visible = false;
var title:Image = new
Image(Assets.getTexture("TitleBmp"));
title.x = GameProperties.stageW / 4;
title.y = GameProperties.stageH / 6;
addChild(title);
}
private function onTriggered(e:Event):void
{
var btn:Button = e.target as Button;
switch (btn)
{
case _btnPlay:
this.dispatchEvent(new
NavigationEvent(NavigationEvent.CHANGE_SCR
EEN, {id: "level"}, true));
break;
case _btnHelp:
this.dispatchEvent(new
NavigationEvent(NavigationEvent.CHANGE_SCR
EEN, {id: "help"}, true));
break;
case _btnAbout:
this.dispatchEvent(new
NavigationEvent(NavigationEvent.CHANGE_SCR
EEN, {id: "about"}, true));
break;
case _btnQuit:
NativeApplication.nativeApplication.exit();
break;
case _btnOption:
showOption();
break;
}
}
private function showOption():void
{
new OptionPanel(this);
}
}
}

AStar.as
package com.vuseon.guardiantree.pathfinding
{
import com.vuseon.guardiantree.properties.GameProperties;
import com.vuseon.guardiantree.properties.GameStatistic;

Universitas Sumatera Utara

A-7

...
import starling.utils.Color;
public class AStar
{
private var _open:Array;
private var _closed:Array;
...
private var ii:uint = 0;
public function AStar()
{
}
public function findPath(grid:Grid):Boolean
{
_time = getTimer();
trace("waktu awal: " + _time);
_grid = grid;
_open = new Array();
_closed = new Array();
_startNode = _grid.startNode;
_endNode = _grid.endNode;
_searchPath = new Array();
_startNode.g = 0;
_startNode.h = _heuristic(_startNode);
_startNode.f = _startNode.g + _startNode.h;
return search();
}
public function search():Boolean
{
var node:Node = _startNode;
var iii:int = 0;
while (node != _endNode)
{
var startX:int = Math.max(0, node.x var endX:int = Math.min(_grid.numCols
node.x + 1);
var startY:int = Math.max(0, node.y var endY:int = Math.min(_grid.numRows

1);
- 1,
1);
- 1,

node.y + 1);
for (var i:int = startX; i f2)
{
f1 = f2;
index = i;
}
}
trace("index:" + index);
return index;
}
private function buildPath():void
{
_path = new Array();
var node:Node = _endNode;
_path.push(node);
while (node != _startNode)
{
node = node.parent;
_path.unshift(node);
}
}
public function get path():Array
{
return _path;
}
private function isOpen(node:Node):Boolean
{
for (var i:int = 0; i < _open.length; i++)
{
if (_open[i] == node)

Universitas Sumatera Utara

A-10

{
return true;
}
}
return false;
}
private function isClosed(node:Node):Boolean
{
for (var i:int = 0; i < _closed.length; i++)
{
if (_closed[i] == node)
{
return true;
}
}
return false;
}
private function manhattan(node:Node):Number
{
return Math.abs(node.x - _endNode.x) * _straightCost +
Math.abs(node.y - _endNode.y) * _straightCost;
}
public function get visited():Array
{
return _closed.concat(_open);
}
public function get searchPath():Array
{
return _searchPath;
}
public function set searchPath(value:Array):void
{
_searchPath = value;
}
}
}

InGame.as
package com.vuseon.guardiantree.screen
{
import com.vuseon.guardiantree.Assets;
import com.vuseon.guardiantree.events.NavigationEvent;
...
import com.vuseon.guardiantree.objects.Character;
public class InGame extends Sprite
{
private var _cellSize:int = 60;
private var _grid:Grid;
...

Universitas Sumatera Utara

A-11

public var _grounds:Vector.;
public function InGame()
{
//stage.align = StageAlign.TOP_LEFT;
//stage.scaleMode = StageScaleMode.NO_SCALE;
//this.addEventListener(starling.events.Event.ADDED_TO_STAGE,
onAddedToStage);
}
public function initialize():void
{
this.addEventListener(starling.events.Event.ADDED_TO_STAGE,
onAddedToStage);
}
private function onAddedToStage(event:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE,
onAddedToStage);
GameProperties.gameWorld = this;
makeGrid();
setUi();
setDefaultProperties();
setEvent();
}
private function setEvent():void
{
_myTimer = new StarlingTimer(Starling.juggler, 1000,
0);
_myTimer.addEventListener(StarlingTimerEvent.TIMER,
onTimerUpdate);
_myTimer.start();
this.addEventListener(EnterFrameEvent.ENTER_FRAME,
gameLoop);
}
private function onTimerUpdate(e:Event):void
{
trace("Current Time:" + _timer + " TIME SPAWN:" +
GameProperties.timeEnemySpawn);
trace("Current Enemy:" + _enemies.length + " Enemy In:"
+ GameProperties.enemyIn);
}
private function gameLoop(e:EnterFrameEvent):void
{
if (GameProperties.isPaused)
return;
GameStatistic.showTime();

Universitas Sumatera Utara

A-12

if (_trees != null && _trees.length > 0)
{
_startGame = true;
if (_enemies.length < GameProperties.MAX_ENEMY)
_timer++;
if (_timer > GameProperties.timeEnemySpawn &&
GameProperties.timeEnemySpawn > 60 && _enemies.length <
GameProperties.MAX_ENEMY)
{
_timer = 0;
spawnEnemy();
GameProperties.enemyIn++;
if (GameProperties.enemyIn % 3 == 0)
{
GameProperties.timeEnemySpawn -=
30;
}
if (GameProperties.enemyIn % 6 == 0)
{
GameProperties.maxEnemy++;
}
}
}
if (_trees != null && _trees.length == 0 && _startGame)
{
this.removeEventListener(EnterFrameEvent.ENTER_FRAME, gameLoop);
GameProperties.isPaused = true;
Starling.juggler.pause();
addChild(new PopUpMenu("game_over", this));
}
}
private function showMenu():void
{
}
public function gameOver():void
{
_startGame = false;
destroyChild();
resetTileColor();
dispose();
}
private function setDefaultProperties():void
{
_enemies = new Array();
_heroes = new Array();
_trees = new Array();
GameProperties.enemyDmg = GameProperties.ENEMY_DMG;
GameProperties.heroDmg = GameProperties.HERO_DMG;
GameProperties.treeOxy = GameProperties.TREE_OXY;
GameProperties.maxEnemy = GameProperties.MAX_ENEMY;

Universitas Sumatera Utara

A-13

GameProperties.timeEnemySpawn =
GameProperties.TIME_ENEMY_SPAWN;
GameProperties.enemyIn = 0;
GameStatistic.oxy = GameProperties.START_OXY;
GameStatistic.score = 0;
GameStatistic.times = 0
GameStatistic.oxygentxt.text = "OXY : 300";
GameStatistic.scoreText.text = "SCORE : 0";
GameStatistic.timetxt.text = "TIME : 0"
GameProperties.isPaused = false;
}
private function setUi():void
{
characterHUD();
consoleText();
statusHUD();
buttonHUD();
}
private function buttonHUD():void
{
_btnPause = new
Button(Assets.getAtlas().getTexture("menu_pause"));
_btnPause.x = 30;
_btnPause.y = 460;
addChild(_btnPause);
_btnPause.addEventListener(Event.TRIGGERED,
onTriggered);
var str:String = (GameProperties.showPath) ?
"menu_check" :
"menu_xcross";
_btnDev = new
Button(Assets.getAtlas().getTexture(str));
_btnDev.x = 50 + _btnDev.width;
_btnDev.y = 460;
_btnDev.text = "Developer Mode?";
_btnDev.addEventListener(Event.TRIGGERED, onTriggered);
addChild(_btnDev);
_btnPause.addEventListener(Event.TRIGGERED,
onTriggered);
}
private function onTriggered(e:Event):void
{
if (e.target as Button == _btnPause)
{
if (!GameProperties.isPaused)
{
GameProperties.isPaused = true;
Starling.juggler.pause();

Universitas Sumatera Utara

A-14

addChild(new PopUpMenu("pause", this));
}
else
{
GameProperties.isPaused = false;
Starling.juggler.start();
}
}
else if (e.target as Button == _btnDev)
{
if ((GameProperties.showPath))
{
_btnDev.upState =
Assets.getAtlas().getTexture("menu_xcross");
resetTileColor();
GameProperties.showPath = false;
}
else
{
_btnDev.upState =
Assets.getAtlas().getTexture("menu_check");
GameProperties.showPath = true;
}
}
}
private function statusHUD():void
{
GameStatistic.time = new Timer();
GameStatistic.time.start();
GameStatistic.scoreText = new TextField(200, 32, "SCORE
: " + GameStatistic.score, Assets.getFont().name, 20, 0xffffff);
GameStatistic.scoreText.hAlign = HAlign.LEFT;
GameStatistic.scoreText.x = 200;
GameStatistic.scoreText.y = GameProperties.stageH - 60;
addChild(GameStatistic.scoreText);
GameStatistic.oxygentxt = new TextField(200, 32, "OXY :
" + GameProperties.START_OXY, Assets.getFont().name, 20, 0xffffff);
GameStatistic.oxygentxt.hAlign = HAlign.LEFT;
GameStatistic.oxygentxt.x = 330;
GameStatistic.oxygentxt.y = GameProperties.stageH - 60;
addChild(GameStatistic.oxygentxt);
GameStatistic.timetxt = new TextField(200, 32, "TIME :
" + GameStatistic.times + " s", Assets.getFont().name, 20, 0xffffff);
GameStatistic.timetxt.hAlign = HAlign.LEFT;
GameStatistic.timetxt.x = 460;
GameStatistic.timetxt.y = GameProperties.stageH - 60;
//GameStatistic.timetxt.border = true;
//GameStatistic.timetxt.height =
GameStatistic.oxygentxt.textBounds.height + 10;
addChild(GameStatistic.timetxt);

Universitas Sumatera Utara

A-15

}
private function spawnEnemy():void
{
trace("Game tree: " + _trees.length);
var _enemy:Enemy = new Enemy(this, _grid,
_trees[Math.round(Math.random() * (_trees.length - 1))], _cellSize,
_path);
_enemy.x = (Math.pow(14, Math.round(Math.random() * 1))
* _cellSize) + 30;
_enemy.y = (Math.pow(5, Math.round(Math.random() * 1))
* _cellSize) + 30;
if (GameProperties.currentLevel == 1)
{
_enemy.x = 30;
_enemy.y = _cellSize + 30;
}
else if (GameProperties.currentLevel == 3)
{
_enemy.x = 30;
_enemy.y = 30;
}
else if (GameProperties.currentLevel == 4)
{
_enemy.x = 30;
_enemy.y = 8 * _cellSize + 30;
}
this.addChild(_enemy);
_enemy.findTarget(_trees);
_enemies.push(_enemy);
}
private function makeGrid():void
{
if (GameProperties.currentLevel 0)
GameStatistic.addOxy(-10);
takeDmg(5);
}
if (_health 0)
{
_htrees = new Array();
_trees = trees;
xpos = Math.floor(x / _cellSize);
ypos = Math.floor(y / _cellSize);
var astar:AStar = new AStar();
var tempLength:Array = new Array();
for (var i:uint = 0; i < _trees.length; i++)
{
_grid.setEndNode(_trees[i].xpos,
_trees[i].ypos);
_grid.setStartNode(xpos, ypos);
if (astar.findPath(_grid))

Universitas Sumatera Utara

A-18

{
var temp:Array = new Array();
temp[0] = i;
temp[1] = astar.path.length;
temp[2] = astar.path;
temp[3] = astar.searchPath;
tempLength.push(temp);
}
}
_index = 0;
trace(tempLength);
tempLength.sortOn("1", Array.NUMERIC);
trace(tempLength);
_path = tempLength[0][2];
_targetIndex = tempLength[0][0];
trace("tree " + _trees[_targetIndex].xpos + " "
+ _trees[_targetIndex].ypos);
for (var j:uint = 0; j < _path.length; j++)
trace(_path[j].x + " " + _path[j].y);
if (GameProperties.showPath)
{
ii = 0;
jj = _path.length - 1;
_searchPath = tempLength[0][3];
_myTimer.addEventListener(StarlingTimerEvent.TIMER, onTimerUpdate);
_myTimer.start();
}else {
addEventListener(Event.ENTER_FRAME,
enterFrame);
}
tempLength = null;
//trace(_path);
}
}
private function onTimerUpdate(e:Event):void
{
if (ii >= _searchPath.length)
{
if (jj 0)
{
vx = _moveSpeed;
_enemymc.play("walk_right");
}
else if (dx < 0)
{
vx = -_moveSpeed;
_enemymc.play("walk_left");
}
else
{

Universitas Sumatera Utara

A-20

vx = 0;
}
if (dy > 0)
{
vy = _moveSpeed;
_enemymc.play("walk_down");
}
else if (dy < 0)
{
vy = -_moveSpeed;
_enemymc.play("walk_up");
}
else
{
vy = 0;
}
if (dist < 1)
{
trace("index:" + _index + " path length:"
+
_path.length);
_index++;
}
else
{
if (_index >= _path.length - 1)
{
var dxx:Number = (x - 30) –
_trees[_targetIndex].x;
var dyy:Number = y _trees[_targetIndex].y;
if (Math.sqrt(dx * dx + dy * dy) <
15)
{
_index++;
return;
}
}
x += vx;
y += vy;
}
}
else if (!_distrupt && _trees.length > 0 &&
_trees[_targetIndex]
!= null && _attackTimer >= _attackSpd)
{
_trees[_targetIndex].takeDmg(GameProperties.enemyDmg);
_attackTimer = 0;
if ((x - 30) - _trees[_targetIndex].x < 0)
_enemymc.play("attack_right");
else
_enemymc.play("attack_left");

Universitas Sumatera Utara

A-21

if (_trees[_targetIndex].health