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 var stats:Stats; private var starling:Starling; private var s:String;
private var 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(); }
(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":
(3)
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)
(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 {
(5)
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);
(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;(7)
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 - 1); var endX:int = Math.min(_grid.numCols - 1,
node.x + 1); var startY:int = Math.max(0, node.y - 1); var endY:int = Math.min(_grid.numRows - 1, node.y + 1);
for (var i:int = startX; i <= endX; i++) {
for (var j:int = startY; j <= endY; j++) {
var test:Node = _grid.getNode(i, j);
if (test == node || !test.walkable || !_grid.getNode(node.x, test.y).walkable || !_grid.getNode(test.x, node.y).walkable)
(8)
{
continue; }
var cost:Number = _straightCost; if (!((node.x == test.x) || (node.y == test.y)))
{
cost = _diagCost; continue;
}
var g:Number = node.g + cost; var h:Number = _heuristic(test); var f:Number = g + h;
if (isOpen(test) || isClosed(test)) {
if (test.f > f) {
test.f = f; test.g = g; test.h = h;
test.parent = node; if (GameProperties.showPath) { _searchPath.push(test); } } } else {
test.f = f; test.g = g; test.h = h;
test.parent = node; _open.push(test) if (GameProperties.showPath) { _searchPath.push(test); } } } }
for (var o:int = 0; o < _open.length; o++) {
}
_closed.push(node); if (_open.length == 0) {
trace("no path found"); return false
(9)
A-9
var index:uint = getShortestF();
node = _open[index] as Node;//as sama dengan cast
_open.splice(index, 1); //iii++;
}
buildPath();
trace("waktu awal :" + _time + " waktu akhir:" + getTimer() + " Operasi A* berhasil dilakukan dalam " + (getTimer() - _time) + " ms atau" + ((getTimer() - _time) / 1000) + " detik");
trace(getTimer());
trace("panjang pencarian:" + _searchPath.length); return true;
}
private function getShortestF():uint {
var f1:uint = _open[0].f; var f2:uint;
var index:uint=0;
for (var i:uint = 1; i < _open.length; i++) {
f2 = _open[i].f; if (f1 > 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)
(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;
(11)
A-11
public var _grounds:Vector.<Vector.<Image>>; 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();
(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;
(13)
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();
(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;
(15)
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 <= 3) {
_grid = new Grid(16, 7); //max level GameProperties.GameAreaH = 400; }
else {
_grid = new Grid(16, 9); GameProperties.GameAreaH = GameProperties.stageH;
}
//membuat node yang tidak bisa di lewati if (!GameProperties.developerMode)
var level:Array = GameProperties["level" + GameProperties.currentLevel];
for (var i:int = 0; i < _grid.numCols; i++) {
for (var j:int = 0; j < _grid.numRows; j++) {
(16)
if (GameProperties.developerMode) { break; } else {
if (level[j][i] == 1)
_grid.setWalkable(i, j, false); } } } drawGrid(); }
private function drawGrid():void {
_grounds = new Vector.<Vector.<Image>>(); for (var i:int = 0; i < _grid.numCols; i++) {
_grounds.push(new Vector.<Image>());
for (var j:int = 0; j < _grid.numRows; j++) {
var tile:Image = new
Image(Assets.getAtlas().getTexture("tile_" + Math.ceil(Math.random() * 6)));
tile.x = (i * _cellSize); tile.y = (j * _cellSize); addChild(tile);
_grounds[i][j] = tile;
if (!_grid.getNode(i, j).walkable) {
var block:Image = new Image(Assets.getAtlas().getTexture("stoneblock"));
block.x = (i * _cellSize); block.y = (j * _cellSize); addChild(block); } } } }
Enemy.as
package com.vuseon.guardiantree.objects { import com.greensock.easing.Expo; import com.vuseon.guardiantree.Assets; ... import starling.utils.Color; public class Enemy extends Sprite(17)
A-17
{
private var _xpos:uint; private var _ypos:uint; private var _game:InGame; private var _tree:Tree; ...
private var _myTimer:StarlingTimer; private var jj:uint = 0;
public function Enemy(game:InGame, grid:Grid, tree:Tree, cellSize:uint,
path:Array) {
_game = game; _grid = grid; ...
_myTimer = new StarlingTimer(Starling.juggler, 400, 0); }
private function onTouch(e:TouchEvent):void {
var touch:Touch = e.getTouch(stage);
if (touch !== null && touch.phase == TouchPhase.ENDED) {
if (GameStatistic.oxy > 0)
GameStatistic.addOxy(-10); takeDmg(5);
}
if (_health <= 0)
InGame._enemies.splice(InGame._enemies.indexOf(this), 1); }
public function findTarget(trees:Array):void {
if (trees.length > 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))
(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) { addEventListener(Event.ENTER_FRAME, enterFrame); _myTimer.removeEventListener(StarlingTimerEvent.TIMER, onTimerUpdate); _myTimer.stop(); return; } GameProperties.gameWorld._grounds[_path[jj].x][_path[jj].y].color = Color.GREEN; jj--;
(19)
A-19
} else {
GameProperties.gameWorld._grounds[_searchPath[ii].x][_searchPath[ii] .y].color = Color.GRAY;
ii++; }
}
private function findPath():void {
var astar:AStar = new AStar(); if (astar.findPath(_grid)) {
_path = astar.path; _index = 0;
addEventListener(Event.ENTER_FRAME, enterFrame); }
}
private function enterFrame(event:Event):void {
if (GameProperties.isPaused) return;
if (_index < _path.length) {
xpos = Math.floor(x / _cellSize); ypos = Math.floor(y / _cellSize);
var targetX:Number = _path[_index].x * _cellSize +
(_cellSize / 2);
var targetY:Number = _path[_index].y * _cellSize +
(_cellSize / 2); var dx:Number = targetX - x;
var dy:Number = targetY - y;
var dist:Number = Math.sqrt(dx * dx + dy * dy); var vx:Number;
var vy:Number; if (dx > 0) {
vx = _moveSpeed;
_enemymc.play("walk_right"); }
else if (dx < 0) {
vx = -_moveSpeed;
_enemymc.play("walk_left"); }
else {
(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
(21)
A-21
if (_trees[_targetIndex].health <= 0) {
_enemymc.stop();
_trees.splice(_trees.indexOf(_trees[_targetIndex]), 1);
_targetIndex = -1; GameProperties.gameWorld.changeEnemyTarget();
GameProperties.gameWorld.resetTileColor(); return;
} }
else if (_trees.length <= 0 && !_distrupt) {
_targetIndex = 0; _enemymc.stop();
removeEventListener(Event.ENTER_FRAME, enterFrame);
}
else if (_distrupt && _target != null && _attackTimer >=
_attackSpd) {
_enemymc.stop();
if ((x - 30) - _target.x < 0)
_enemymc.play("attack_right"); else
_enemymc.play("attack_left"); _target.takeDmg(GameProperties.enemyDmg); _attackTimer = 0;
//if(_trees[_targetIndex]==null) rem if (_target.health <= 0)
{
_distrupt = false;
_enemymc.stop();
InGame._heroes.splice(InGame._heroes.indexOf(_target), 1); _targetIndex = 0;
removeEventListener(Event.ENTER_FRAME, enterFrame); GameProperties.gameWorld.resetTileColor(); findTarget(_trees); } }
if (_attackTimer < _attackSpd) _attackTimer++;
}
public function changeTargets(value:Array, str:String):void {
if (!_distrupt) {
if (str == "tree")
(22)
{
_trees = value; }
if
(hasEventListener(EnterFrameEvent.ENTER_FRAME))
removeEventListener(Event.ENTER_FRAME, enterFrame);
findTarget(value); }
}
public function takeDmg(dmg:int):void {
addChild(new PopUpText(-25, -103, dmg, Color.RED)); _health -= dmg;
if (_healthBar) {
_healthBar.takeDamage(dmg); }
if (_health <= 0) {
destroy(); }
} }
(23)
B-1
CURRICULUM VITAE
Nama : Rahmat Irfan Pohan Tempat/Tanggal Lahir : Sisumut/ 19 Maret 1993 Jenis Kelamin : Laki-Laki
Tinggi/Berat Badan : 170 cm / 72 kg Agama : Islam
Kewarganegaraan : Indonesia
Alamat : Jl. Asrama/Ampera II no. 19 A Telp/ Hp : 082274376735
Email : r.irfanpohan@gmail.com
Riwayat Pendidikan
2011 – 2016 : S-1 Ilmu Komputer Universitas Sumatera Utara, Medan 2008 – 2011 : SMA Harapan 1 Medan
2005 – 2008 : SMP Harapan 2 Medan 1999 – 2005 : SD IKAL Medan 1997 – 1999 : TK IKAL Medan
Keahlian
Bahasa : Indonesia, Inggris
Bahasa Pemrograman : Java, Actionscript, C#.NET, PHP, JavaScript Database : Microsoft Access, Mysql, Microsoft SQL Design : Adobe Photoshop, Adobe Ilustrator
Pengalaman Organisasi
[2012 – 2013] Anggota RisTek BKM AL-KHUWARIZMI [2013 – 2014] Anggota Syiar UKMI AL-KHUWARIZMI [2013 – sekarang] Anggota Sobat Bumi Medan
[2013 – 2014] Anggota RisTek PEMA FASILKOM-TI
[2013 – 2015] Asisten Laboratory IKLC(Ilmu Komputer Laboratory Center) [2014 – 2015] Anggota Kemenlu PEMA USU
Pengalaman Kepanitiaan
[2011] Anggota Publikasi dan Dokumentasi ArTechno
[2011] Anggota Publikasi dan Dokumentasi Dies Natalis Ilmu Komputer [2011] Koordinator Publikasi dan Dokumentasi Hari Ibu
(24)
[2012] Anggota Humas Sahur on The Road
[2013] Anggota Publikasi dan Dokumentasi Porseni Imilkom 2013 [2013] Anggota Publikasi dan Dokumentasi Al-Khuwarizmi Festival [2013] Anggota Bidang Dana dan Usaha PORSENI IMILKOM 2013
[2013] Koordinator Publikasi dan Dokumentasi PMB S1 Ilmu Komputer 2013 [2014] Anggota Publikasi dan Dokumentasi PMB Fasilkom-TI 2013
[2014] Koordinator Peralatan, Tempat, dan Perlengkapan Penerimaan Beasiswa Sobat Bumi 2014
Pengalaman Kerja
[2011-sekarang] Freelancer Software Developer (Flash, Web, Mobile, Desktop) [2012-2014] Gitaris (Entertain) Parfi (Persatuan Artis Film Indonesia) SUMUT [2012-2014] Freelancer Graphic Designer
[2015-sekarang] Owner, Founder, Creative Director Noire Pomade [2015-sekarang] Direktur CV. Vuseon (Virtue Synergy Solution)
Pengalaman Pembicara
[2013] Pemateri Sosialisasi Sistem Informasi Akuntasi Koperasi Simpan Pinjam, Binjai
[2013-2014] Tentor Pelatihan Animasi Flash di Al-Khuwarizmi Academy, UKMI Al-Khuwarizmi Fasilkom-TI USU, Medan
[2013] Pemateri di Pelatihan Animasi Flash, Imilkom Goes To School, SMA Harapan Mandiri Medan
[2013] Pemateri Workshop Animasi Flash pada Penerimaan Mahasiswa Baru Muslim (PMBM) 2013, USU, Medan
[2014] Pemateri Sosialisasi Sistem Informasi Akuntasi Koperasi Simpan Pinjam, Rantau Prapat
[2014] Pemateri di Pelatihan Animasi Flash dalam Pengabdian di SMK Amal Bakri Lubuk Pakam
[2014] Pemateri di Pelatihan Animasi Flash, Imilkom Goes To School, SMA Negeri 1 Binjai, Binjai
[2014] Pemateri di Pelatihan Animasi Flash, Imilkom Goes To School, SMA Negeri 1 Medan, Medan
[2016] Narasumber dalam Temu Usaha Forum Bisnis Medan, Hotel Darma Deli, Medan
(25)
B-3
Prestasi
[2013] Juara II Kontes Programming Porseni Imilkom 2013 [2013] Penerima Beasiswa Pertamina Sobat Bumi
[2014] Finalis Telkomsel Digital Creative Innovation 2013 [2015] Finalis Gemastik 8 Kategori Bisnis Teknologi [2015] Finalis Big Idea Competition SEC USU 2016
[2016] Delegasi dari Indonesia Student ASEAN Entreprenur Entrepreneur Network 2016 (ASENET)
(26)
Daftar Pustaka
Apperley, T. H. 2006. Genre and Game Studies: Toward a Critical Approach to Video Game Genres. University of Melbourne: Melbourne.
Bondy, J.A., Murty, U.S.R. 2008. Graph Theory, Springer: London. Bose, J. 2013. Starling Game Development Essentials. Packt: Birmingham
Cui, Xiao & Shi, H. 2011. A* based pathfinding in modern computer games. IJCSNS International Journal of Computer Science and Network Security, VOL. 11 No. 1: 125-130
Delling, D., Sanders P., Schultes D. & Wagner, D. (2009). Algorithmics of Large and Complex Networks: Design, Analysis, and Simulation. Springer : Berlin
Enterprise, Jubilee. 2010. Step By Step Ponsel Android. PT Elex Media Komputindo: Jakarta
Imbert, T. 2012. Introducing Starling. O’Reilly Media: Sebastopol
Levitin, A. 2011. Introduction to Design and Analysis of Algorithm. Pearson : New Jersey
Munir, R. 2009. Matematika Diskrit. Informatika: Bandung
Munir, R. & Lidya, L. 1998. Algoritma dan Pemrogaman. Informatika: Bandung. Patel, A. 2010. The A* algorithm, heuristic for grid maps. (Online)
http://theory.stanford.edu/~amitp/GameProgramming/AStarComparison.html. Stanford University: Stanford (25 September 2015).
Peters, K. 2009. Advanced Actionscript 3.0 Animation. Apress : New York Rahayu, D. N. 2011. Penerapan algoritma A* (A Star) dalam pencarian jalan
terpendek pada game pathfinding. Skripsi. Universitas Komputer Indonesia. Sedgewick, Robert & Flajolet, P. 2013. Analysis of Algorithms Second Edition.
Pearson : New Jersey
Skiena, S. S. 2008. The Algorithm Design Manual. Departement of Computer Science State University:New York
Spuy, R. V. D . 2010. Game Design ActionScript 3. Apress: New York
Witanti, Wina & Dewi N. R. . 2013. Analisis pengaruh penggunaan nilai heuristik terhadap performansi algortima A*. Prosiding Seminar Nasional Sistem Informasi Indonesia (SESINDO 2013), pp. 505-509.
(27)
BAB III
ANALISIS DAN PERANCANGAN SISTEM
Berisi tentang uraian analisis mengenai proses kerja dari metode A*.
3.1 Analisis Sistem
Analisis sistem terdiri dari fase-fase berbeda yang mendeskripsikan pengembangan sistem. Dalam tugas akhir ini, ada tiga fase analisis yaitu: analisis masalah, analisis kebutuhan dan analisis proses. Analisis masalah bertujuan untuk memahami kelayakan masalah. Analisis kebutuhan dilakukan untuk menjelaskan fungsi-fungsi yang ditawarkan dan mampu dikerjakan sistem. Sedangkan analisis proses untuk memodelkan tingkah laku sistem.
3.1.1. Analisis Masalah
Saat ini Pathfinding (Pencarian jalan terdekat) telah dipakai di berbagai bidang Ilmu Komputer, salah satunya pada bidang Game Development (Pengembangan Video Game). Masalah utama dalam penelitiaan ini Bagaimana cara menerapkan algoritma Pathfinding A* untuk pembuatan AI (Artificial Intelligence) Musuh yang bisa menemukan jalan terdekatnya sendiri dari posisi awalnya menuju posisi pohon.
Masalah-masalah pada penelitian ini diidentifikasikan dengan menggunakan diagram Ishikawa. Diagram Ishikawa atau yang sering dikenal dengan Cause and Effect Diagram adalah diagram yang digunakan untuk memahami dan mengidentifikasi serta menggambarkan beberapa masalah yang terjadi pada sistem dan akibat yang ditimbulkan oleh masalah.
(28)
Permasalahan pada penelitian ini secara umum dapat ditunjukkan pada diagram Ishikawa gambar 3.1.
Gambar 3.1 Diagram Ishikawa
Pada gambar 3.1, dapat disimpulkan bahwa permasalahannya adalah muncul bagaimana cara objek musuh dapat mencari rute terdekat menuju pohon.
Solusi yang dapat ditawarkan adalah mencari rute terdekat dari posisi musuh ke posisi pohon dengan menggunakan algoritma A*.
3.1.2. Analisis Kebutuhan
Didalam analisis kebutuhan ini terdapat dua kebutuhan yaitu kebutuhan fungsional dan kebutuhan non fungsional.
3.1.2.1. Kebutuhan Fungsional
Kebutuhan fungsional adalah menjelaskan proses-proses aktifitas yang dapat dilakukan oleh sistem dalam melakukan pelayanan yang dilakukan sistem dan kebutuhan yang harus dipenuhi oleh sistem, yaitu:
1. Fungsi Pathfinding
Musuh dapat melakukan proses pencarian rute dari node awal ke node pohon. 3.1.2.2. Kebutuhan Non-Fungsional
Kebutuhan non-fungsional adalah mendeskripsikan fitur, karakteristik dan batasan lainnya seperti performa, penggunaan, model penyimpanan data, dokumentasi,
(29)
20
kontrol, dan ekonomi. Terdapat beberapa hal yang menjadi syarat kebutuhan non-fungsional antara lain:
1. Performa
Aplikasi yang dibangun dapat menampilkan hasil dari fungsi pathfinding yang dilakukan oleh sistem.
2. Mudah dipelajari dan digunakan
Aplikasi yang dibangun harus sederhana dan user friendly agar mudah digunakan dan dipelajari oleh pengguna.
3. Dokumentasi
Aplikasi yang akan dibangun memiliki panduan penggunaan aplikasi. 4. Kontrol
Aplikasi yang akan dibangun memiliki pesan error jika pengguna salah meletakkan objek pohon atau objek pelindung.
5. Ekonomi
Aplikasi yang dibangun tidak membutuhkan biaya dan perangkat tambahan. 3.1.3. Analisis Proses
Pada penelitian ini Aplikasi yang dibangun menggunakan algoritma A* Berbasis Pathfinding untuk melakukan proses pencarian rute terdekat.
3.2 Pemodelan
Pemodelan sistem dilakukan untuk menunjukkan dan mendeskripsikan gambaran dari sistem yang akan dibangun. Pada penelitian ini dilakukan pemodelan dengan menggunakan UML untuk mendesain serta merancang sistem.UML adalah bahasa yang digunakan untuk memberikan penjelasan mengenai komponen-komponen untuk membangun sistem dan interaksi antar komponen sistem. Model UML yang digunakan dalam penelitian ini antara lain adalah use case diagram, activity diagram serta sequance diagram.
3.2.1. Use-Case Diagram
Use-case Diagram adalah gambaran skenario penggunaan aplikasi sistem tentang bagaimana cara sistem bekerja dengan pengguna. Use-case Diagram membutuhkan identifikasi siapakah pengguna yang akan menggunakan sistem tersebut. Pengguna
(30)
tersebut dinamakan actor. Actor berperan untuk melakukan komunikasi dengan sistem. Hubungan antar actor dengan use-case dihubungkan dengan garis lurus. Sedangkan hubungan dimana satu use-case digunakan untuk meredudansi use-case lainnya digunakan garis putus-putus dengan keterangan include. Untuk extend digunakan untuk mensimplifikasi satu use-case dengan use-case lainnya
Gambar 3.2 Diagram Use-Case
Pada gambar 3.2
terdapat actor yang
mempunyai
peran yaitu sebagai
pemain. Actor
(pemain) meletakkan
objek pohon
terlebih dahulu.
Kemudian
musuh akan muncul
dan akan mencari rute
dari posisi awal
musuh menuju
(31)
22
Berikut ini merupakan tabel narrative use-case yang dapat dilihat pada tabel 3.1
Tabel 3.1 Narrative Use-Case Pathfinding A*
Use-case Name Pencarian Node Pohon
Design Scope Sistem (black box)
Goal Level Subfunction
Stakeholder and
Interest Musuh (AI) : dapat berjalan menuju pohon terdekat.
Precondition Pemain, Pohon, dan Pelindung
Minimal Guarantee Musuh akan diam ketika proses pencarian node gagal.
Success Guarantee
Musuh akan menuju ke node pohon terdekat
Trigger Pohon yang ditanam pemain
Main Succes Scenario
1. Musuh mencari rute untuk menuju node pohon terdekat
2. Musuh berjalan melalui rute yang berhasil dicari 3. Musuh menebang pohon
4. Musuh menyerang pelindung, bilamana musuh diserang pelindung
3.2.2. Sequence Diagram
Sequence Diagram berfungsi untuk menggambarkan rangkaian pesan yang akan dikirim antara object yang ada serta interaksi yang terjadi antar object. Berikut Sequence Diagram dari sistem yang dirancang dapat dilihat pada gambar 3.3 dan gambar 3.4.
(32)
:
Gambar 3.3 Diagram Sequence untuk proses Pathfinding A*
3.2.3. Activity Diagram
Pada Activity Diagram menggambarkan berbagai alur aktivitas yang ada di dalam sistem yang sedang dirancang dan bagaimana masing-masing alur yang ada berawal serta berakhir. Activity Diagram juga bertujuan untuk membantu bagaimana memahami proses dan menggambarkan setiap interaksi yang ada antara beberapa use case yang digunakan. Activity Diagram dari sistem dapat dilihat pada gambar 3.4.
(33)
24
Gambar 3.4 Activity Diagram Pathfinding A* 3.3. Flowchart Sistem
Flowchart merupakan diagram alir dari bagan-bagan tertentu yang memiliki arus penggambaran mengenai langkah-langkah penyelesaian suatu permasalahan. Selain itu, flowchart juga memiliki fungsi memudahkan proses pengecekan terhadap sistem yang akan dibuat.
3.3.1. Flowchart Sistem
(34)
Berikut merupakan flowchart dari sistem yang dibangun dapat dilihat pada gambar 3.5.
Gambar 3.5 Flowchart Sistem
(35)
26
Berikut adalah flowchart pathfinding dari sistem yang dibangun dapat dilihat pada gambar 3.6.
Gambar 3.6 Flowchart Pathfinding Algoritma A*
3.3.3. Flowchart Proses Game
Berikut adalah flowchart proses dari game yang dibangun dapat dilihat pada gambar 3.7
(36)
Gambar 3.7 Flowchart proses game. 3.4. Pseudocode Sistem
Pseudocode merupakan pendeskripsian dari algoritma pemrograman komputer yang ada dimana menggunakan struktur sederhana dari bahasa pemrograman yang
(37)
28
digunakan dan dapat dimengerti. Berikut merupakana pseudocode dari sistem yang dibangun.
3.4.1. Psuedocode Pathfinding A*
function A*(start, goal)
open_list = set containing start closed_list = empty set
start.g = 0
start.f = start.g + heuristic(start, goal) while current is not goal
current = open_list element with lowest f cost remove current from open_list
add current to closed_list for each neighbor of current if neighbor not in closed_list
neighbor.f = current.g + heuristic(neighbor, goal) if neighbor is not in open_list
add neighbor to open_list else
openneighbor = neighbor in open_list if neighbor.g < openneighbor.g
openneighbor.g = neighbor.g
openneighbor.parent = neighbor.parent if open_list is empty
return false
return backtrack_path(goal)
3.5. Perancangan Antarmuka
Perancangan antarmuka adalah desain awal dari tampilan sistem yang akan sistem bangun. Antarmuka harus dirancang dengan memperhatikan faktor pengguna sehingga sistem yang dibangun dapat memberikan kenyamanan dan kemudahan untuk digunakan oleh pengguna. Sistem yang dibangun terdiri dari form utama, form pilihan level, dan form game.
3.5.1 Form Utama
Form Utama adalah tampilan awal dari sistem ini dijalankan. Gambar 3.8 menunjukkan tampilan sementara dari form utama dan home.
(38)
Gambar 3.8 Rancangan Tampilan Form Utama
Keterangan:
1) Tombol Mulai, untuk memulai permainan dan pindah ke form berikutnya. 2) Tombol Bantuan, untuk menampilkan panduan cara memainkan game 3) Tombol Tentang, untuk menampilkan keterangan dan informasi game 4) Tombol Keluar, untuk keluar dari aplikasi game ini.
3.5.2 Form Pilihan Level
Pada halaman form pengirim ini, pemain dapat memilih level berdasarkan tingkat kesulitan permainan.Gambar 3.9 menunjukkan tampilan sementara dari form pilihan level.
(39)
30
Gambar 3.9 Rancangan Form Pilihan Level
Keterangan:
1) Pemain dapat memilih level sesuai keinginannya. 2) Level dibedakan atas tingkat kesulitan permainan.
3.5.3 Form Game
Form Game adalah halaman dimana pengguna dapat melakukan interaksi terhadap objek pada game. Pada form inilah proses pathfinding dioperasikan. Gambar 3.10 menunjukkan tampilan sementara dari form penerima.
Gambar 3.10 Rancangan Form Game
Keterangan:
1) Pemain harus meletakkan pohon terlebih dahulu, untuk memulai permainan 2) Pemain dapat bebas meletakkan pohon atau pelindung di area permainan yang
belum terisi oleh objek lain.
3) Musuh akan muncul jika terdapat pohon di area permainan, kemudian musuh melakukan operasi pathfinding untuk dapat mencari rute dari posis awal musuh menuju posisi pohon.
4) Score adalah hadiah yang diberikan game setelah pemain menanam pohon dan mengalahkan musuh
(40)
5) Waktu adalah waktu dalam detik untuk menunjukkan berapa lama pemain dapat bertahan pada game ini
6) Pause adalah tombol untuk memberhentikan permainan secara sementara.
7) Game akan berakhir bilamana tidak ada lagi pohon di area permainan. 8) Setelah game berakhir form akan pindah ke form pilihan level.
(41)
BAB IV
IMPLEMENTASI DAN PENGUJIAN
Pada bab ini dilakukan pembuatan sistem sesuai dengan analisis dan perancangan. Kemudian melakukan pengujian sistem
4.1 Implementasi
Dalam tugas akhir ini, program dibangun menggunakan bahasa pemrograman Actionscript 3. Program ini terdiri dari 5 form utama, yaitu: form main menu untuk menampilkan menu pada game ini, form pilihan level untuk memilih level game, form tentang untuk menampilkan informasi game, form game sebagai tempat berlangsungnya permainan dan interaksi antara pemain dengan objek pada game.
4.1.1 Form Main Menu
Form Main Menu merupakan form yang pertama muncul setelah animasi intro game ini. Pada form ini, terdapat tiga button untuk memulai menggunakan sistem ini.
Gambar 4.1 Form Main Menu
(42)
4.1.2 Form Pilihan Level
Form Pilihan Level merupakan form untuk memilih level. Pada form ini pemain dapat memilih level permainan.
Gambar 4.2 Form Pilihan Level
4.1.3 Form Game
Form Game merupakan form sebagai tempat berlangsungnya proses game dan interaksi dari pemain dengan objek game. Pada form ini pemain dapat meletakkan objek pohon dan objek pelindung. Di form ini juga terjadinya proses pathfinding pada objek musuh untuk mendapatkan rute perjalanan menuju objek pohon.
(43)
34
4.1.4 Form Bantuan
Form Bantuan digunakan sebagai panduan untuk cara memainkan video game ini.
Gambar 4.4 Form Bantuan
4.1.5 Form Tentang
Form Tentang berisikan tentang informasi tentang informasi game dan pengembang game (developer).
Gambar 4.5 Form Tentang.
(44)
4.2 Pengujian
4.2.1 Skenario Algoritma A*
Misalkan grid peta permainan berukuran 16x7 (Kolom x Baris) dalam bentuk matrix yang terdiri dari node-node objek game dan masing-masing objek tersebut memiliki identitas, yaitu tanah = “ “ (kosong), pohon = “T”, batu = “S”. Dimana terdapat 3 objek pohon yang terdapat dalam matrix. Dan musuh tidak dapat melangkahi batu. Matrix yang akan diuji, yaitu:
Gambar 4.6 Grid Permainan
Dan masing-masing posisi objek adalah (kolom,baris) : 1. Musuh E = (1,2)
2. Pohon T1 = (2,5)
3. Pohon T2 = (6,7)
4. Pohon T3 = (12,2)
Berikut adalah proses pathfinding dengan algoritma A*.
4.2.1.1 Searching
Proses ini bertujuan untuk mencari jalan ke pohon yang akan di tujuh oleh musuh. Dalam hal ini menggunakan persamaan . Berikut ini adalah langkah demi langkah proses pencarian node pohon, sebagai contoh pencarian node pohon T1.
(45)
36
Warna merah : unwalkable node (node yang tidak dapat dilalui) Warna kuning : current node (node sekarang)
Warna abu-abu : open node (node yang bisa dilalui) Warna orange : closed node (node yang sudah dilalui) Warna hijau : path (rute)
1.
2.
Gambar 4.7 Ilustrasi Proses Pathfinding A* ke- 1 dan 2
3.
(46)
4.
5.
Gambar 4.8 Ilustrasi Proses Pathfinding A* ke- 3 s.d. 5
6.
(47)
38
8.
Gambar 4.9 Ilustrasi Proses Pathfinding ke- 6 s.d. 8
9.
10.
(48)
11.
Gambar 4.10 Ilustrasi Proses Pathfinding A* ke- 9 s.d. 11
12.
(49)
40
14.
Gambar 4.11 Ilustrasi Proses Pathfinding A* ke-12 s.d. 14
15.
`16.
(50)
17.
Gambar 4.12 Ilustrasi Proses Pathfinding A* ke-15 s.d. 17
(51)
42
19.
20.
Gambar 4.13 Ilustrasi Proses Pathfinding A* ke-18 s.d. 20
21.
(52)
22.
23..
Gambar 4.14 Ilustrasi Proses Pathfinding A* ke-21 s.d. 23
(53)
44
25. .
26.
Gambar 4.15 Ilustrasi Proses Pathfinding A* ke-24 s.d. 26
27.
28.
(54)
29.
Gambar 4.16 Ilustrasi Proses Pathfinding A* ke-27 s.d. 29
30.
(55)
46
Proses searching akan berakhir, bila current node sama dengan goal node (node tujuan). Penjelasan proses searching dapat dilihat pada table 4.1.
Tabel 4.1 Proses Pathfinding Algoritma A*
n Current Node
Neighbour
Node g(n) h(n)
f(n)=
g(n)+h(n) Open Node Closed Node
Parent Node
1 (1,2)
(1,1) 1 11 12 (1,1);(1,3);(2,2 )
(1,2) -
(1,3) 1 9 10
(2,2) 1 9 10
2 (1,3) (1,4) 2 8 10 (1,1);(2,2);
(1,4);(2,3)
(1,2);(1,3)
(1,2)
(2,3) 2 8 10
3 (2,2)
(2,1) 2 8 10 (1,1);(1,4);(2,3 );
(2,1);(3,2)
(1,2);(1,3);(2,2
) (1,2)
(3,2) 2 8 10
4 (1,4)
(1,5) 3 7 10 (1,1);(2,3);(2,1 ); (3,2);(1,5);(2,4 ) (1,2);(1,3);(2,2 ); (1,4) (1,3)
(2,4) 3 7 10
5 (2,3) (3,3) 3 7 10
(1,1);(2,1);(3,2 ); (1,5);(2,4);(3,3 ) (1,2);(1,3);(2,2 ); (1,4);(2,3) (1,3)
6 (3,2) (4,2) - - -
(1,1);(2,1);(1,5 ); (2,4);(3,3) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ) (2,2)
7 (1,5)
(1,6) 4 6 10 (1,1);(2,1);(2,4 ); (3,3);(1,6); (2,5); (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5) (1,4)
(2,5) 4 6 10
(56)
8 (2,4) (3,4) 4 6 10 (1,1);(2,1);(3,3 ); (1,6);(2,5);(3,4 ) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4) (1,4)
9 (3,3) (4,3) 4 6 10
(1,1);(2,1);(1,6 ) (2,5);(3,4);(4,3 ) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ) (2,3)
10 (1,6)
(1,7) 5 5 10 (1,1);(2,1);(2,5 ); (3,4)(4,3);(1,7) ; (2,6) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6) (1,5)
(2,6) 5 5 10
11 (2,5) (3,5) 5 5 10
(1,1);(2,1);(3,4 ); (4,3);(1,7);(2,6 ); (3,5) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5) (1,5)
12 (3,4) (4,4) 5 5 10
(1,1);(2,1);(4,3 ); (1,7);(2,6);(3,5 ); (4,4); (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 (2,4)
(57)
48
)
13 (4,3) (5,3) - - -
(1,1);(2,1);(1,7 ); (2,6); (3,5);(4,4); (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 ); (4,3) (3,3)
14 (1,7) (2,7) 5 5 10
(1,1);(2,1);(2,6 ); (3,5);(4,4);(2,7 ); (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 ); (4,3);(1,7) (1,6)
15 (2,6) (3,6) 5 5 10
(1,1);(2,1); (3,5); (4,4);(2,7);(3,6 ) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 ); (4,3);(1,7);(2,6 ) (1,6)
16 (3,5) (4,5) - - -
(1,1);(2,1);(4,4 ); (2,7);(3,6); (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 (2,5)
(58)
); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 ); (4,3);(1,7);(2,6 ); (3,5)
17 (4,4) (5,4) 6 4 10
(1,1);(2,1);(2,7 ); (3,6);(5,4) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 ); (4,3);(1,7);(2,6 ); (3,5);(4,4) (3,4)
18 (2,7) (3,7) 7 3 10
(1,1);(2,1);(3,6 ); (5,4);(3,7) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 ); (4,3);(1,7);(2,6 ); (3,5);(4,4);(2,7 ) (1,7)
19 (3,6) (4,6) - - - (1,1);(2,1);(5,4
);
(1,2);(1,3);(2,2
(59)
50
(3,7) (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 ); (4,3);(1,7);(2,6 ); (3,5);(4,4);(2,7 ); (3,6)
20 (5,4)
(5,5) 7 3
10 (1,1);(2,1);(3,7 ); (5,5);(6,4) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 ); (4,3);(1,7);(2,6 ); (3,5);(4,4);(2,7 ); (3,6);(5,4) (4,4)
(6,4) 7 3 10
21 (3,7) (4,7) - - -
(1,1);(2,1);(5,5 ); (6,4) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 ); (4,3);(1,7);(2,6 (2,7)
(60)
);
(3,5);(4,4);(2,7 );
(3,6);(5,4);(3,7 )
22 (5,5)
(5,6) 8 2 10
(1,1);(2,1);(6,4 ); (5,6);(6,5) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 ); (4,3);(1,7);(2,6 ); (3,5);(4,4);(2,7 ); (3,6);(5,4);(3,7 ); (5,5) (5,4)
(6,5) 8 2 10
23 (6,4) (7,4) 8 4 12
(1,1);(2,1);(5,6 ); (6,5);(7,4) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 ); (4,3);(1,7);(2,6 ); (3,5);(4,4);(2,7 ); (3,6);(5,4);(3,7 (5,4)
(61)
52
);
(5,5);(6,4)
24 (5,6)
(5,7) 9 1 10
(1,1);(2,1);(6,5 ); (7,4);(5,7);(6,6 ) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 ); (4,3);(1,7);(2,6 ); (3,5);(4,4);(2,7 ); (3,6);(5,4);(3,7 ); (5,5);(6,4);(5,6 ) (5,5)
(6,6) 9 1 10
25 (6,5) (7,5) 9 3 12
(1,1);(2,1);(7,4 ); (5,7);(6,6);(7,5 ) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 ); (4,3);(1,7);(2,6 ); (3,5);(4,4);(2,7 ); (3,6);(5,4);(3,7 ); (5,5);(6,4);(5,6 (5,5)
(62)
); (6,5)
26 (5,7) (6,7) 10 0 10
(1,1);(2,1);(7,4 ); (6,6);(7,5);(6,7 ) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 ); (4,3);(1,7);(2,6 ); (3,5);(4,4);(2,7 ); (3,6);(5,4);(3,7 ); (5,5);(6,4);(5,6 ); (6,5);(5,7) (5,6)
27 (6,6) (7,6) 10 2 12
(1,1);(2,1);(7,4 ); (7,5);(6,7);(7,6 ) (1,2);(1,3);(2,2 ); (1,4);(2,3);(3,2 ); (1,5);(2,4);(3,3 ); (1,6);(2,5);(3,4 ); (4,3);(1,7);(2,6 ); (3,5);(4,4);(2,7 ); (3,6);(5,4);(3,7 ); (5,6)
(63)
54
(5,5);(6,4);(5,6 );
(6,5);(5,7);(6,6 )
28 (6,7) - - - - (5,7)
4.2.1.2 Backtracking
Setelah goal node didapat, maka proses selanjutnya yaitu backtracking. Proses bracktracking bertujuan untuk memetakan rute yang akan dilalui dengan cara memanggil satu per-satu parent node (node induk) dimulai dari memanggil parent node goal node hingga parent node start node (node awal). Proses backtracking berhenti bila parent node merupakan node awal.
Gambar 4.18 Proses Backtracking
Berikut adalah rute yang dihasilkan dari proses backtracking, dapat dilihat pada gambar 4.19.
(64)
Gambar 4.19 Sebelum proses backtracking (a), sesudah proses backtracking (b)
4.2.1.3 Rute Pohon Terdekat
Untuk mengetahui pohon mana yang akan di tuju duluan oleh musuh, maka musuh harus mencari setiap rute masing-masing pohon. Dengan cara di atas, maka hasil dari pencarian rute dari musuh ke masing-masing pohon adalah
a. E terhadap T1, memiliki 18 langkah.
b.
Gambar 4.20 Rute Musuh menuju Pohon T1
(65)
56
Gambar 4.21 Rute Musuh menuju Pohon T2 d. E terhadap T3 memiliki 15 langkah
(66)
e.
Gambar 4.22 Rute Musuh menuju Pohon T3
Dari proses pencarian goal node pada masing-masing pohon di atas, kemudian dibandingkan panjang rute dari start node. Perbandingan panjang rute ke masing-masing pohon dapat dilihat pada table 4.2.
Tabel 4.2 Heuristik Manhattan Distance
Ex Ey Tx Ty dx=[Tx-Ex] dy=[Ty-Ey] h=dx+dy Panjang Rute
1 2 5 2 4 0 4 18
1 2 6 7 5 5 10 10
1 2 12 2 11 0 11 15
Berdasarkan tabel 4.2 maka pohon yang memiliki rute terpendek adalah pohon T2 dengan jarak estimasi (heuristik) sebesar 10.
(67)
58
Pengujian ini dilakukan untuk mengetahui pengaruh banyak penghalang terhadap banyak node yang dikunjungi, pengaruh banyak node yang dikunjungi terhadap rute, dan pengaruh banyak node yang dikunjungi dan panjang rute terhadap waktu dengan start node dan goal node yang berbeda.
Tabel 4.3. Banyak Node yang Dikunjungi terhadap Banyak Penghalang
NO Start Node (kolom,baris)
Goal Node (kolom,baris)
Banyak Penghalang
Banyak node yang dikunjungi
1. (1,2) (6,7) 20 40
2. (1,2) (12,2) 20 49
3. (1,2) (2,5) 20 69
4. (1,1) (1,7) 45 112
5. (1,9) (16,16) 60 144
Berdasarkan tabel 4.3 dapat dapat dilihat grafik yang terdapat pada gambar 4.23 yaitu pengaruh banyak node yang dikunjungi terhadap banyak penghalang berbeda.
Gambar 4.23 Grafik Banyak Node Dikunjungi terhadap Banyak Penghalang
Berdasarkan grafik pada gambar 4.23 dapat diinformasikan bahwa semakin banyak penghalang (node yang tidak dapat dilalui) maka semakin banyak node yang dikunjungi untuk sampai ke goal node.
(68)
Tabel 4.4. Banyak Node Dikunjungi terhadap Panjang rute
NO Start Node (kolom,baris)
Goal Node (kolom,baris)
Banyak node yang dikunjungi
Panjang Rute
1. (1,2) (6,7) 40 10
2. (1,2) (12,2) 49 15
3. (1,2) (2,5) 69 18
4. (1,1) (1,7) 112 67
5. (1,9) (16,16) 144 84
Berdasarkan tabel 4.4 dapat dapat dilihat grafik yang terdapat pada gambar 4.24 yaitu pengaruh banyak node yang dikunjungi terhadap panjang rute.
Gambar 4.24 Grafik Pengaruh Panjang Rute terhadap Banyak Node yang Dikunjungi
Berdasarkan grafik pada gambar 4.24 dapat diinformasikan bahwa semakin banyak banyak node yang dikunjungi maka semakin panjang rute untuk sampai ke goal node.
Tabel 4.5 Pengaruh Banyak Node Penghalang, Banyak Node yang Dikunjungi dan Panjang Rute terhadap Waktu
NO Start Node (kolom,baris)
Goal Node (kolom,baris)
Banyak Penghalang
Banyak node yang dikunjungi
Panjang Rute
Waktu (detik)
(69)
60
1. (1,2) (6,7) 20 40 10 0,004
2. (1,2) (12,2) 20 49 15 0,007
3. (1,2) (2,5) 20 69 18 0,009
4. (1,1) (1,7) 45 112 67 0,015
5. (1,9) (16,16) 60 144 84 0,016
Berdasarkan tabel 4.5 dapat dapat dilihat grafik yang terdapat pada gambar 4.25 yaitu pengaruh banyak penghalang, banyak node yang dikunjungi dan panjang rute terhadap waktu dalam melakukan proses pathfinding. Waktu pada proses pathfinding A* akan berubah sesuai dengan spesifikasi dan performa hardware dimana aplikasi tersebut diuji.
Gambar 4.25 Grafik Pengaruh Banyak Node Pengahalang, Banyak Node yang Dikunjungi dan Panjang Rute terhadap Waktu
(70)
Berdasarkan grafik pada gambar 4.25 dapat diinformasikan bahwa semakin banyak penghalang (node yang tidak dapat dilalui), semakin banyak node yang dikunjungi, dan semakin panjang rute. maka sistem memerlukan waktu yang lebih lama untuk
(71)
BAB V
KESIMPULAN DAN SARAN 5.1 Kesimpulan
Berdasarkan pembahasan dan hasil dari penelitian, maka diperoleh beberapa kesimpulan sebagai berikut:
1. Pada penelitian ini perbandingan banyak node yang dikunjungi berbanding lurus dengan panjang rute, dan waktu proses pathfinding A*.
2. Semakin banyak jumlah objek penghalang / unwalkable node (node yang tidak dapat dilalui) maka semakin banyak pula node yang dikunjungi.
3. Semakin banyak jumlah objek penghalang / unwalkable node (node yang tidak dapat dilalui) maka waktu yang dibutuhkan untuk melakukan proses pencarian rute dari node objek musuh menuju node objek pohon akan semakin lama.
(72)
4.
5.2 Saran
Berikut ini adalah saran yang dapat digunakan untuk tahap pengembangan penelitian sistem ini antara lain:
1. Di dalam penelitian ini pathfinding algortima A* digunakan pada game berbasis grid based (menggunakan grid) sehingga pergerakkan musuh dapat mudah di tebak, diharapkan kedepannya game tidak hanya dikembangkan dengan konsep grid based saja.
2. Di dalam penelitian ini pathfinding algortima A* menggunakan heuristik Manhattan Distance, yang hanya bisa melakukan pergerakkan 4 arah. Diharapkan kedepannya dapat menggunakan heuristik yang lain sehingga dapat melakukan pergerakkan lebih dari 4 arah.
3. Di dalam penelitiaan ini pathfinding diimplementasikan pada pengembangan game dua dimensi. Diharapkan kedepannya pathfinding dapat diimplementasikan pada pengembangan game tiga dimensi.
(73)
BAB II
TINJAUAN PUSTAKA
Bab ini akan menjelaskan tentang pembahasan teori-teori algoritma A*.
2.1. Video Game
Video game (permainan video) adalah permainan yang menggunakan interaksi dengan antarmuka pengguna melalui gambar yang dihasilkan oleh piranti video. Permainan video umumnya menyediakan sistem penghargaan misalnya skor yang dihitung berdasarkan tingkat keberhasilan yang dicapai dalam menyelesaikan tugas-tugas yang ada di dalam permainan.
Kata "video" pada "permainan video" pada awalnya merujuk pada piranti tampilan raster. Namun dengan semakin dipakainya istilah "video game", kini kata permainan video dapat digunakan untuk menyebut permainan pada piranti tampilan apapun. Sistem elektronik yang digunakan untuk menjalankan permainan video disebut platform, contohnya adalah komputer, permainan konsol dan smartphone. (Apperley, 2006)
2.2. Desain Analisis Algoritma
Desain Analisis Algoritma merupakan suatu cabang khusus dalam ilmu komputer yang mempelajari karakteristik dan performa dari suatu algoritma dalam menyelesaikan masalah (Levitin, 2011). Untuk menganalisis sebuah algoritma, kita harus mengidentifikasi sumber primer sehingga analisis rinci dapat difokuskan dengan benar. Sebuah analisis lengkap dari waktu berjalan dari algoritma melibatkan langkah-langkah berikut:
1. Melaksanakan algoritma sepenuhnya.
2. Tentukan waktu yang dibutuhkan untuk setiap operasi dasar. Mengidentifikasi jumlah yang tidak diketahui yang dapat digunakan untuk menggambarkan frekuensi pelaksanaan operasi dasar.
3. Mengembangkan model yang realistis untuk input ke program.
4. Menganalisis jumlah yang tidak diketahui, dengan asumsi input yang dimodelkan.
(74)
5. Hitung total waktu berjalan dengan mengalikan waktu dengan frekuensi untuk setiap operasi, kemudian menambahkan semua produk.
Langkah pertama dalam analisis ini adalah untuk hati-hati menerapkan algoritma pada komputer tertentu. Sebuah implementasi tertentu tidak hanya menyediakan objek konkret untuk belajar, tetapi juga dapat memberikan data empiris yang berguna untuk membantu dalam atau untuk memeriksa analisis.
Langkah berikutnya adalah untuk memperkirakan waktu yang dibutuhkan oleh masing-masing instruksi komponen program. Pendekatan lain adalah dengan hanya menjalankan program untuk input kecil ukuran untuk "estimasi" nilai-nilai konstanta, atau untuk melakukannya secara tidak langsung dalam agregat.
Langkah berikutnya adalah untuk model input ke program, untuk membentuk dasar untuk analisis matematis dari frekuensi instruksi. Nilai dari frekuensi diketahui tergantung pada masukan untuk algoritma: masalah ukuran parameter utama yang digunakan untuk mengungkapkan hasil (Sedgewick, 2013).
2.3. Teori Graf
terhubung oleh sisi (edge) atau busur (arc). Biasanya graf digambarkan sebagai kumpulan titik-titik (melambangkan "simpul") yang dihubungkan oleh garis-garis (melambangkan "sisi") atau garis berpanah (melambangkan "busur"). Suatu sisi dapat menghubungkan suatu simpul dengan simpul yang sama. Sisi yang demikian
dinamakan 2.4. Jenis-Jenis Graf
Jenis graf dibedakan atas 3 karakteristik yaitu, berdasarkan sisi ganda (berdasarkan ada tidaknya suatu gelang), arah (berdasarkan arah dari sisi) , dan berdasarkan pada bobot sisinya (Bondy, 2008).
(75)
8
2.4.1.Berdasarkan sisi ganda
Berdasarkan ada tidaknya gelang atau sisi ganda pada suatu graf, maka secara umum graf dapat digolongkan menjadi dua jenis:
1. Graf sederhana, graf yang tidak mengandung gelang maupun sisi ganda dinamakan graf sederhana.
2. Graf tak-sederhana, graf yang mengandung sisi ganda dinamakan graf tak- sederhana. Ada dua macam graf tak sederhana, yaitu graf ganda dan graf semu. Graf ganda adalah graf yang mengandung sisi ganda. Sebuah graf memiliki sisi ganda jika ada 2 buah simpulyang dihubungkan lebih dari satu sisi. Graf semu adalah graf yang memiliki sisi gelang (loop). Sisi gelang adalah sisi yang menghubungkan sebuah simpul dengan simpul itu sendiri.
Gambar 2.1 Graf sederhana(G1), Graf Ganda (G2), Graf Semu(G3) (Munir, 2009)
2.4.2.Berdasarkan arah
Berdasarkan arah dari sisi, graf dibedakan menjadi 2 jenis : 1. Graf tak-berarah
Graf yang sisinya tidak memiliki orientasi arah disebut graf tak-berarah. Pada graf tak-berarah, urutan pasangan simpul pada sisi tidak diperhatikan. Sebuah sisi e = (u, v) sama dengan e = (v, u).
Gambar 2.2 Graf tidak berarah (Munir, 2009)
(76)
2. Graf Berarah
Graf yang setiap sisinya memiliki orientasi arah disebuh graf berarah. Pada graf berarah, sebuah sisi dikenal juga sebagai busur (arc). Pada graf berarah, (u, v) dan (v, u) menyatakan dua buah sisi yang berbeda. Pada sebuah sisi (u, v), simpul u menyatakan simpul asal (initial vertex) dan simpul v menyatakan simpul terminal (terminal vertex).
Gambar 2.3 Graf berarah (Munir, 2009)
2.4.3.Berdasarkan bobot
1. Graf berbobot (weighted graph)
Graf berbobot adalah graf yang setiap sisinya memiliki bobot. Bobot pada sisi graf dapat merepresentasikan kapasitas, biaya, atau keuntungan.
Gambar 2.4. Graf berbobot (Munir, 2009)
2. Graf tak-berbobot (unweighted graph)
Graf tak-berbobot adalah graf yang setiap sisinya tidak memiliki bobot.
(77)
10
2.5.Pathfinding
Pathfinding adalah suatu metode yang digunakan untuk pencarian jalur yang bertujuan untuk mencapai suatu tempat tujuan dari tempat awal. Cara kerja metode pathfinding adalah dengan mencari sebuah grafik dengan memulai pada satu titik dan menjelajahi node yang berdekatan sampai node tujuan tercapai, umumnya dengan maksud untuk menemukan rute terpendek. Namun, tidak perlu untuk memeriksa semua jalur yang mungkin untuk menemukan satu yang optimal. Dalam sistem-perjalanan routing yang praktis, kompleksitas waktu yang lebih baik dapat dicapai dengan algoritma yang dapat pra-proses grafik untuk mencapai kinerja yang lebih baik. (Deiling, 2009).
2.6. Algoritma A*
Algoritma A* adalah pengembangan dari algoritma Djikstra yaitu suatu algoritma yang bertujuan untuk memproses perencanaan jalur yang efisien di antara beberapa titik (node) dengan menggunakan heuristik. Peter Hart, Nils Nilsson dan Bertram Raphael dari Stanford Research Institute memperkenalkan algoritma ini pada tahun 1968 (Deiling, 2009).
A* menggunakan pencarian terbaik pertama dan menemukan jalan dengan biaya terendah dari node awal yang diberikan ke satu node tujuan. A* melintasi grafik untuk membangun sebuah pohon jalur parsial. Daun pohon ini (disebut set atau pinggiran terbuka) disimpan dalam antrian prioritas yang memerintahkan node daun dengan fungsi biaya, yang menggabungkan perkiraan heuristik dari biaya untuk mencapai tujuan dan jarak yang ditempuh dari node awal. Secara khusus, fungsi biaya:
f (n) = g (n) + h (n).
Di sini, g (n) adalah biaya diketahui mendapatkan dari node awal untuk nilai ini dilacak oleh algoritma. h (n) adalah perkiraan heuristik dari biaya untuk mendapatkan dari n ke setiap node tujuan. Untuk algoritma untuk menemukan jalur terpendek yang sebenarnya, fungsi heuristik harus diterima, artinya tidak pernah overestimates biaya yang sebenarnya untuk sampai ke node tujuan terdekat. Fungsi heuristik adalah spesifik masalah dan harus disediakan oleh pengguna dari algoritma.
Beberapa terminologi dasar yang terdapat pada algoritma A* adalah starting point, simpul (nodes), open list, closed list, harga (cost), halangan (unwalkable).
(78)
Starting point adalah sebuah terminologi untuk posisi awal sebuah benda. Simpul adalah petak-petak kecil sebagai representasi dari area pathfinding. Bentuknya dapat berupa persegi, lingkaran, maupun segitiga. Open list adalah tempat menyimpan data simpul yang mungkin diakses dari starting point maupun simpul yang sedang dijalankan. Closed list adalah tempat menyimpan data simpul sebelum A yang juga merupakan bagian dari jalur terpendek yang telah berhasil didapatkan. Simpul tujuan yaitu simpul yang dituju. Halangan adalah sebuah atribut yang menyatakan bahwa sebuah simpul tidak dapat dilalui oleh A. Prinsip algoritma ini adalah mencari jalur terpendek dari sebuah starting point menuju simpul tujuan dengan memperhatikan harga (F) terkecil (Munir, 1998).
2.6.1 Cara Kerja
Dimulai dengan node awal, ia mempertahankan antrian prioritas node yang akan dilalui, dikenal sebagai set atau pinggiran terbuka. Semakin rendah f (x) untuk diberikan simpul x, semakin tinggi prioritas. Pada setiap langkah algoritma, node dengan f (x) nilai terendah akan dihapus dari antrian, f dan g nilai tetangganya diperbarui sesuai, dan tetangga ini ditambahkan ke antrian. Algoritma terus sampai node tujuan memiliki nilai f rendah dari setiap node dalam antrian (atau sampai antrian kosong). (Node Goal dapat melewati beberapa kali jika masih ada node lain dengan nilai f yang lebih rendah, karena dapat menyebabkan jalan yang lebih pendek untuk tujuan.) Nilai f dari tujuannya adalah maka panjang jalur terpendek, karena jam pada tujuannya adalah nol dalam heuristik diterima.
Algoritma yang dijelaskan sejauh memberi kita hanya panjang jalur terpendek. Untuk menemukan urutan yang sebenarnya dari langkah-langkah, algoritma dapat dengan mudah direvisi sehingga setiap node di jalan melacak pendahulunya. Setelah algoritma ini dijalankan, node berakhir akan mengarah ke pendahulunya, dan seterusnya, sampai pendahulunya beberapa node adalah node awal.Selain itu, jika heuristik yang monoton (atau konsisten, lihat di bawah), satu set tertutup node sudah dilalui dapat digunakan untuk membuat pencarian lebih efisien. (Deiling, 2009).
(79)
12
2.6.2. Sifat Algoritma A*
A* selesai dan akan selalu mencari solusi jika ada. Jika heuristik fungsi h adalah diterima, artinya tidak pernah overestimates biaya minimal sebenarnya mencapai tujuan, maka A* itu sendiri diterima (atau optimal) jika kita tidak menggunakan satu set tertutup. Jika satu set tertutup digunakan, maka h juga harus monoton (atau konsisten) untuk A* menjadi optimal. Ini berarti bahwa untuk setiap pasangan node yang berdekatan x dan y, di mana d (x, y) menunjukkan panjang dari tepi antara mereka, kita harus memiliki:
Hal ini memastikan bahwa untuk setiap jalur X dari node awal untuk x:
dimana L adalah fungsi yang menunjukkan panjang jalan, dan Y adalah jalan X diperluas untuk mencakup y. Dengan kata lain, tidak mungkin untuk menurunkan (total jarak sejauh + diperkirakan jarak yang tersisa) dengan memperluas jalan untuk memasukkan node tetangga. (Ini analog dengan pembatasan untuk nonnegatif tepi bobot dalam algoritma Dijkstra.) Monotonisitas berarti diterimanya ketika estimasi heuristik setiap node tujuan itu sendiri adalah nol, karena (membiarkan P = (f, v1, v2, ..., vn, g ) menjadi jalur terpendek dari setiap node f ke terdekat g tujuan):
A* juga optimal efisien untuk setiap heuristik h, yang berarti bahwa tidak ada algoritma optimal mempekerjakan heuristik yang sama akan memperluas node kurang dari A*, kecuali jika ada solusi parsial beberapa di mana h persis memprediksi biaya jalur yang optimal. Bahkan dalam kasus ini, untuk setiap grafik terdapat beberapa urutan hubungan melanggar dalam antrian prioritas sehingga A* memeriksa node paling sedikit mungkin (Deiling, 2009).
2.7. Heuristik
Heuristik adalah fungsi optimasi pada algoritma A* dengan cara memberi nilai pada tiap simpul yang memandu A* mendapatkan solusi yang diinginkan. Dengan heuristik, maka A* pasti akan mendapatkan solusi (jika memang ada solusinya). Heuristik
(80)
inilah yang membedakan algoritma A* dengan algoritma pathfinding lainnya. Heuristik dapat digunakan untuk mengontrol perilaku A*.
Pada satu ekstrim, jika h (n) adalah 0, maka hanya g (n) memainkan peran, dan A* berubah menjadi Algoritma Dijkstra, yang dijamin untuk menemukan jalan terpendek.
Jika h (n) selalu lebih rendah dari (atau sama dengan) biaya pindah dari n ke tujuan, maka A* dijamin untuk menemukan jalan terpendek. Lebih rendah h (n), semakin simpul A* mengembang, membuatnya lebih lambat.
Jika h (n) adalah persis sama dengan biaya pindah dari n ke tujuan, maka A* hanya akan mengikuti jalan terbaik dan tidak pernah memperluas apa pun, sehingga sangat cepat.
Jika h (n) kadang-kadang lebih besar dari biaya bergerak dari n ke tujuan, maka A* tidak dijamin untuk menemukan jalur terpendek, tetapi dapat berjalan lebih cepat.
Pada ekstrem yang lain, jika h (n) relatif sangat tinggi untuk g (n), maka hanya h (n) memainkan peran, dan A* berubah menjadi Greedy Best-First-Search.
Heuristik pada Algoritma A* memilki beberapa jenis dibedakan berdasarkan berapa arah yang digunakan, yaitu heuristik Manhattan Distance, Diagona l Distance, dan Euclidian Distance (Peters, 2009)
2.7.1 Manhattan Distance
Manhattan Distance adalah Heuristik standar pada peta grid yang memperkenankan 4 arah gerakan. Fungsi biaya dan menemukan minimum biaya D untuk bergerak dari satu ruang ke ruang yang berdekatan. Dalam kasus sederhana, Anda dapat mengatur D menjadi 1. Heuristik pada grid persegi D kali jarak Manhattan, yaitu :
function heuristik(node) {
dx = abs(node.x - goal.x) dy = abs(node.y - goal.y) return D * (dx + dy) }
(81)
14
Cara memilih nilai D adalah gunakan skala yang cocok dengan bobot fungsi. Untuk jalur terbaik, ubah nilai D menjadi bobot terendah diantara petak yang berdekatan (Patel, 2010).
Gambar 2.6. Ilustrasi Manhattan Distance (Patel, 2010).
2.7.2. Diagonal Distance
Diagonal Distance adalah Heuristik pada peta grid yang memungkinkan gerakan diagonal. Jika Manhatan Distance membutuhkan gerakan 4 timur dan 4 utara (8 gerakan) untuk mencapai target, menjadi 8*D.
Namun, pada diagonal distance hanya membutuhkan 4 gerakan (4 timur laut) untuk mencapai target, sehingga heuristik menjadi 4 * D2, di mana D2 adalah biaya bergerak diagonal.
Gambar 2.7. Ilustrasi Heuristik Diagonal Distance (Patel, 2010).
function heuristik(node) { dx = abs(node.x - goal.x) dy = abs(node.y - goal.y)
return D * (dx + dy) + (D2 - 2 * D) * min(dx, dy) }
(82)
Di sini menghitung jumlah langkah yang diambil tidak dapat mengambil diagonal, kemudian kurangi langkah-langkah yang disimpan dengan menggunakan diagonal. Ada min (dx, dy) langkah diagonal, dan masing-masing biaya D2 tapi menghemat 2*D langkah non-diagonal. Ketika D = 1 dan D2 = 1, ini disebut jarak Chebyshev. Ketika D = 1 dan D2 = sqrt (2), ini disebut jarak octile (Patel, 2010).
2.7.3 Euclidian Distance
Jika unit dapat bergerak di setiap sudut (bukan arah grid), maka harus menggunakan jarak garis lurus:
Namun, jika hal ini terjadi, maka memiliki masalah dengan menggunakan A* langsung karena fungsi biaya g tidak akan cocok dengan heuristik fungsi h. Karena jarak Euclidean lebih pendek dari Manhattan atau jarak diagona masih akan mendapatkan jalur terpendek, tetapi A* akan memakan waktu lebih lama untuk menjalankan (Patel, 2010).
Gambar 2.8 Ilustrasi Heuristik Euclidian (Patel, 2010).
2.8.Android
Android merupakan sistem operasi mobile berbasis kernel linux yang dikembangkan oleh Android Inc dan kemudian diakusisi oleh Google. Sistem operasi ini bersifat open source sehingga para programmer dapat membuat aplikasi secara mudah. Salah satu keunggulan Android terletak pada bervariasinya merek ponsel yang mengadopsi sistem operasi ini. Oleh karena itu, tidak heran jika kita melihat beragam merek ponsel menggunakan sistem operasi ini, seperti HTC, Samsung, dan lain sebagainya. Google pun juga merilis ponsel dengan nama Google Nexus One. Fenomena ini tentu
function heuristik (node) { dx = abs (node.x - goal.x) dy = abs (node.y - goal.y)
return D * sqrt (dx * dx + dy * dy) }
(83)
16
mengakibatkan kita sebagai konsumen memliki banyak pilihan dalam menggunakan ponsel bersistem operasi Android. Tidak sama dengan iPhone yang bentuk persis untuk setiap seri atau Blacberry yang jumlahnya terbatas, ponsel berbasis Android memilik banyak bentuk dan merek (Jubille, 2010).
2.9.Actionscript 3.0
ActionScript adalah bahasa pemrograman berorientasi objek awalnya dikembangkan oleh Macromedia Inc (sekarang diakusisi oleh Adobe Systems). Ini adalah derivasi dari HyperTalk, bahasa scripting untuk HyperCard. Sekarang dialek dari ECMAScript (artinya itu adalah superset dari sintaks dan semantik dari bahasa lebih banyak dikenal sebagai JavaScript), meskipun awalnya muncul sebagai saudara, baik yang dipengaruhi oleh HyperTalk.
ActionScript 3 juga digunakan dengan sistem Adobe AIR untuk pengembangan desktop dan aplikasi mobile. Bahasa itu sendiri adalah open source dalam spesifikasi yang ditawarkan gratis dan kedua kompiler open source (sebagai bagian dari Adobe Flex) dan mesin virtual open source (Mozilla Tamarin) yang tersedia (Spuy, 2010).
2.10. Framework Starling
Starling adalah Framework Actionscript 3 dikembangkan di atas Stage3D API (Application Programming Interface). Starling dirancang untuk pengembangan game, tapi bisa digunakan untuk banyak kasus penggunaan lainnya. Starling memungkinkan untuk menulis aplikasi GPU(Graphic Processing Unit)-accelerated tanpa harus menyentuh level rendah Stage3D API. Kebanyakan pengembang Adobe AIR ingin dapat memanfaatkan akselerasi GPU tanpa perlu menulis framework yang lebih tinggi. (Imbert, 2012).
Starling dikembangkan untuk pengembang ActionScript 3, terutama mereka yang terlibat dalam pengembangan game 2D, sehingga perlu memiliki pemahaman dasar tentang ActionScript 3. Dengan desain ringan, fleksibel, dan sederhana. Starling juga digunakan untuk kasus penggunaan lain seperti pemrograman UI(User Interface). (Bose, 2013).
(84)
3. Penelitian yang Relevan
Berikut ini beberapa penelitian tentang desain analisis dan algoritma yang berkaitan dengan Algoritma A*.
No Nama/Tahun Judul Hasil Penelitian
1. Witanti, Wina, (2013)
Analisis pengaruh penggunaan nilai Heuristik Terhadap Performansi
Algortima A*
Nilai heuristik berpengaruh terhadap performa algoritma A* dalam mencari rute terdekat [15].
2. Cui, Xiao & Shi, H
(2011)
A*based Pathfinding in Modern Computer Games
Cara untuk mengoptimalkan performa pencarian A* adalah dengan meningkatkan fungsi heuristik [4].
3. Rahayu, D. N (2011)
Optimasi Rute Perjalanan Ambulance Menggunakan Algoritma A-Star
Lamanya proses pencarian dan banyaknya simpul yang diperiksa untuk pencarian jalan tergantung pada jarak antara titik awal dan titik tujuan [12].
(85)
A-1
BAB I PENDAHULUAN
Bab ini akan menjelaskan mengenai latar belakang penelitian judul skripsi “Implementasi algoritma A* berbasis pathfinding dalam pengembangan game menanam pohon”.
1.1. Latar Belakang
Perkembangan ilmu pengetahuan dapat dirasakan dalam berbagai bidang di kehidupan manusia. Perkembangan ilmu pengetahuan juga memicu tumbuhnya teknologi. Perkembangan teknologi ini juga mempengaruhi industri hiburan khususnya dibidang permainan. Dari pesatnya berkembangan pengetahuan dan teknologi, kini permainan dapat dikembangkan ke dalam bentuk digital (video game) yang dapat dimainkan dimana saja.
Pathfinding (Pencarian jalan terdekat) telah dipakai di berbagai bidang ilmu komputer, salah satunya pada bidang game development (pengembangan video game) untuk membuat pergerakan objek dari tempat awal ke tempat tujuan. Seiring perkembangan video game, semakin populer juga pathfinding digunakan di berbagai jenis game, seperti tile based video game. Pathfinding adalah bagaimana mencari rute terpendek diantara dua titik. Salah satu algoritma pathfinding yang paling populer adalah Algoritma A* (A Star).
Konsep dasar A* yaitu berulang kali memeriksa lokasi paling sesuai yang belum dijelajahi. Algoritma ini selesai jika lokasi tersebut adalah tujuan, jika tidak, maka algortima a* akan mencatat tetangga lokasi tersebut bahwa lokasi lainnya akan dijelajahi. Beberapa terminologi dasar yang terdapat pada algoritma A* adalah starting point, simpul (nodes), open list, closed list, harga (cost), halangan (unwalkable) (Munir, 1998).
Kelebihan A* adalah menggunakan heuristik yang berfungsi sebagai optimasi dengan cara memberi nilai pada tiap simpul yang memandu A* untuk mendapatkan solusi yang diinginkan (Munir, 1998).
Berdasarkan penjelasan di atas, penulis akan mengembangkan suatu aplikasi game 2D dengan konsep tile based menggunakan peta grid pada platform Android.
(1)
2.6 Algoritma A* 2.6.1 Cara Kerja 2.6.2 Sifat Algoritma 2.7 Heuristik
2.7.1 Manhattan Distance 2.7.2 Diagonal Distance 2.7.3 Euclidian Distance 2.8 Android
2.9 Actionscript 3.0 2.10 Framework Starling
10 11 12 13 13 14 15 15 16 16
Bab III Analisis Dan PerancanganSistem 18
3.1 AnalisisSistem 18
3.1.1 Analisis Masalah 18
3.1.2 Analisis Kebutuhan 19
3.1.2.1 Kebutuhan Fungsional Sistem 19
3.1.2.2 Kebutuhan Non-Fungsional Sistem 20
3.1.3 Analisis Proses 20
3.2 Pemodelan 21
3.2.1 Use Case Diagram 21
3.2.2 Sequence Diagram 3.2.3. Activity Diagram
22 23 3.3 Flowchart Sistem
3.3.1 Flowchart Sistem
3.3.2 Flowchart Flowchart Pathfinding Algoritma A* 3.3.3 Flowchart Proses Game
24 25 26 27
(2)
Bab IV Implementasi dan Pengujian 32
4.1 Implementasi 32
4.1.1 Form Main Menu 4.1.2 Form Pilihan Level 4.1.3 Form Game
4.1.4 Form Bantuan 4.1.5 Form Tentang
32 33 33 34 34
4.2 Pengujian Sistem 35
4.2.1 Skenario Algoritma A* 4.2.1.1 Searching 4.2.1.2 Backtracking
4.2.1.3 Rute Pohon Terdekat 4.2.2 Pengujian Pathfinding A*
35 43 50 51 54
Bab V Kesimpulan dan Saran 58
5.1 Kesimpulan 58
5.2 Saran 59
Daftar Pustaka 60
(3)
DAFTAR TABEL
Nomor Tabel
NamaTabel Halaman
3.1 4.1 4.2 4.3
4.4 4.5
Narrative Use-Case Pathfinding A* Proses Pathfinding Algoritma A* Heuristik Manhattan Distance
Banyak Node yang Dikunjungi terhadap Banyak Penghalang
Banyak Node Dikunjungi terhadap Panjang rute Pengaruh Banyak Node Penghalang, Banyak Node yang Dikunjungi dan Panjang Rute terhadap Waktu
22 46 53 54 49 55 56
(4)
DAFTAR GAMBAR
Nomor Gambar
Nama Gambar Halaman
2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.12 4.13 4.14 4.15 4.16 4.17 4.18 4.19
Graf Sederhana(G1), Graf Ganda (G2), Graf
Semu(G3)
Graf Tidak Berarah Graf Berarah Weighted Graph Unweighted Graph
Ilustrasi Manhattan Distance
Ilustrasi Heuristik Diagonal Distance Ilustrasi Heuristik Euclidean Distance Diagram Ishikawa
Diagram Use-Case
Diagram Sequence Untuk Proses Pathfinding A* Activity Diagram Pathfinding A*
Flowchart Sistem
Flowchart Pathfinding Algoritma A* Flowchart Proses Game.
Rancangan Tampilan Form Utama Rancangan Form Pilihan Level Rancangan Form Game
Form Main Menu Form Pilihan Level Form Game Form Bantuan Form Tentang Grid Permainan
Ilustrasi Proses Pathfinding A* ke-1 dan 2 Ilustrasi Proses Pathfinding A* ke-3 s.d. 5 Ilustrasi Proses Pathfinding A* ke-6 s.d. 8 Ilustrasi Proses Pathfinding A* ke-9 s.d. 11 Ilustrasi Proses Pathfinding A* ke-12 s.d. 14 Ilustrasi Proses Pathfinding A* ke-15 s.d. 17 Ilustrasi Proses Pathfinding A* ke-18 s.d. 20 Ilustrasi Proses Pathfinding A* ke-21 s.d. 23 Ilustrasi Proses Pathfinding A* ke-24 s.d. 26 Ilustrasi Proses Pathfinding A* ke-27 s.d. 29 Ilustrasi Proses Pathfinding A* ke-30
Proses Backtracking
Sebelum proses backtracking (a), sesudah proses
8 8 9 9 10 14 14 15 19 21 23 24 25 26 27 29 30 30 32 33 33 34 34 34 35 36 37 38 39 40 41 42 43 44 45 46 50
(5)
4.20 4.21 4.22 4.23
4.24
4.25
backtracking (b)
Rute Musuh menuju Pohon T1
Rute Musuh menuju Pohon T2
Rute Musuh menuju Pohon T3
Grafik Banyak Node Dikunjungi terhadap Banyak Penghalang
Grafik Pengaruh Panjang Rute terhadap Banyak Node yang Dikunjungi
Grafik Pengaruh Banyak Node Pengahalang, Banyak Node yang Dikunjungi dan Panjang Rute terhadap Waktu
52 52 53 53
55
(6)
DAFTAR LAMPIRAN
A. Listing Program A1
B. Curriculum Vitae B1