From b97f5d99140b3f79a127a8b240b803c7c6e12f0a Mon Sep 17 00:00:00 2001 From: Andrew Ardill Date: Wed, 10 Jul 2013 20:49:10 +1000 Subject: [PATCH 1/4] world.js: Introduce function to copy positions --- script/world.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/script/world.js b/script/world.js index 0e81465..2b2f621 100644 --- a/script/world.js +++ b/script/world.js @@ -821,5 +821,9 @@ var World = { setTitle: function() { document.title = 'A Barren World'; + }, + + copyPos: function(pos) { + return [pos[0], pos[1]]; } }; \ No newline at end of file From c4afe143a96a2266aac84dc37fdf507e38c98fe4 Mon Sep 17 00:00:00 2001 From: Andrew Ardill Date: Wed, 10 Jul 2013 13:32:44 +1000 Subject: [PATCH 2/4] world.js: Introduce World.VILLAGE_POS This constant gets reused in a few places, so extract it out. Work will be required to migrate existing code away from hard coding World.RADIUS in places where we are talking about the village location. --- script/world.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/script/world.js b/script/world.js index 2b2f621..5dbde21 100644 --- a/script/world.js +++ b/script/world.js @@ -1,6 +1,7 @@ var World = { RADIUS: 30, + VILLAGE_POS: [30, 30], TILE: { VILLAGE: 'A', IRON_MINE: 'I', @@ -810,7 +811,7 @@ var World = { World.starvation = false; World.thirst = false; World.usedOutposts = {}; - World.curPos = [World.RADIUS, World.RADIUS]; + World.curPos = World.copyPos(World.VILLAGE_POS); World.drawMap(); World.setTitle(); World.dead = false; From 26b955fee837354f9dded81a3349ce996700bb82 Mon Sep 17 00:00:00 2001 From: Andrew Ardill Date: Wed, 10 Jul 2013 13:39:46 +1000 Subject: [PATCH 3/4] world.js: Increase functionality of getDistance Allow passing 'from' and 'to' positions to getDistance to find the distance between them. --- script/world.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/script/world.js b/script/world.js index 5dbde21..7534d80 100644 --- a/script/world.js +++ b/script/world.js @@ -419,8 +419,10 @@ var World = { } }, - getDistance: function() { - return Math.abs(World.curPos[0] - World.RADIUS) + Math.abs(World.curPos[1] - World.RADIUS); + getDistance: function(from, to) { + from = from || World.curPos; + to = to || World.VILLAGE_POS; + return Math.abs(from[0] - to[0]) + Math.abs(from[1] - to[1]); }, getTerrain: function() { From 255bdd68fce7367faa0510d9a4eb6f610a00b36c Mon Sep 17 00:00:00 2001 From: Andrew Ardill Date: Wed, 10 Jul 2013 11:59:21 +1000 Subject: [PATCH 4/4] world.js: Improve road drawing algorithm Instead of drawing an 'L' shape road to the village, find the closest road, outpost or village and draw the road to it. Care is taken to ensure that a road is drawn if you are standing on top of an outpost, as the outpost may be created before the tile it stands on is connected to the road network. --- script/world.js | 61 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/script/world.js b/script/world.js index 7534d80..1342c57 100644 --- a/script/world.js +++ b/script/world.js @@ -152,27 +152,68 @@ var World = { }, drawRoad: function() { - var xDist = World.curPos[0] - World.RADIUS; - var yDist = World.curPos[1] - World.RADIUS; + var findClosestRoad = function(startPos) { + // We'll search in a spiral to find the closest road tile + // We spiral out along manhattan distance contour + // lines to ensure we draw the shortest road possible. + // No attempt is made to reduce the search space for + // tiles outside the map. + var searchX, searchY, dtmp, + x = 0, + y = 0, + dx = 1, + dy = -1; + for (var i = 0; i < Math.pow(World.getDistance(startPos, World.VILLAGE_POS) + 2, 2); i++) { + searchX = startPos[0] + x; + searchY = startPos[1] + y; + if (0 < searchX && searchX < World.RADIUS * 2 && 0 < searchY && searchY < World.RADIUS * 2) { + // check for road + var tile = World.state.map[searchX][searchY]; + if ( + tile === World.TILE.ROAD || + (tile === World.TILE.OUTPOST && !(x === 0 && y === 0)) || // outposts are connected to roads + tile === World.TILE.VILLAGE // all roads lead home + ) { + return [searchX, searchY]; + } + } + if (x === 0 || y === 0) { + // Turn the corner + dtmp = dx; + dx = -dy; + dy = dtmp; + } + if (x === 0 && y <= 0) { + x++; + } else { + x += dx; + y += dy; + } + } + return World.VILLAGE_POS; + }; + var closestRoad = findClosestRoad(World.curPos); + var xDist = World.curPos[0] - closestRoad[0]; + var yDist = World.curPos[1] - closestRoad[1]; var xDir = Math.abs(xDist)/xDist; var yDir = Math.abs(yDist)/yDist; var xIntersect, yIntersect; if(Math.abs(xDist) > Math.abs(yDist)) { - xIntersect = World.RADIUS; - yIntersect = World.RADIUS + yDist; + xIntersect = closestRoad[0]; + yIntersect = closestRoad[1] + yDist; } else { - xIntersect = World.RADIUS + xDist; - yIntersect = World.RADIUS; + xIntersect = closestRoad[0] + xDist; + yIntersect = closestRoad[1]; } for(var x = 0; x < Math.abs(xDist); x++) { - if(World.isTerrain(World.state.map[World.RADIUS + (xDir*x)][yIntersect])) { - World.state.map[World.RADIUS + (xDir*x)][yIntersect] = World.TILE.ROAD; + if(World.isTerrain(World.state.map[closestRoad[0] + (xDir*x)][yIntersect])) { + World.state.map[closestRoad[0] + (xDir*x)][yIntersect] = World.TILE.ROAD; } } for(var y = 0; y < Math.abs(yDist); y++) { - if(World.isTerrain(World.state.map[xIntersect][World.RADIUS + (yDir*y)])) { - World.state.map[xIntersect][World.RADIUS + (yDir*y)] = World.TILE.ROAD; + if(World.isTerrain(World.state.map[xIntersect][closestRoad[1] + (yDir*y)])) { + World.state.map[xIntersect][closestRoad[1] + (yDir*y)] = World.TILE.ROAD; } } World.drawMap();