fixed PathFinder and now it is async

This commit is contained in:
TorgaW 2024-04-21 00:09:06 +03:00
parent fdfa7bd7cb
commit 815422f8e4
7 changed files with 191 additions and 91 deletions

View File

@ -1,8 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en" style="width: 100%; height: 100%;">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- <meta name="viewport" content="width=device-width,initial-scale=1" /> -->
<title>Amogus factory</title> <title>Amogus factory</title>
@ -14,8 +15,9 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=VT323&display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css2?family=VT323&display=swap" rel="stylesheet" />
<script defer src="/build/bundle.js"></script> <script defer src="/build/bundle.js"></script>
</head> </head>
<body></body> <body style="width: 100%; height: 100%;"></body>
</html> </html>

View File

@ -74,9 +74,6 @@
ambientSound = s.ambient; ambientSound = s.ambient;
musicSound = s.music; musicSound = s.music;
}); });
import {search} from "./Test";
search();
</script> </script>
<div id="game-ui" class="absolute inset-0 flex items-center justify-center text-white select-none tracking-widest font-pixel pointer-events-none"> <div id="game-ui" class="absolute inset-0 flex items-center justify-center text-white select-none tracking-widest font-pixel pointer-events-none">

View File

@ -20,6 +20,7 @@ import { WorldChunksVisibilityUpdater } from "./WorldGeneration/WorldChunksVisib
import { NPCProto } from "./NPC/NPCProto/NPCProto"; import { NPCProto } from "./NPC/NPCProto/NPCProto";
import { NPCController } from "./NPC/NPCController/NPCController"; import { NPCController } from "./NPC/NPCController/NPCController";
import { PathFinder } from "./Utils/PathFinding.utils"; import { PathFinder } from "./Utils/PathFinding.utils";
import { getNavigationGridTile } from "./World/NavigationGrid/NavigationGrid";
export function generateWorld() { export function generateWorld() {
@ -63,10 +64,11 @@ function setupInGameSelector() {
BC_VIEWPORT.onpointerdown = (e) => BC_VIEWPORT.onpointerdown = (e) =>
{ {
let t = screenToWorldCoordinates(e.data.global.x, e.data.global.y); 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())); // 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); let tile = getNavigationGridTile(t.x, t.y);
if(tile.props.navigationCost > 100) return; if(tile.isObstacle) return;
npccc.moveTo(new PointInt2D(tile.worldPosition.getX(), tile.worldPosition.getY()), npccc.moveTo(new PointInt2D(tile.position.getX(), tile.position.getY()),
(cb)=>{ (cb)=>{
console.log(cb); console.log(cb);
}); });

View File

@ -1,6 +1,7 @@
import { GameObject } from "../../GameObject/GameObject"; import { GameObject } from "../../GameObject/GameObject";
import { PointInt2D } from "../../Utils/Math.utils"; import { PointInt2D } from "../../Utils/Math.utils";
import { NavigationPath, PathFinder } from "../../Utils/PathFinding.utils"; import { NavigationPath, PathFinder } from "../../Utils/PathFinding.utils";
import { findPathOnNavigationGridIfExists } from "../../World/NavigationGrid/NavigationGrid";
import { NPCProto } from "../NPCProto/NPCProto"; import { NPCProto } from "../NPCProto/NPCProto";
/** /**
* NPCController defines NPC behavior. Many NPC can have same NPCController for the same behavior. * 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) moveTo(position, callback)
{ {
let pf = new PathFinder(); // let pf = new PathFinder();
let nPath = pf.search(new PointInt2D(this.controlledNPC.worldPosition.getX(), this.controlledNPC.worldPosition.getY()), position); // let nPath = pf.findPathIfExist(new PointInt2D(this.controlledNPC.worldPosition.getX(), this.controlledNPC.worldPosition.getY()), position);
console.log(nPath); let nPath = findPathOnNavigationGridIfExists(new PointInt2D(this.controlledNPC.worldPosition.getX(), this.controlledNPC.worldPosition.getY()), position);
if(nPath.error) nPath.then((r)=>{
if(r.error)
{ {
callback("failed"); callback("failed");
return; return;
} }
else if (nPath.result.path.length < 2) else if (r.result.path.length < 2)
{ {
callback("success"); callback("success");
return; return;
} }
for (let i = nPath.result.path.length-1; i > 0; i--) { for (let i = r.result.path.length-1; i > 0; i--) {
this.navigationPathQueue.push(nPath.result.path[i]); this.navigationPathQueue.push(r.result.path[i]);
} }
this.navigationCallback = callback; this.navigationCallback = callback;
this.navigationInProgress = true; this.navigationInProgress = true;
});
// console.log("boba");
// console.log(nPath);
} }
/** /**

View File

@ -4,14 +4,19 @@ import { getTileAt } from "../WorldGeneration/WorldGen";
import { PointInt2D } from "./Math.utils"; import { PointInt2D } from "./Math.utils";
import { SceneObject } from "../SceneObjects/SceneObject"; import { SceneObject } from "../SceneObjects/SceneObject";
import { getNavigationGridTile } from "../World/NavigationGrid/NavigationGrid"; import { getNavigationGridTile } from "../World/NavigationGrid/NavigationGrid";
import { TerrainTile } from "../WorldGeneration/WorldObjects/TerrainTile/TerrainTile";
class PathFinderNode { class PathFinderNode {
position; position;
fScore = 0; fScore = 1e16;
gScore = 1e16; gScore = 1e16;
dScore = 1; dScore = 1;
// hScore = 1e16; // hScore = 1e16;
id; id;
/**
* @type {TerrainTile}
*/
ref;
/** /**
* *
@ -77,12 +82,32 @@ export class PathFinder {
_goal = new PointInt2D(); _goal = new PointInt2D();
_start = 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} start
* @param {PointInt2D} goal * @param {PointInt2D} goal
*/ */
search(start, goal) { search(start, goal) {
this._openSet = [];
this._closedSet = [];
this.#iterationsCounter = 0;
start.divideBy(BC_TERRAIN_SETTINGS.totalSize); start.divideBy(BC_TERRAIN_SETTINGS.totalSize);
start.multiplyBy(BC_TERRAIN_SETTINGS.totalSize); start.multiplyBy(BC_TERRAIN_SETTINGS.totalSize);
this._start = start; this._start = start;
@ -90,6 +115,7 @@ export class PathFinder {
goal.divideBy(BC_TERRAIN_SETTINGS.totalSize); goal.divideBy(BC_TERRAIN_SETTINGS.totalSize);
goal.multiplyBy(BC_TERRAIN_SETTINGS.totalSize); goal.multiplyBy(BC_TERRAIN_SETTINGS.totalSize);
this._goal = goal; 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))); this._openSet.push(new PathFinderNode(this._start, 0, this._heuristic(this._start, 0)));
@ -110,28 +136,29 @@ export class PathFinder {
/** /**
* @type Map<String, PathFinderNode> * @type Map<String, PathFinderNode>
*/ */
let cameFrom = new Array(); let cameFrom = new Map();
let minFScoreNodeIndex = 0; let minFScoreNodeIndex = 0;
//START LOOP WOOOOAAAW //START LOOP WOOOOAAAW
// console.log(goal);
while (this._openSet.length > 0) { 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 //find node with min f score
//better to rewrite it to priority queue //better to rewrite it to priority queue
minFScoreNodeIndex = 0;
for (let i = 0; i < this._openSet.length; i++) { 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; if (this._openSet[i].fScore < this._openSet[minFScoreNodeIndex].fScore) minFScoreNodeIndex = i;
} }
//wow! node is found and set!! //wow! node is found and set!!
currentNode = this._openSet[minFScoreNodeIndex]; currentNode = this._openSet[minFScoreNodeIndex];
minFScoreNodeIndex = 0; // if (currentNode.ref) currentNode.ref.drawObject.tint = 0xff0000;
if (PointInt2D.isEqual(currentNode.position, this._goal)) { if (PointInt2D.isEqual(currentNode.position, this._goal)) {
//wow!!! we have found an end of the path!!! this is so cool!!! //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)), 1); //return something weird stuff
return new NavigationResult(false, "", new NavigationPath(this._reconstructPath(cameFrom, currentNode))); //return something weird stuff
} }
//and now we must delete this node... what a sad situation... //and now we must delete this node... what a sad situation...
@ -144,24 +171,20 @@ export class PathFinder {
*/ */
let currentNeighbors = this._getNeighbors(currentNode.position); let currentNeighbors = this._getNeighbors(currentNode.position);
for (const neighbor of currentNeighbors) { for (const neighbor of currentNeighbors) {
let tentativeGScore = currentNode.gScore + this._manhattanDistance(currentNode.position, neighbor.position);
if (this._existsInClosedSet(neighbor)) continue; if (this._existsInClosedSet(neighbor)) continue;
this._closedSet.push(neighbor); let tentativeGScore = currentNode.gScore + this._manhattanDistance(currentNode.position, neighbor.position);
if (tentativeGScore < neighbor.gScore) { if (tentativeGScore < neighbor.gScore && !this._existsInOpenSet(neighbor)) {
cameFrom.push({ id: neighbor.id, node: currentNode }); cameFrom.set(neighbor.id, currentNode);
neighbor.gScore = tentativeGScore; neighbor.gScore = tentativeGScore;
neighbor.fScore = tentativeGScore + this._heuristic(neighbor.position, neighbor.dScore)*0; neighbor.fScore = tentativeGScore + this._heuristic(neighbor.position, neighbor.dScore);
if (!this._existsInOpenSet(neighbor)) {
if(!this._existsInOpenSet(neighbor))
{
this._openSet.push(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) { _reconstructPath(cameFrom, current) {
let totalPath = [current.position]; let totalPath = [current.position];
console.log(cameFrom); console.log(cameFrom);
// let keys = [...cameFrom.keys()]; let keys = [...cameFrom.keys()];
// while (keys.includes(current.id)) { while (keys.includes(current.id)) {
// if (current.id === cameFrom.get(current.id).id) break; if (current.id === cameFrom.get(current.id).id) break;
// current = cameFrom.get(current.id); current = cameFrom.get(current.id);
// totalPath.push(current.position); totalPath.push(current.position);
// } }
return totalPath.reverse(); return totalPath.reverse();
} }
@ -194,39 +217,67 @@ export class PathFinder {
let currentTile = getNavigationGridTile(root.getX(), root.getY() + BC_TERRAIN_SETTINGS.totalSize); let currentTile = getNavigationGridTile(root.getX(), root.getY() + BC_TERRAIN_SETTINGS.totalSize);
let node; let node;
if (currentTile && !currentTile.isObstacle) { if (currentTile && !currentTile.isObstacle) {
currentTile.optionalTerrainTileRef.drawObject.tint = 0xff0000; // currentTile.optionalTerrainTileRef.drawObject.tint = 0x0000ff;
node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost); node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost);
if (/*!this._existsInClosedSet(node) &&*/ !currentTile.isObstacle) { node.ref = currentTile.optionalTerrainTileRef;
neighbors.push(node); 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 //south
currentTile = getNavigationGridTile(root.getX(), root.getY() - BC_TERRAIN_SETTINGS.totalSize); currentTile = getNavigationGridTile(root.getX(), root.getY() - BC_TERRAIN_SETTINGS.totalSize);
if (currentTile && !currentTile.isObstacle) { if (currentTile && !currentTile.isObstacle) {
currentTile.optionalTerrainTileRef.drawObject.tint = 0xff0000; // currentTile.optionalTerrainTileRef.drawObject.tint = 0x0000ff;
node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost); node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost);
if (/*!this._existsInClosedSet(node) &&*/ !currentTile.isObstacle) { node.ref = currentTile.optionalTerrainTileRef;
neighbors.push(node); 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 //east
currentTile = getNavigationGridTile(root.getX() + BC_TERRAIN_SETTINGS.totalSize, root.getY()); currentTile = getNavigationGridTile(root.getX() + BC_TERRAIN_SETTINGS.totalSize, root.getY());
if (currentTile && !currentTile.isObstacle) { if (currentTile && !currentTile.isObstacle) {
currentTile.optionalTerrainTileRef.drawObject.tint = 0xff0000; // currentTile.optionalTerrainTileRef.drawObject.tint = 0x0000ff;
node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost); node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost);
if (/*!this._existsInClosedSet(node) &&*/ !currentTile.isObstacle) { node.ref = currentTile.optionalTerrainTileRef;
neighbors.push(node); neighbors.push(node);
} }
}
//west //west
currentTile = getNavigationGridTile(root.getX() - BC_TERRAIN_SETTINGS.totalSize, root.getY()); currentTile = getNavigationGridTile(root.getX() - BC_TERRAIN_SETTINGS.totalSize, root.getY());
if (currentTile && !currentTile.isObstacle) { if (currentTile && !currentTile.isObstacle) {
currentTile.optionalTerrainTileRef.drawObject.tint = 0xff0000; // currentTile.optionalTerrainTileRef.drawObject.tint = 0x0000ff;
node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost); node = new PathFinderNode(currentTile.position, 1e16, 1e16, currentTile.movementCost);
if (/*!this._existsInClosedSet(node) &&*/ !currentTile.isObstacle) { node.ref = currentTile.optionalTerrainTileRef;
neighbors.push(node); neighbors.push(node);
} }
}
return neighbors; return neighbors;
} }
@ -234,12 +285,24 @@ export class PathFinder {
* *
* @param {PointInt2D} start * @param {PointInt2D} start
* @param {PointInt2D} goal * @param {PointInt2D} goal
* @returns * @returns {Number}
*/ */
_manhattanDistance(start, goal) { _manhattanDistance(start, goal) {
return Math.abs(start.getX() - goal.getX()) + Math.abs(start.getY() - goal.getY()); 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 * @param {PointInt2D} current
@ -251,7 +314,8 @@ export class PathFinder {
let x2 = this._start.getX() - this._goal.getX(); let x2 = this._start.getX() - this._goal.getX();
let y2 = this._start.getY() - this._goal.getY(); let y2 = this._start.getY() - this._goal.getY();
let cross = Math.abs(x1 * y2 - x2 * y1); 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;
} }
/** /**

View File

@ -1,4 +1,5 @@
import { PointInt2D } from "../../Utils/Math.utils"; import { PointInt2D } from "../../Utils/Math.utils";
import { PathFinder } from "../../Utils/PathFinding.utils";
import { getWorldChunkAt, worldCoordinatesToChunkLocalCoordinates } from "../../WorldGeneration/WorldGen"; import { getWorldChunkAt, worldCoordinatesToChunkLocalCoordinates } from "../../WorldGeneration/WorldGen";
import { TerrainTile } from "../../WorldGeneration/WorldObjects/TerrainTile/TerrainTile"; 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} xWorld
* @param {Number} yWorld * @param {Number} yWorld
* @returns
*/ */
static getNavigationGridTile(xWorld, yWorld)
{
let chunk = getWorldChunkAt(xWorld, yWorld);
if(chunk)
{
return chunk.navigationGridChunk.getFromChunk(xWorld, yWorld);
}
return undefined;
}
}
export function getNavigationGridTile(xWorld, yWorld) export function getNavigationGridTile(xWorld, yWorld)
{ {
let chunk = getWorldChunkAt(xWorld, yWorld); let chunk = getWorldChunkAt(xWorld, yWorld);
@ -108,3 +114,26 @@ export function getNavigationGridTile(xWorld, yWorld)
} }
return undefined; 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;
}

View File

@ -8,7 +8,7 @@ import { Point2D, PointInt2D, clampNumber } from "../Utils/Math.utils";
import { addGameObjectToGameState } from "../GameState/GameState"; import { addGameObjectToGameState } from "../GameState/GameState";
import { VegetationTile, VegetationTileProps } from "./WorldObjects/VegetationTile/VegetationTile"; import { VegetationTile, VegetationTileProps } from "./WorldObjects/VegetationTile/VegetationTile";
import { WorldChunksVisibilityUpdater } from "./WorldChunksVisibilityUpdater/WorldChunksVisibilityUpdater"; import { WorldChunksVisibilityUpdater } from "./WorldChunksVisibilityUpdater/WorldChunksVisibilityUpdater";
import { NavigationGrid, NavigationGridChunk, NavigationGridTile } from "../World/NavigationGrid/NavigationGrid"; import { NavigationGridChunk, NavigationGridTile } from "../World/NavigationGrid/NavigationGrid";
/** /**
* @type Map<String, WorldChunk> * @type Map<String, WorldChunk>
@ -30,8 +30,8 @@ const terrainTypeList = {
}; };
const terrainNavigationCostList = { const terrainNavigationCostList = {
0: 100000000000, //water 0: 100000000000, //water
1: 1, //sand 1: 3, //sand
2: 1, //grass 2: 2, //grass
3: 1, //stone 3: 1, //stone
}; };
const grassVegetationSpriteList = { const grassVegetationSpriteList = {
@ -78,6 +78,7 @@ const grassVegResourcesList = {
export function worldCoordinatesToChunkIndex(x, y) { export function worldCoordinatesToChunkIndex(x, y) {
let w = BC_CHUNKS_SETTINGS.width * BC_TERRAIN_SETTINGS.tileSize * BC_TERRAIN_SETTINGS.scale; 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; 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) }; return { x: Math.floor(x / w), y: Math.floor(y / h) };
} }
export function worldCoordinatesToChunkIndexesCoordinates(x, y) { export function worldCoordinatesToChunkIndexesCoordinates(x, y) {
@ -126,7 +127,7 @@ export function getWorldChunkById(id) {
* @param {Number} xWorld * @param {Number} xWorld
* @param {Number} yWorld * @param {Number} yWorld
* @param {ChunkStorageTypes} storageType * @param {ChunkStorageTypes} storageType
* @returns * @returns {}
*/ */
export function getTileAt(xWorld, yWorld, storageType) { export function getTileAt(xWorld, yWorld, storageType) {
let c = getWorldChunkAt(xWorld, yWorld); let c = getWorldChunkAt(xWorld, yWorld);