diff --git a/public/index.html b/public/index.html
index fdc713e..1f9d708 100644
--- a/public/index.html
+++ b/public/index.html
@@ -1,8 +1,9 @@
-
+
-
+
+
Amogus factory
@@ -14,8 +15,9 @@
+
-
+
diff --git a/src/App.svelte b/src/App.svelte
index 0e323a6..cab2516 100644
--- a/src/App.svelte
+++ b/src/App.svelte
@@ -74,9 +74,6 @@
ambientSound = s.ambient;
musicSound = s.music;
});
-
- import {search} from "./Test";
- search();
diff --git a/src/Game/Game.js b/src/Game/Game.js
index 49496c4..4f62baf 100644
--- a/src/Game/Game.js
+++ b/src/Game/Game.js
@@ -20,6 +20,7 @@ import { WorldChunksVisibilityUpdater } from "./WorldGeneration/WorldChunksVisib
import { NPCProto } from "./NPC/NPCProto/NPCProto";
import { NPCController } from "./NPC/NPCController/NPCController";
import { PathFinder } from "./Utils/PathFinding.utils";
+import { getNavigationGridTile } from "./World/NavigationGrid/NavigationGrid";
export function generateWorld() {
@@ -63,10 +64,11 @@ function setupInGameSelector() {
BC_VIEWPORT.onpointerdown = (e) =>
{
let t = screenToWorldCoordinates(e.data.global.x, e.data.global.y);
+ // console.log(getNavigationGridTile(t.x, t.y));
// npccc.moveTo(new Point2D(getTileAt(t.x, t.y, ChunkStorageTypes.TYPE_TERRAIN).worldPosition.getX(), getTileAt(t.x, t.y, ChunkStorageTypes.TYPE_TERRAIN).worldPosition.getY()));
- let tile = getTileAt(t.x, t.y, ChunkStorageTypes.TYPE_TERRAIN);
- if(tile.props.navigationCost > 100) return;
- npccc.moveTo(new PointInt2D(tile.worldPosition.getX(), tile.worldPosition.getY()),
+ let tile = getNavigationGridTile(t.x, t.y);
+ if(tile.isObstacle) return;
+ npccc.moveTo(new PointInt2D(tile.position.getX(), tile.position.getY()),
(cb)=>{
console.log(cb);
});
diff --git a/src/Game/NPC/NPCController/NPCController.js b/src/Game/NPC/NPCController/NPCController.js
index 6274b32..5ecc741 100644
--- a/src/Game/NPC/NPCController/NPCController.js
+++ b/src/Game/NPC/NPCController/NPCController.js
@@ -1,6 +1,7 @@
import { GameObject } from "../../GameObject/GameObject";
import { PointInt2D } from "../../Utils/Math.utils";
import { NavigationPath, PathFinder } from "../../Utils/PathFinding.utils";
+import { findPathOnNavigationGridIfExists } from "../../World/NavigationGrid/NavigationGrid";
import { NPCProto } from "../NPCProto/NPCProto";
/**
* NPCController defines NPC behavior. Many NPC can have same NPCController for the same behavior.
@@ -33,24 +34,28 @@ export class NPCController extends GameObject
*/
moveTo(position, callback)
{
- let pf = new PathFinder();
- let nPath = pf.search(new PointInt2D(this.controlledNPC.worldPosition.getX(), this.controlledNPC.worldPosition.getY()), position);
- console.log(nPath);
- if(nPath.error)
- {
- callback("failed");
- return;
- }
- else if (nPath.result.path.length < 2)
- {
- callback("success");
- return;
- }
- for (let i = nPath.result.path.length-1; i > 0; i--) {
- this.navigationPathQueue.push(nPath.result.path[i]);
- }
- this.navigationCallback = callback;
- this.navigationInProgress = true;
+ // let pf = new PathFinder();
+ // let nPath = pf.findPathIfExist(new PointInt2D(this.controlledNPC.worldPosition.getX(), this.controlledNPC.worldPosition.getY()), position);
+ let nPath = findPathOnNavigationGridIfExists(new PointInt2D(this.controlledNPC.worldPosition.getX(), this.controlledNPC.worldPosition.getY()), position);
+ nPath.then((r)=>{
+ if(r.error)
+ {
+ callback("failed");
+ return;
+ }
+ else if (r.result.path.length < 2)
+ {
+ callback("success");
+ return;
+ }
+ for (let i = r.result.path.length-1; i > 0; i--) {
+ this.navigationPathQueue.push(r.result.path[i]);
+ }
+ this.navigationCallback = callback;
+ this.navigationInProgress = true;
+ });
+ // console.log("boba");
+ // console.log(nPath);
}
/**
diff --git a/src/Game/Utils/PathFinding.utils.js b/src/Game/Utils/PathFinding.utils.js
index c0bebe5..7c9ba61 100644
--- a/src/Game/Utils/PathFinding.utils.js
+++ b/src/Game/Utils/PathFinding.utils.js
@@ -4,14 +4,19 @@ import { getTileAt } from "../WorldGeneration/WorldGen";
import { PointInt2D } from "./Math.utils";
import { SceneObject } from "../SceneObjects/SceneObject";
import { getNavigationGridTile } from "../World/NavigationGrid/NavigationGrid";
+import { TerrainTile } from "../WorldGeneration/WorldObjects/TerrainTile/TerrainTile";
class PathFinderNode {
position;
- fScore = 0;
+ fScore = 1e16;
gScore = 1e16;
dScore = 1;
// hScore = 1e16;
id;
+ /**
+ * @type {TerrainTile}
+ */
+ ref;
/**
*
@@ -77,12 +82,32 @@ export class PathFinder {
_goal = new PointInt2D();
_start = new PointInt2D();
+ #MAX_PATH_ITERATIONS = 10000;
+ #iterationsCounter = 0;
+
+ // findPathIfExist(start, goal)
+ // {
+ // let resultFromGoal = this.search(goal, start);
+ // if(resultFromGoal.state !== 1)
+ // {
+ // return resultFromGoal;
+ // }
+ // else
+ // {
+ // resultFromGoal.result.path.reverse();
+ // return resultFromGoal;
+ // }
+ // }
+
/**
*
* @param {PointInt2D} start
* @param {PointInt2D} goal
*/
search(start, goal) {
+ this._openSet = [];
+ this._closedSet = [];
+ this.#iterationsCounter = 0;
start.divideBy(BC_TERRAIN_SETTINGS.totalSize);
start.multiplyBy(BC_TERRAIN_SETTINGS.totalSize);
this._start = start;
@@ -90,6 +115,7 @@ export class PathFinder {
goal.divideBy(BC_TERRAIN_SETTINGS.totalSize);
goal.multiplyBy(BC_TERRAIN_SETTINGS.totalSize);
this._goal = goal;
+ // getNavigationGridTile(goal.getX(), goal.getY()).optionalTerrainTileRef.drawObject.tint = 0x0000FF;
this._openSet.push(new PathFinderNode(this._start, 0, this._heuristic(this._start, 0)));
@@ -110,28 +136,29 @@ export class PathFinder {
/**
* @type Map
*/
- let cameFrom = new Array();
+ let cameFrom = new Map();
let minFScoreNodeIndex = 0;
//START LOOP WOOOOAAAW
- // console.log(goal);
while (this._openSet.length > 0) {
+ this.#iterationsCounter++;
+ if(this.#iterationsCounter >= this.#MAX_PATH_ITERATIONS)
+ {
+ return new NavigationResult(true, "reached limit", new NavigationPath(), 2);
+ }
//find node with min f score
//better to rewrite it to priority queue
+ minFScoreNodeIndex = 0;
for (let i = 0; i < this._openSet.length; i++) {
- // if(!this._openSet[i] || !this._openSet[minFScoreNodeIndex]){
- // return new NavigationResult(true, "Failed to access element in openSet", undefined);
- // }
if (this._openSet[i].fScore < this._openSet[minFScoreNodeIndex].fScore) minFScoreNodeIndex = i;
}
//wow! node is found and set!!
currentNode = this._openSet[minFScoreNodeIndex];
- minFScoreNodeIndex = 0;
+ // if (currentNode.ref) currentNode.ref.drawObject.tint = 0xff0000;
if (PointInt2D.isEqual(currentNode.position, this._goal)) {
//wow!!! we have found an end of the path!!! this is so cool!!!
- // console.log(cameFrom);
- return new NavigationResult(false, "", new NavigationPath(this._reconstructPath(cameFrom, currentNode))); //return something weird stuff
+ return new NavigationResult(false, "", new NavigationPath(this._reconstructPath(cameFrom, currentNode)), 1); //return something weird stuff
}
//and now we must delete this node... what a sad situation...
@@ -144,24 +171,20 @@ export class PathFinder {
*/
let currentNeighbors = this._getNeighbors(currentNode.position);
for (const neighbor of currentNeighbors) {
- let tentativeGScore = currentNode.gScore + this._manhattanDistance(currentNode.position, neighbor.position);
if (this._existsInClosedSet(neighbor)) continue;
- this._closedSet.push(neighbor);
- if (tentativeGScore < neighbor.gScore) {
- cameFrom.push({ id: neighbor.id, node: currentNode });
+ let tentativeGScore = currentNode.gScore + this._manhattanDistance(currentNode.position, neighbor.position);
+ if (tentativeGScore < neighbor.gScore && !this._existsInOpenSet(neighbor)) {
+ cameFrom.set(neighbor.id, currentNode);
neighbor.gScore = tentativeGScore;
- neighbor.fScore = tentativeGScore + this._heuristic(neighbor.position, neighbor.dScore)*0;
-
- if(!this._existsInOpenSet(neighbor))
- {
+ neighbor.fScore = tentativeGScore + this._heuristic(neighbor.position, neighbor.dScore);
+ if (!this._existsInOpenSet(neighbor)) {
this._openSet.push(neighbor);
}
}
}
- // console.log([...this._openSet]);
}
- return new NavigationResult(false, "", new NavigationPath());
+ return new NavigationResult(false, "", new NavigationPath(), 0);
}
/**
@@ -172,12 +195,12 @@ export class PathFinder {
_reconstructPath(cameFrom, current) {
let totalPath = [current.position];
console.log(cameFrom);
- // let keys = [...cameFrom.keys()];
- // while (keys.includes(current.id)) {
- // if (current.id === cameFrom.get(current.id).id) break;
- // current = cameFrom.get(current.id);
- // totalPath.push(current.position);
- // }
+ let keys = [...cameFrom.keys()];
+ while (keys.includes(current.id)) {
+ if (current.id === cameFrom.get(current.id).id) break;
+ current = cameFrom.get(current.id);
+ totalPath.push(current.position);
+ }
return totalPath.reverse();
}
@@ -194,38 +217,66 @@ export class PathFinder {
let currentTile = getNavigationGridTile(root.getX(), root.getY() + BC_TERRAIN_SETTINGS.totalSize);
let node;
if (currentTile && !currentTile.isObstacle) {
- currentTile.optionalTerrainTileRef.drawObject.tint = 0xff0000;
+ // currentTile.optionalTerrainTileRef.drawObject.tint = 0x0000ff;
node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost);
- if (/*!this._existsInClosedSet(node) &&*/ !currentTile.isObstacle) {
- neighbors.push(node);
- }
+ node.ref = currentTile.optionalTerrainTileRef;
+ neighbors.push(node);
}
+ //north-e
+ // currentTile = getNavigationGridTile(root.getX() + BC_TERRAIN_SETTINGS.totalSize, root.getY() + BC_TERRAIN_SETTINGS.totalSize);
+ // if (currentTile && !currentTile.isObstacle) {
+ // // currentTile.optionalTerrainTileRef.drawObject.tint = 0x0000ff;
+ // node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost);
+ // node.ref = currentTile.optionalTerrainTileRef;
+ // neighbors.push(node);
+ // }
+ //north-w
+ // currentTile = getNavigationGridTile(root.getX() - BC_TERRAIN_SETTINGS.totalSize, root.getY() + BC_TERRAIN_SETTINGS.totalSize);
+ // if (currentTile && !currentTile.isObstacle) {
+ // // currentTile.optionalTerrainTileRef.drawObject.tint = 0x0000ff;
+ // node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost);
+ // node.ref = currentTile.optionalTerrainTileRef;
+ // neighbors.push(node);
+ // }
//south
currentTile = getNavigationGridTile(root.getX(), root.getY() - BC_TERRAIN_SETTINGS.totalSize);
if (currentTile && !currentTile.isObstacle) {
- currentTile.optionalTerrainTileRef.drawObject.tint = 0xff0000;
+ // currentTile.optionalTerrainTileRef.drawObject.tint = 0x0000ff;
node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost);
- if (/*!this._existsInClosedSet(node) &&*/ !currentTile.isObstacle) {
- neighbors.push(node);
- }
+ node.ref = currentTile.optionalTerrainTileRef;
+ neighbors.push(node);
}
+ //south-e
+ // currentTile = getNavigationGridTile(root.getX() + BC_TERRAIN_SETTINGS.totalSize, root.getY() - BC_TERRAIN_SETTINGS.totalSize);
+ // if (currentTile && !currentTile.isObstacle) {
+ // // currentTile.optionalTerrainTileRef.drawObject.tint = 0x0000ff;
+ // node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost);
+ // node.ref = currentTile.optionalTerrainTileRef;
+ // neighbors.push(node);
+ // }
+ //south-w
+ // currentTile = getNavigationGridTile(root.getX() - BC_TERRAIN_SETTINGS.totalSize, root.getY() - BC_TERRAIN_SETTINGS.totalSize);
+ // if (currentTile && !currentTile.isObstacle) {
+ // // currentTile.optionalTerrainTileRef.drawObject.tint = 0x0000ff;
+ // node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost);
+ // node.ref = currentTile.optionalTerrainTileRef;
+ // neighbors.push(node);
+ // }
//east
currentTile = getNavigationGridTile(root.getX() + BC_TERRAIN_SETTINGS.totalSize, root.getY());
if (currentTile && !currentTile.isObstacle) {
- currentTile.optionalTerrainTileRef.drawObject.tint = 0xff0000;
+ // currentTile.optionalTerrainTileRef.drawObject.tint = 0x0000ff;
node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost);
- if (/*!this._existsInClosedSet(node) &&*/ !currentTile.isObstacle) {
- neighbors.push(node);
- }
+ node.ref = currentTile.optionalTerrainTileRef;
+ neighbors.push(node);
}
//west
currentTile = getNavigationGridTile(root.getX() - BC_TERRAIN_SETTINGS.totalSize, root.getY());
if (currentTile && !currentTile.isObstacle) {
- currentTile.optionalTerrainTileRef.drawObject.tint = 0xff0000;
+ // currentTile.optionalTerrainTileRef.drawObject.tint = 0x0000ff;
node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost);
- if (/*!this._existsInClosedSet(node) &&*/ !currentTile.isObstacle) {
- neighbors.push(node);
- }
+ node.ref = currentTile.optionalTerrainTileRef;
+ neighbors.push(node);
}
return neighbors;
}
@@ -234,12 +285,24 @@ export class PathFinder {
*
* @param {PointInt2D} start
* @param {PointInt2D} goal
- * @returns
+ * @returns {Number}
*/
_manhattanDistance(start, goal) {
return Math.abs(start.getX() - goal.getX()) + Math.abs(start.getY() - goal.getY());
}
+ /**
+ *
+ * @param {PointInt2D} start
+ * @param {PointInt2D} goal
+ * @returns {Number}
+ */
+ _euclideanDistance(start, goal) {
+ let dx = Math.abs(start.getX() - goal.getX());
+ let dy = Math.abs(start.getY() - goal.getY());
+ return Math.sqrt(dx * dx + dy * dy);
+ }
+
/**
*
* @param {PointInt2D} current
@@ -251,7 +314,8 @@ export class PathFinder {
let x2 = this._start.getX() - this._goal.getX();
let y2 = this._start.getY() - this._goal.getY();
let cross = Math.abs(x1 * y2 - x2 * y1);
- return this._manhattanDistance(current, this._goal) * d;
+ // console.log("cross", cross);
+ return this._manhattanDistance(current, this._goal) * d + cross * 0.00001;
}
/**
diff --git a/src/Game/World/NavigationGrid/NavigationGrid.js b/src/Game/World/NavigationGrid/NavigationGrid.js
index 69cbeb5..af32fc0 100644
--- a/src/Game/World/NavigationGrid/NavigationGrid.js
+++ b/src/Game/World/NavigationGrid/NavigationGrid.js
@@ -1,4 +1,5 @@
import { PointInt2D } from "../../Utils/Math.utils";
+import { PathFinder } from "../../Utils/PathFinding.utils";
import { getWorldChunkAt, worldCoordinatesToChunkLocalCoordinates } from "../../WorldGeneration/WorldGen";
import { TerrainTile } from "../../WorldGeneration/WorldObjects/TerrainTile/TerrainTile";
@@ -80,25 +81,30 @@ export class NavigationGridChunk
}
-export class NavigationGrid
-{
+// export class NavigationGrid
+// {
- /**
- *
- * @param {Number} xWorld
- * @param {Number} yWorld
- */
- static getNavigationGridTile(xWorld, yWorld)
- {
- let chunk = getWorldChunkAt(xWorld, yWorld);
- if(chunk)
- {
- return chunk.navigationGridChunk.getFromChunk(xWorld, yWorld);
- }
- return undefined;
- }
-}
+// /**
+// *
+// * @param {Number} xWorld
+// * @param {Number} yWorld
+// */
+// static getNavigationGridTile(xWorld, yWorld)
+// {
+// let chunk = getWorldChunkAt(xWorld, yWorld);
+// if(chunk)
+// {
+// return chunk.navigationGridChunk.getFromChunk(xWorld, yWorld);
+// }
+// return undefined;
+// }
+// }
+/**
+ * @param {Number} xWorld
+ * @param {Number} yWorld
+ * @returns
+ */
export function getNavigationGridTile(xWorld, yWorld)
{
let chunk = getWorldChunkAt(xWorld, yWorld);
@@ -107,4 +113,27 @@ export function getNavigationGridTile(xWorld, yWorld)
return chunk.navigationGridChunk.getFromChunk(xWorld, yWorld);
}
return undefined;
+}
+
+function NavigationGridPathFinderCallback(result) {
+
+}
+
+async function _findPathAsync(start, goal)
+{
+ let pf = new PathFinder();
+ return pf.search(start, goal);
+}
+/**
+ * @param {PointInt2D} start
+ * @param {PointInt2D} goal
+ */
+export async function findPathOnNavigationGridIfExists(start, goal) {
+ let r0 = await _findPathAsync(goal, start);
+ if(!r0.error){
+ r0.result.path.reverse();
+ return r0;
+ }
+ let r1 = await _findPathAsync(start, goal);
+ return r1;
}
\ No newline at end of file
diff --git a/src/Game/WorldGeneration/WorldGen.js b/src/Game/WorldGeneration/WorldGen.js
index d754afd..60356f2 100644
--- a/src/Game/WorldGeneration/WorldGen.js
+++ b/src/Game/WorldGeneration/WorldGen.js
@@ -8,7 +8,7 @@ import { Point2D, PointInt2D, clampNumber } from "../Utils/Math.utils";
import { addGameObjectToGameState } from "../GameState/GameState";
import { VegetationTile, VegetationTileProps } from "./WorldObjects/VegetationTile/VegetationTile";
import { WorldChunksVisibilityUpdater } from "./WorldChunksVisibilityUpdater/WorldChunksVisibilityUpdater";
-import { NavigationGrid, NavigationGridChunk, NavigationGridTile } from "../World/NavigationGrid/NavigationGrid";
+import { NavigationGridChunk, NavigationGridTile } from "../World/NavigationGrid/NavigationGrid";
/**
* @type Map
@@ -30,8 +30,8 @@ const terrainTypeList = {
};
const terrainNavigationCostList = {
0: 100000000000, //water
- 1: 1, //sand
- 2: 1, //grass
+ 1: 3, //sand
+ 2: 2, //grass
3: 1, //stone
};
const grassVegetationSpriteList = {
@@ -78,6 +78,7 @@ const grassVegResourcesList = {
export function worldCoordinatesToChunkIndex(x, y) {
let w = BC_CHUNKS_SETTINGS.width * BC_TERRAIN_SETTINGS.tileSize * BC_TERRAIN_SETTINGS.scale;
let h = BC_CHUNKS_SETTINGS.height * BC_TERRAIN_SETTINGS.tileSize * BC_TERRAIN_SETTINGS.scale;
+ // console.log(w, h);
return { x: Math.floor(x / w), y: Math.floor(y / h) };
}
export function worldCoordinatesToChunkIndexesCoordinates(x, y) {
@@ -126,7 +127,7 @@ export function getWorldChunkById(id) {
* @param {Number} xWorld
* @param {Number} yWorld
* @param {ChunkStorageTypes} storageType
- * @returns
+ * @returns {}
*/
export function getTileAt(xWorld, yWorld, storageType) {
let c = getWorldChunkAt(xWorld, yWorld);