terrain generation changed

This commit is contained in:
TorgaW 2024-05-07 23:04:23 +03:00
parent 0fe482a152
commit 8abe52eca8
26 changed files with 594 additions and 791 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -2,15 +2,17 @@ import { BC_CAMERA, BC_VIEWPORT } from "../GlobalVariables/GlobalVariables";
import { UICameraInfo } from "../UIPipes/UIPipes"; import { UICameraInfo } from "../UIPipes/UIPipes";
import { interpolate, interpolateCos } from "../Utils/Math.utils"; import { interpolate, interpolateCos } from "../Utils/Math.utils";
const cameraSpeed = 500;
export function moveVertically(tick, keyCode) { export function moveVertically(tick, keyCode) {
BC_CAMERA.position.y += (tick.deltaMS / 1000) * 1800 * (keyCode === "KeyS" ? 1 : -1); BC_CAMERA.position.y += (tick.deltaMS / 1000) * cameraSpeed * (keyCode === "KeyS" ? 1 : -1);
UICameraInfo.update((s) => { UICameraInfo.update((s) => {
s.position.y = BC_CAMERA.position.y; s.position.y = BC_CAMERA.position.y;
}); });
} }
export function moveHorizontally(tick, keyCode) { export function moveHorizontally(tick, keyCode) {
BC_CAMERA.position.x += (tick.deltaMS / 1000) * 1800 * (keyCode === "KeyD" ? 1 : -1); BC_CAMERA.position.x += (tick.deltaMS / 1000) * cameraSpeed * (keyCode === "KeyD" ? 1 : -1);
UICameraInfo.update((s) => { UICameraInfo.update((s) => {
s.position.x = BC_CAMERA.position.x; s.position.x = BC_CAMERA.position.x;
}); });

View File

@ -4,7 +4,7 @@ import { UICameraInfo, UIGameProfilerPipe, UIMainPipe, UIObtainedResourcesPipe,
import { getSpriteFromAtlas } from "./Utils/Sprites.utils"; import { getSpriteFromAtlas } from "./Utils/Sprites.utils";
import { profileFPS } from "./Profiler/Profiler"; import { profileFPS } from "./Profiler/Profiler";
import { createKeyboardBinding, inputControllerTick } from "./InputController/InputController"; import { createKeyboardBinding, inputControllerTick } from "./InputController/InputController";
import { BC_APP, BC_BUILDING_PLACEHOLDERS, BC_CAMERA, BC_CURRENT_SCENE, BC_SPRITES_SETTINGS, BC_VIEWPORT, BC_WORLD, PRNG, setBC_APP, setBC_CURRENT_SCENE, setBC_NPC_LAYER, setBC_SELECTION, setBC_VIEWPORT, setBC_WORLD } from "./GlobalVariables/GlobalVariables"; import { BC_APP, BC_BUILDING_PLACEHOLDERS, BC_CAMERA, BC_CURRENT_SCENE, BC_SPRITES_SETTINGS, BC_TERRAIN_MANAGER, BC_VIEWPORT, BC_WORLD, PRNG, setBC_APP, setBC_CURRENT_SCENE, setBC_NPC_LAYER, setBC_SELECTION, setBC_TERRAIN_MANAGER, setBC_VIEWPORT, setBC_WORLD } from "./GlobalVariables/GlobalVariables";
import { Point2D, PointInt2D, clampNumber, interpolate, } from "./Utils/Math.utils"; import { Point2D, PointInt2D, clampNumber, interpolate, } from "./Utils/Math.utils";
import { calculateViewportFromCamera, moveHorizontally, moveVertically, screenToWorldCoordinates } from "./Camera/Camera"; import { calculateViewportFromCamera, moveHorizontally, moveVertically, screenToWorldCoordinates } from "./Camera/Camera";
@ -14,13 +14,15 @@ import { ambientDay, ambientMusic, ambientNight, handleSounds } from "./Sound/So
import { addGameObjectToGameState, gameStateObjectsCleaner } from "./GameState/GameState"; import { addGameObjectToGameState, gameStateObjectsCleaner } from "./GameState/GameState";
import { tickHandler } from "./TickHandler/TickHandler"; import { tickHandler } from "./TickHandler/TickHandler";
import { GameScene } from "./GameScene/GameScene"; import { GameScene } from "./GameScene/GameScene";
import { createFirstWorldChunks, getTileAt, getWorldChunkAt, worldCoordinatesToChunkIndex } from "./WorldGeneration/WorldGen"; // import { createFirstWorldChunks, getTileAt, getWorldChunkAt, worldCoordinatesToChunkIndex } from "./WorldGeneration/WorldGen_";
import { ChunkStorageTypes } from "./WorldGeneration/WorldChunk/WorldGenChunk"; // import { ChunkStorageTypes } from "./WorldGeneration/WorldChunk/WorldGenChunk";
import { WorldChunksVisibilityUpdater } from "./WorldGeneration/WorldChunksVisibilityUpdater/WorldChunksVisibilityUpdater"; // import { WorldChunksVisibilityUpdater } from "./WorldGeneration/WorldChunksVisibilityUpdater/WorldChunksVisibilityUpdater";
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"; import { getNavigationGridTile } from "./World/NavigationGrid/NavigationGrid";
import { TerrainManger } from "./WorldGenV2/TerrainManager/TerrainManager";
import { generateFirstChunks } from "./WorldGenV2/WorldGenV2";
export function generateWorld() { export function generateWorld() {
@ -55,12 +57,19 @@ function setupInGameSelector() {
let t = screenToWorldCoordinates(e.data.global.x, e.data.global.y); let t = screenToWorldCoordinates(e.data.global.x, e.data.global.y);
// let tChunk = getWorldChunkAt(t.x, t.y); // let tChunk = getWorldChunkAt(t.x, t.y);
// let tTerrainTile = tChunk.getFromChunk(t.x, t.y, ChunkStorageTypes.TYPE_TERRAIN); // let tTerrainTile = tChunk.getFromChunk(t.x, t.y, ChunkStorageTypes.TYPE_TERRAIN);
let terrainTile = getTileAt(t.x, t.y, ChunkStorageTypes.TYPE_TERRAIN); // let terrainTile = getTileAt(t.x, t.y, ChunkStorageTypes.TYPE_TERRAIN);
// console.log(terrainTile); // console.log(terrainTile);
UISelectionInfo.update((s)=>{ // UISelectionInfo.update((s)=>{
s.types = [terrainTile.props.type]; // s.types = [terrainTile.props.type];
}); // });
let tile = BC_TERRAIN_MANAGER.getTileAt(new PointInt2D(t.x, t.y));
// console.log(tile);
if(tile)
{
UISelectionInfo.update((s)=>{
s.types = [tile.tileId];
});
}
t.x = BC_SPRITES_SETTINGS.defaultSize * BC_SPRITES_SETTINGS.scale * Math.floor(t.x / (BC_SPRITES_SETTINGS.defaultSize * BC_SPRITES_SETTINGS.scale)); t.x = BC_SPRITES_SETTINGS.defaultSize * BC_SPRITES_SETTINGS.scale * Math.floor(t.x / (BC_SPRITES_SETTINGS.defaultSize * BC_SPRITES_SETTINGS.scale));
t.y = BC_SPRITES_SETTINGS.defaultSize * BC_SPRITES_SETTINGS.scale * Math.floor(t.y / (BC_SPRITES_SETTINGS.defaultSize * BC_SPRITES_SETTINGS.scale)); t.y = BC_SPRITES_SETTINGS.defaultSize * BC_SPRITES_SETTINGS.scale * Math.floor(t.y / (BC_SPRITES_SETTINGS.defaultSize * BC_SPRITES_SETTINGS.scale));
sprite0.position.set(t.x, t.y); sprite0.position.set(t.x, t.y);
@ -122,11 +131,11 @@ export async function initGame() {
app.ticker.add(inputControllerTick); app.ticker.add(inputControllerTick);
app.ticker.add(calculateViewportFromCamera); app.ticker.add(calculateViewportFromCamera);
//static functions shitty binding //static functions shitty binding
app.ticker.add(WorldChunksVisibilityUpdater.handleWorldChunksVisibility.bind(WorldChunksVisibilityUpdater)); // app.ticker.add(WorldChunksVisibilityUpdater.handleWorldChunksVisibility.bind(WorldChunksVisibilityUpdater));
app.ticker.add(WorldChunksVisibilityUpdater.handleWorldChunkFilling.bind(WorldChunksVisibilityUpdater)); // app.ticker.add(WorldChunksVisibilityUpdater.handleWorldChunkFilling.bind(WorldChunksVisibilityUpdater));
//end of shit //end of shit
app.ticker.add(profileFPS); app.ticker.add(profileFPS);
app.ticker.add(handleBuildingsIncome); // app.ticker.add(handleBuildingsIncome);
createKeyboardBinding("KeyW", "Hold", [moveVertically]); createKeyboardBinding("KeyW", "Hold", [moveVertically]);
createKeyboardBinding("KeyS", "Hold", [moveVertically]); createKeyboardBinding("KeyS", "Hold", [moveVertically]);
@ -148,7 +157,13 @@ function startGame() {
BC_APP.ticker.add(gameStateObjectsCleaner); BC_APP.ticker.add(gameStateObjectsCleaner);
BC_APP.ticker.add(tickHandler); BC_APP.ticker.add(tickHandler);
createFirstWorldChunks(); let terrainManager = new TerrainManger();
terrainManager.currentTerrain = terrainManager.createNewTerrain();
setBC_TERRAIN_MANAGER(terrainManager);
BC_VIEWPORT.addChild(terrainManager.currentTerrain.drawObject);
BC_APP.ticker.add(terrainManager.tickHandler.bind(terrainManager));
generateFirstChunks();
// createFirstWorldChunks();
let testNPCController = new NPCController(true); let testNPCController = new NPCController(true);
let testNPC = new NPCProto(true, testNPCController); let testNPC = new NPCProto(true, testNPCController);

View File

@ -66,4 +66,16 @@ export class GameObject {
isTickEnabled(){return this._tickEnabled;}; isTickEnabled(){return this._tickEnabled;};
isMarkedPendingKill(){return this._markedPendingKill;}; isMarkedPendingKill(){return this._markedPendingKill;};
isInitialized(){return (this.minorId > -1 && this.majorId > -1);};
/**
*
* @param {GameObject} objectA
* @param {GameObject} objectB
* @returns
*/
static isEqual(objectA, objectB)
{
if(!objectA || !objectB) return false;
return (objectA.minorId === objectB.minorId) && (objectA.majorId === objectB.majorId);
};
}; };

View File

@ -1,6 +1,7 @@
import Alea from "alea"; import Alea from "alea";
import { Container } from "../../pixi/pixi.mjs"; import { Container } from "../../pixi/pixi.mjs";
import { GameScene } from "../GameScene/GameScene"; import { GameScene } from "../GameScene/GameScene";
import { TerrainManger } from "../WorldGenV2/TerrainManager/TerrainManager";
export let BC_APP; export let BC_APP;
@ -43,8 +44,8 @@ export function setBC_NPC_LAYER(npc_layer) {
// export let BC_TERRAIN; // export let BC_TERRAIN;
export let BC_TERRAIN_SETTINGS = { export let BC_TERRAIN_SETTINGS = {
tileSize: 16, tileSize: 16,
scale: 8.0, scale: 2,
totalSize: 16*8.0 totalSize: 16*2
} }
// export let BC_TERRAIN_VAULT = {}; // export let BC_TERRAIN_VAULT = {};
// export function setBC_TERRAIN(terrain) { // export function setBC_TERRAIN(terrain) {
@ -59,7 +60,7 @@ export let BC_TERRAIN_SETTINGS = {
export let BC_SPRITES_SETTINGS = { export let BC_SPRITES_SETTINGS = {
defaultSize: 16, defaultSize: 16,
scale: 8.0 scale: 2
}; };
// export let BC_CHUNKS_VAULT = {}; // export let BC_CHUNKS_VAULT = {};
@ -71,11 +72,11 @@ export let BC_CHUNKS_SETTINGS = {
export const BC_CAMERA = { export const BC_CAMERA = {
position: {x: 0.0, y: 0.0}, position: {x: 0.0, y: 0.0},
offset_position: {x: 0.0, y: 0.0}, offset_position: {x: 0.0, y: 0.0},
zoom: 1.0, zoom: 1.5,
targetZoom: 1.0, targetZoom: 1.5,
minZoom: 0.25, minZoom: 1.2,
maxZoom: 1.2, maxZoom: 4,
zoomStep: 0.05, zoomStep: 0.1,
}; };
export let PRNG = new Alea(); export let PRNG = new Alea();
@ -96,3 +97,16 @@ export let BC_CURRENT_SCENE;
export function setBC_CURRENT_SCENE(scene) { export function setBC_CURRENT_SCENE(scene) {
BC_CURRENT_SCENE = scene; BC_CURRENT_SCENE = scene;
}; };
/**
* @type {TerrainManger}
*/
export let BC_TERRAIN_MANAGER;
/**
*
* @param {TerrainManger} manager
*/
export function setBC_TERRAIN_MANAGER(manager) {
BC_TERRAIN_MANAGER = manager;
}

View File

@ -1,6 +1,7 @@
import { GameObject } from "../GameObject/GameObject"; import { GameObject } from "../GameObject/GameObject";
import { Container } from "../../pixi/pixi.mjs"; import { Container } from "../../pixi/pixi.mjs";
import { Point2D, PointInt2D } from "../Utils/Math.utils"; import { Point2D, PointInt2D } from "../Utils/Math.utils";
import { addGameObjectToGameState } from "../GameState/GameState";
export class SceneObject extends GameObject { export class SceneObject extends GameObject {
/** /**
@ -23,19 +24,30 @@ export class SceneObject extends GameObject {
* *
* @param {Boolean} tickAble * @param {Boolean} tickAble
*/ */
constructor(tickAble) constructor(tickAble) {
{
super(tickAble); super(tickAble);
// this._tickEnabled = tickAble; // this._tickEnabled = tickAble;
} }
/**
*
* @param {SceneObject} childObject
*/
addChild(childObject) {
if (childObject.isMarkedPendingKill()) return;
if (childObject.isInitialized() === false) {
addGameObjectToGameState(childObject);
}
this.drawObject.addChild(childObject.drawObject);
childObject.onSpawn();
}
/** /**
* Instantly* kills drawObject (by PIXI) and after several ticks kills SceneObject * Instantly* kills drawObject (by PIXI) and after several ticks kills SceneObject
* *
* * not sure about instant killing * * not sure about instant killing
*/ */
kill() kill() {
{
super.kill(); super.kill();
this.drawObject.destroy(); this.drawObject.destroy();
} }

View File

@ -47,14 +47,14 @@ export class PointInt2D
#x = 0; #x = 0;
#y = 0; #y = 0;
/** /**
* Point2D object * PointInt2D object
* @param {Number} x * @param {Number} x
* @param {Number} y * @param {Number} y
*/ */
constructor(x = 0, y = 0) constructor(x = 0, y = 0)
{ {
this.#x = x; this.setX(x);
this.#y = y; this.setY(y);
} }
getX() { getX() {
@ -62,14 +62,8 @@ export class PointInt2D
}; };
setX(x) { setX(x) {
if(x >= 0) this.#x = Math.trunc(x);
{ if(this.#x === -0) this.#x = 0;
this.#x = Math.floor(x);
}
else
{
this.#x = Math.ceil(x);
}
}; };
getY() { getY() {
@ -77,14 +71,8 @@ export class PointInt2D
}; };
setY(y) { setY(y) {
if(y >= 0) this.#y = Math.trunc(y);
{ if(this.#y === -0) this.#y = 0;
this.#y = Math.floor(y);
}
else
{
this.#y = Math.ceil(y);
}
}; };
/** /**
@ -93,16 +81,10 @@ export class PointInt2D
*/ */
divideBy(x) divideBy(x)
{ {
if(x > 0) if(x !== 0)
{ {
this.#x = Math.floor(this.#x / x); this.#x = Math.trunc(this.#x / x);
this.#y = Math.floor(this.#y / x); this.#y = Math.trunc(this.#y / x);
return true;
}
else if (x < 0)
{
this.#x = Math.ceil(this.#x / x);
this.#y = Math.ceil(this.#y / x);
return true; return true;
} }
return false; return false;
@ -110,16 +92,8 @@ export class PointInt2D
multiplyBy(x) multiplyBy(x)
{ {
if(x >= 0) this.#x = Math.trunc(this.#x * x);
{ this.#y = Math.trunc(this.#y * x);
this.#x = Math.floor(this.#x * x);
this.#y = Math.floor(this.#y * x);
}
else
{
this.#x = Math.ceil(this.#x * x);
this.#y = Math.ceil(this.#y * x);
}
} }
/** /**

View File

@ -0,0 +1,7 @@
/**
*
* @param {Array} array
*/
export function selectRandomValueFromArray(array, ent) {
return array[(Math.floor(ent * 999999999999) % array.length)];
}

View File

@ -1,10 +1,11 @@
import { BC_TERRAIN_SETTINGS } from "../GlobalVariables/GlobalVariables"; import { BC_TERRAIN_SETTINGS } from "../GlobalVariables/GlobalVariables";
import { ChunkStorageTypes } from "../WorldGeneration/WorldChunk/WorldGenChunk"; // import { ChunkStorageTypes } from "../WorldGeneration/WorldChunk/WorldGenChunk";
import { getTileAt } from "../WorldGeneration/WorldGen"; // 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"; import { TerrainTile } from "../WorldGenV2/Tiles/TerrainTile";
// import { TerrainTile } from "../WorldGeneration/WorldObjects/TerrainTile/TerrainTile";
class PathFinderNode { class PathFinderNode {
position; position;

View File

@ -1,7 +1,9 @@
import { BC_TERRAIN_MANAGER, BC_TERRAIN_SETTINGS } from "../../GlobalVariables/GlobalVariables";
import { PointInt2D } from "../../Utils/Math.utils"; import { PointInt2D } from "../../Utils/Math.utils";
import { PathFinder } from "../../Utils/PathFinding.utils"; import { PathFinder } from "../../Utils/PathFinding.utils";
import { getWorldChunkAt, worldCoordinatesToChunkLocalCoordinates } from "../../WorldGeneration/WorldGen"; import { TerrainTile } from "../../WorldGenV2/Tiles/TerrainTile";
import { TerrainTile } from "../../WorldGeneration/WorldObjects/TerrainTile/TerrainTile"; // import { getWorldChunkAt, worldCoordinatesToChunkLocalCoordinates } from "../../WorldGeneration/WorldGen";
// import { TerrainTile } from "../../WorldGeneration/WorldObjects/TerrainTile/TerrainTile";
export class NavigationGridTile export class NavigationGridTile
{ {
@ -59,8 +61,8 @@ export class NavigationGridChunk
getFromChunk(xWorld, yWorld) getFromChunk(xWorld, yWorld)
{ {
let coords = worldCoordinatesToChunkLocalCoordinates(xWorld, yWorld); let key = Math.floor(xWorld / BC_TERRAIN_SETTINGS.totalSize) * BC_TERRAIN_SETTINGS.totalSize + "_" + Math.floor(yWorld / BC_TERRAIN_SETTINGS.totalSize) * BC_TERRAIN_SETTINGS.totalSize;
return this._gridTiles.get(coords.x+"_"+coords.y); return this._gridTiles.get(key);
} }
/** /**
@ -107,10 +109,11 @@ export class NavigationGridChunk
*/ */
export function getNavigationGridTile(xWorld, yWorld) export function getNavigationGridTile(xWorld, yWorld)
{ {
let chunk = getWorldChunkAt(xWorld, yWorld); let chunk = BC_TERRAIN_MANAGER.getChunkAt(new PointInt2D(xWorld, yWorld));
// console.log(chunk);
if(chunk) if(chunk)
{ {
return chunk.navigationGridChunk.getFromChunk(xWorld, yWorld); return chunk.navigationChunk.getFromChunk(xWorld, yWorld);
} }
return undefined; return undefined;
} }

View File

@ -0,0 +1,63 @@
import { GameObject } from "../../GameObject/GameObject";
import { PointInt2D } from "../../Utils/Math.utils";
import { NavigationGridChunk } from "../../World/NavigationGrid/NavigationGrid";
import { TerrainTile } from "../Tiles/TerrainTile";
import { Tile } from "../Tiles/Tile";
export const CHUNK_LAYER_TERRAIN = 0;
export class Chunk extends GameObject
{
/**
* @type {Map<String, TerrainTile>}
*/
terrainLayer = new Map();
chunkPivotCoordinates = new PointInt2D();
/**
* @type {NavigationGridChunk}
*/
navigationChunk = null;
filled = false;
/**
*
* @param {Boolean} tickable
* @param {PointInt2D} pivot
*/
constructor(tickable, pivot)
{
super(tickable);
this.chunkPivotCoordinates = pivot;
}
/**
*
* @param {Number} layerId
* @param {Tile} object
*/
addToLayer(layerId, object)
{
switch (layerId) {
case CHUNK_LAYER_TERRAIN:
this.terrainLayer.set(object.tileKey, object);
break;
default:
break;
}
}
/**
*
* @param {Boolean} newVisibility
*/
changeVisibility(newVisibility)
{
for (const i of this.terrainLayer) {
i[1].drawObject.visible = newVisibility;
}
}
}

View File

@ -0,0 +1,55 @@
import { Noise } from "noisejs";
import { PRNG } from "../../../GlobalVariables/GlobalVariables";
import { Point2D } from "../../../Utils/Math.utils";
import { DWFBMSimplex2 } from "../../../Utils/Noise.utils";
import { NumberCue } from "../../../Utils/DataTypes.utils";
export class TileValue {
noiseValue = -1;
temperatureValue = 0;
tileId = -1;
constructor(noiseValue, tileId, temperatureValue) {
this.noiseValue = noiseValue;
this.tileId = tileId;
this.temperatureValue = temperatureValue;
}
}
export class TerrainGenerator {
cNoise = new Noise(Math.floor(PRNG() * 999999999999));
tNoise = new Noise(Math.floor(PRNG() * 999999999999));
/**
*
* @param {Noise} cNoise
* @param {Noise} tNoise
*/
constructor(cNoise, tNoise) {
if (cNoise) this.cNoise = cNoise;
if (tNoise) this.tNoise = tNoise;
}
/**
* returns tile value at point
* @param {Point2D} point
* @returns {TileValue}
*/
getValueAt(point) {
let mainValue = DWFBMSimplex2(this.cNoise, point.getX() / 1000.0, point.getY() / 1000.0, 3.0);
mainValue *= mainValue;
mainValue *= DWFBMSimplex2(this.cNoise, point.getX() / 100, point.getY() / 100, 3.0);
let temperatureValue = DWFBMSimplex2(this.tNoise, point.getX() / 10.0, point.getY() / 10.0, 3.0);
// let tileId = -1;
// if (mainValue < 0.25) {
// tileId = 0;
// } else if (mainValue < 0.3) {
// tileId = 1;
// } else if (mainValue < 0.8) {
// tileId = 2;
// } else {
// tileId = 3;
// }
return new TileValue(mainValue, -1, temperatureValue);
}
}

View File

@ -0,0 +1,77 @@
import { Rectangle } from "../../../pixi/pixi.mjs";
import { BC_CHUNKS_SETTINGS, BC_TERRAIN_SETTINGS } from "../../GlobalVariables/GlobalVariables";
import { SceneObject } from "../../SceneObjects/SceneObject";
import { Point2D, PointInt2D } from "../../Utils/Math.utils";
import { NavigationGridTile } from "../../World/NavigationGrid/NavigationGrid";
import { CHUNK_LAYER_TERRAIN, Chunk } from "../Chunk/Chunk";
import { TerrainTile } from "../Tiles/TerrainTile";
import { Tile } from "../Tiles/Tile";
import { TerrainGenerator } from "./Generator/TerrainGenerator";
import { createTerrainTileFromTileValue } from "./TerrainTilesFactory/TerrainTilesFactory";
export class Terrain extends SceneObject {
/**
* @type {Map<String, Chunk>}
*/
chunkStorage = new Map();
/**
* @type {Map<String, Chunk>}
*/
visibleChunks = new Map();
terrainGenerator = new TerrainGenerator();
/**
* adds chunk to terrain. Chunk object must contain pivot coordinates
* @param {Chunk} chunk
*/
addChunk(chunk) {
this.chunkStorage.set(chunk.chunkPivotCoordinates.getX() + "_" + chunk.chunkPivotCoordinates.getY(), chunk);
}
/**
* fills chunk with tiles
* @param {Chunk} chunk
*/
fillChunk(chunk) {
let ii = 0;
let jj = 0;
for (let i = BC_CHUNKS_SETTINGS.width * chunk.chunkPivotCoordinates.getX(); i < BC_CHUNKS_SETTINGS.width * (chunk.chunkPivotCoordinates.getX() + 1); i++) {
for (let j = BC_CHUNKS_SETTINGS.height * chunk.chunkPivotCoordinates.getY(); j < BC_CHUNKS_SETTINGS.height * (chunk.chunkPivotCoordinates.getY() + 1); j++) {
let result = this.terrainGenerator.getValueAt(new Point2D(i, j));
let resultTile = createTerrainTileFromTileValue(result, new PointInt2D(i * BC_TERRAIN_SETTINGS.totalSize - BC_TERRAIN_SETTINGS.totalSize / 2, j * BC_TERRAIN_SETTINGS.totalSize - BC_TERRAIN_SETTINGS.totalSize / 2));
resultTile.tileKey = resultTile.worldPosition.getX() + BC_TERRAIN_SETTINGS.totalSize / 2 + "_" + (resultTile.worldPosition.getY() + BC_TERRAIN_SETTINGS.totalSize / 2);
this.addChild(resultTile);
resultTile.drawObject.scale.set(BC_TERRAIN_SETTINGS.scale, BC_TERRAIN_SETTINGS.scale);
resultTile.drawObject.position.set(resultTile.worldPosition.getX(), resultTile.worldPosition.getY());
resultTile.drawObject.zIndex = resultTile.zOrder;
chunk.addToLayer(CHUNK_LAYER_TERRAIN, resultTile);
chunk.navigationChunk.addToChunk(new NavigationGridTile(
new PointInt2D(i * BC_TERRAIN_SETTINGS.totalSize, j * BC_TERRAIN_SETTINGS.totalSize),
resultTile.navigationCost,
resultTile.isObstacle,
resultTile
), resultTile.tileKey);
jj++;
}
ii++;
}
chunk.filled = true;
}
/**
*
* @param {PointInt2D} point in world coordinates
* @returns {Tile | undefined}
*/
getTileAt(point) {
let tileKey = Math.floor(point.getX() / BC_TERRAIN_SETTINGS.totalSize) * BC_TERRAIN_SETTINGS.totalSize + "_" + Math.floor(point.getY() / BC_TERRAIN_SETTINGS.totalSize) * BC_TERRAIN_SETTINGS.totalSize;
let chunkKey = Math.floor(point.getX() / (BC_TERRAIN_SETTINGS.totalSize * BC_CHUNKS_SETTINGS.width)) + "_" + Math.floor(point.getY() / (BC_TERRAIN_SETTINGS.totalSize * BC_CHUNKS_SETTINGS.height));
let chunk = this.chunkStorage.get(chunkKey);
// console.log(tileKey);
if (chunk) {
return chunk.terrainLayer.get(tileKey);
}
return undefined;
}
}

View File

@ -0,0 +1,79 @@
import { Rectangle } from "../../../../pixi/pixi.mjs";
import { PRNG } from "../../../GlobalVariables/GlobalVariables";
import { PointInt2D } from "../../../Utils/Math.utils";
import { selectRandomValueFromArray } from "../../../Utils/PRNG.utils";
import { TerrainTile } from "../../Tiles/TerrainTile";
import { TileValue } from "../Generator/TerrainGenerator";
const TERRAIN_TILE_WATER = 0;
const TERRAIN_TILE_SAND = 1;
const TERRAIN_TILE_GRASS = 2;
const TERRAIN_TILE_STONE = 3;
const TERRAIN_TILE_SOIL = 4;
const TERRAIN_TILE_WATER_Z = 1;
const TERRAIN_TILE_SAND_Z = 0;
const TERRAIN_TILE_GRASS_Z = 4;
const TERRAIN_TILE_STONE_Z = 2;
const TERRAIN_TILE_SOIL_Z = 3;
const TERRAIN_TILE_WATER_FRAMES = [new Rectangle(1, 1, 32, 32)];
const TERRAIN_TILE_SAND_FRAMES = [new Rectangle(1, 35, 32, 32), new Rectangle(35, 35, 32, 32), new Rectangle(69, 35, 32, 32), new Rectangle(103, 35, 32, 32)];
const TERRAIN_TILE_GRASS_FRAMES = [new Rectangle(1, 69, 32, 32), new Rectangle(35, 69, 32, 32), new Rectangle(69, 69, 32, 32)];
const TERRAIN_TILE_STONE_FRAMES = [new Rectangle(1, 103, 32, 32)];
const TERRAIN_TILE_SOIL_FRAMES = [new Rectangle(1, 137, 32, 32)];
const terrainNavigationCostList = {
0: 10, //water
1: 1.7, //sand
2: 1, //grass
3: 1.5, //stone
4: 1.6 //soil
};
/**
*
* @param {TileValue} value
* @param {PointInt2D} position
* @returns {TerrainTile | null}
*/
export function createTerrainTileFromTileValue(value, position) {
let t = new TerrainTile(false, position);
t.spriteSheetPath = "assets/images/world/world_terrain_atlas_overlay.png";
if (value.noiseValue < 0.5) {
t.frame = selectRandomValueFromArray(TERRAIN_TILE_WATER_FRAMES, value.noiseValue);
t.tileId = TERRAIN_TILE_WATER;
t.zOrder = TERRAIN_TILE_WATER_Z;
t.navigationCost = terrainNavigationCostList[TERRAIN_TILE_WATER];
} else if (value.noiseValue < 0.6)
{
t.frame = selectRandomValueFromArray(TERRAIN_TILE_SAND_FRAMES, value.noiseValue);
t.tileId = TERRAIN_TILE_SAND;
t.zOrder = TERRAIN_TILE_SAND_Z;
t.navigationCost = terrainNavigationCostList[TERRAIN_TILE_SAND];
} else if (value.noiseValue < 0.8)
{
if(value.temperatureValue >= 0.95 && value.noiseValue >= 0.75)
{
t.frame = selectRandomValueFromArray(TERRAIN_TILE_SOIL_FRAMES, value.noiseValue);
t.tileId = TERRAIN_TILE_SOIL;
t.zOrder = TERRAIN_TILE_SOIL_Z;
t.navigationCost = terrainNavigationCostList[TERRAIN_TILE_SOIL];
}
else
{
t.frame = selectRandomValueFromArray(TERRAIN_TILE_GRASS_FRAMES, value.noiseValue);
t.tileId = TERRAIN_TILE_GRASS;
t.zOrder = TERRAIN_TILE_GRASS_Z;
t.navigationCost = terrainNavigationCostList[TERRAIN_TILE_GRASS];
}
}
else
{
t.frame = selectRandomValueFromArray(TERRAIN_TILE_STONE_FRAMES, value.noiseValue);
t.tileId = TERRAIN_TILE_STONE;
t.zOrder = TERRAIN_TILE_STONE_Z;
t.navigationCost = terrainNavigationCostList[TERRAIN_TILE_STONE];
}
return t;
}

View File

@ -0,0 +1,139 @@
import { GameObject } from "../../GameObject/GameObject";
import { addGameObjectToGameState } from "../../GameState/GameState";
import { BC_CAMERA, BC_CHUNKS_SETTINGS, BC_TERRAIN_SETTINGS } from "../../GlobalVariables/GlobalVariables";
import { PointInt2D } from "../../Utils/Math.utils";
import { NavigationGridChunk } from "../../World/NavigationGrid/NavigationGrid";
import { Chunk } from "../Chunk/Chunk";
import { Terrain } from "../Terrain/Terrain";
import { Tile } from "../Tiles/Tile";
export class TerrainManger {
/**
* @type {Terrain}
*/
currentTerrain;
/**
* @type {Array<Chunk>}
*/
#chunkFillingQueue = [];
/**
* @type {Chunk}
*/
#focusedChunk = null;
#chunkVisibilityPeriod = 0.3;
#currentChunkVisibilityState = 0.0;
chunkVisibilityOptions = {
min: -2,
max: 3,
};
/**
*
* @returns {Terrain}
*/
createNewTerrain() {
let t = new Terrain(false);
addGameObjectToGameState(t);
return t;
}
/**
*
* @param {PointInt2D} pivot
* @returns {Chunk}
*/
createNewChunk(pivot) {
let t = new Chunk(false, pivot);
addGameObjectToGameState(t);
t.navigationChunk = new NavigationGridChunk();
return t;
}
tickHandler(ticker) {
// console.log(this.currentTerrain);
if (this.#chunkFillingQueue.length > 0) {
this.currentTerrain.fillChunk(this.#chunkFillingQueue.pop());
}
this.#currentChunkVisibilityState += ticker.deltaMS / 1000;
if (this.#currentChunkVisibilityState >= this.#chunkVisibilityPeriod) {
this.handleChunkVisibility();
this.#currentChunkVisibilityState = 0.0;
}
}
/**
* adds chunk to terrain. Chunk object must contain pivot coordinates. This function is a part of terrain manager interface.
* @param {Chunk} chunk
*/
addChunk(chunk) {
this.currentTerrain.addChunk(chunk);
if (!chunk.filled) this.#chunkFillingQueue.push(chunk);
}
/**
*
* @param {PointInt2D} point
*/
getChunkAt(point)
{
let w = BC_CHUNKS_SETTINGS.width * BC_TERRAIN_SETTINGS.totalSize;
let h = BC_CHUNKS_SETTINGS.height * BC_TERRAIN_SETTINGS.totalSize;
let chunkId = Math.floor(point.getX() / w) + "_" + Math.floor(point.getY() / h);
return this.currentTerrain.chunkStorage.get(chunkId);
}
/**
* update tile in terrain
* @param {Tile} tile new tile
* @param {Number} layerId chunk layer id
* @param {PointInt2D} coordinates world coordinates
*/
updateTile(tile, layer, coordinates) {}
addEntity() {}
/**
*
* @param {PointInt2D} point in world coordinates
* @returns {Tile | undefined}
*/
getTileAt(point) {
return this.currentTerrain.getTileAt(point);
}
handleChunkVisibility() {
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 cx = Math.floor(BC_CAMERA.position.x / w);
let cy = Math.floor(BC_CAMERA.position.y / h);
let chunkId = cx + "_" + cy;
if (!this.#focusedChunk || !GameObject.isEqual(this.#focusedChunk, this.currentTerrain.chunkStorage.get(chunkId))) {
for (const i of this.currentTerrain.visibleChunks) {
i[1].changeVisibility(false);
}
this.currentTerrain.visibleChunks.clear();
let t_chunkId;
let t_chunk;
for (let i = this.chunkVisibilityOptions.min; i < this.chunkVisibilityOptions.max; i++) {
for (let j = this.chunkVisibilityOptions.min; j < this.chunkVisibilityOptions.max; j++) {
t_chunkId = cx + i + "_" + (cy + j);
if (this.currentTerrain.chunkStorage.has(t_chunkId)) {
t_chunk = this.currentTerrain.chunkStorage.get(t_chunkId);
t_chunk.changeVisibility(true);
if (i === 0 && j === 0) this.#focusedChunk = t_chunk;
this.currentTerrain.visibleChunks.set(t_chunkId, t_chunk);
} else {
t_chunk = this.createNewChunk(new PointInt2D(cx + i, cy + j));
this.#chunkFillingQueue.push(t_chunk);
if (i === 0 && j === 0) this.#focusedChunk = t_chunk;
this.currentTerrain.addChunk(t_chunk);
this.currentTerrain.visibleChunks.set(t_chunkId, t_chunk);
}
}
}
}
}
}

View File

@ -0,0 +1,10 @@
import { SceneObject } from "../../SceneObjects/SceneObject";
import { Tile } from "./Tile";
export class TerrainTile extends Tile
{
constructor(tickable, position)
{
super(tickable, position);
}
}

View File

@ -0,0 +1,32 @@
import { Rectangle } from "../../../pixi/pixi.mjs";
import { SceneObject } from "../../SceneObjects/SceneObject";
import { PointInt2D } from "../../Utils/Math.utils";
import { getSpriteFromAtlas } from "../../Utils/Sprites.utils";
export class Tile extends SceneObject
{
tileId = 0;
spriteSheetPath = "";
frame = new Rectangle();
tileKey = "";
zOrder = -1;
navigationCost = -1;
isObstacle = false;
/**
*
* @param {Boolean} tickable
* @param {PointInt2D} position
*/
constructor(tickable, position)
{
super(tickable);
this.worldPosition = position;
}
onInit()
{
super.onInit();
this.drawObject = getSpriteFromAtlas(this.spriteSheetPath, this.frame);
};
}

View File

@ -0,0 +1,19 @@
// const FIRST_CHUNKS_SIZE = 3;
import { addGameObjectToGameState } from "../GameState/GameState";
import { BC_CAMERA, BC_CHUNKS_SETTINGS, BC_TERRAIN_MANAGER, BC_TERRAIN_SETTINGS } from "../GlobalVariables/GlobalVariables";
import { PointInt2D } from "../Utils/Math.utils";
import { Chunk } from "./Chunk/Chunk";
export function generateFirstChunks() {
let w = BC_CHUNKS_SETTINGS.width * BC_TERRAIN_SETTINGS.totalSize;
let h = BC_CHUNKS_SETTINGS.height * BC_TERRAIN_SETTINGS.totalSize;
for (let i = -1; i < 2; i++) {
for (let j = -1; j < 2; j++) {
let chunkPivot = new PointInt2D(Math.floor((BC_CAMERA.position.x + w * i) / w), Math.floor((BC_CAMERA.position.y + h * j) / h));
let chunk = BC_TERRAIN_MANAGER.createNewChunk(chunkPivot);
BC_TERRAIN_MANAGER.addChunk(chunk);
}
}
}

View File

@ -1,57 +0,0 @@
import {Noise} from "noisejs";
import { BC_CHUNKS_SETTINGS, PRNG } from "../../GlobalVariables/GlobalVariables";
import { clampNumber } from "../../Utils/Math.utils";
import { DWFBMSimplex2, FBMSimplex2 } from "../../Utils/Noise.utils";
/**
* Terrain generator
*
* cNoise 1:100 - continent type
* mNoise 1:20 - mountains
*/
let cNoise = new Noise(Math.floor(PRNG() * 999999999999));
let tNoise = new Noise(Math.floor(PRNG() * 999999999999));
export function genTerrain(xMin, xMax, yMin, yMax)
{
/**
* @type {Array<Number>}
*/
let terrainResult = new Array(BC_CHUNKS_SETTINGS.width * BC_CHUNKS_SETTINGS.height);
let mainValue = 0;
let mountainsValue = 0;
let temperatureValue = 0;
let ii = 0;
let jj = 0;
for (let i = xMin; i < xMax; i++) {
jj = 0;
for (let j = yMin; j < yMax; j++) {
mainValue = DWFBMSimplex2(cNoise, i / 1000.0, j / 1000.0, 3.0);
mainValue *= mainValue;
temperatureValue = DWFBMSimplex2(tNoise, i / 1000.0, j / 1000.0, 3.0);
// mainValue = Math.abs(temperatureValue - mainValue);
// if(temperatureValue > 0.5)
// {
mainValue *= DWFBMSimplex2(cNoise, i / 100, j / 100, 3.0);
// }
// mountainsValue = _normalizeNoiseValue(mNoise.simplex2(i / 200, j / 200));
// mainValue += clampNumber(Math.pow(mountainsValue * 2, 5), 0.0, 1.0);
// mainValue = clampNumber(mainValue, 0.0, 0.99);
terrainResult[ii * BC_CHUNKS_SETTINGS.width + jj] = mainValue;
// //soil
// if(continentValue > 0.5)
// {
// terrainResult[ii * BC_CHUNKS_SETTINGS.width + jj] = continentValue;
// }
// else //water
// {
// terrainResult[ii * BC_CHUNKS_SETTINGS.width + jj] = continentValue * 0.3;
// }
jj++;
}
ii++;
}
return terrainResult;
}

View File

@ -1,47 +0,0 @@
import { Rectangle } from "../../../pixi/pixi.mjs";
class _type_TerrainTilesMapPreDefinition
{
/**
* @type {Array<Rectangle>}
*/
textureVariations;
/**
* @type {Number}
*/
textureVariationsNumber;
/**
* @type {Number}
*/
zIndex;
}
/**
* @type {Array<_type_TerrainTilesMapPreDefinition>}
*/
export const TerrainTilesMapPreDefinition = {
//water
0: {
textureVariations: [new Rectangle(1, 1, 32, 32)],
textureVariationsNumber: 1,
zIndex: 4,
},
//sand
1: {
textureVariations: [new Rectangle(1, 35, 32, 32), new Rectangle(35, 35, 32, 32), new Rectangle(69, 35, 32, 32), new Rectangle(103, 35, 32, 32)],
textureVariationsNumber: 4,
zIndex: 2,
},
//grass
2: {
textureVariations: [new Rectangle(1, 69, 32, 32), new Rectangle(35, 69, 32, 32), new Rectangle(69, 69, 32, 32)],
textureVariationsNumber: 3,
zIndex: 3,
},
//stone
3: {
textureVariations: [new Rectangle(1, 103, 32, 32)],
textureVariationsNumber: 1,
zIndex: 1,
},
};

View File

@ -1,116 +0,0 @@
import { Container } from "../../../pixi/pixi.mjs";
import { SceneObject } from "../../SceneObjects/SceneObject";
import { worldCoordinatesToChunkIndexesCoordinates, worldCoordinatesToChunkLocalCoordinates } from "../WorldGen";
import { TerrainTile } from "../WorldObjects/TerrainTile/TerrainTile";
import { VegetationTile } from "../WorldObjects/VegetationTile/VegetationTile";
import { NavigationGridChunk } from "../../World/NavigationGrid/NavigationGrid";
export class ChunkStorageTypes
{
static TYPE_TERRAIN = 0;
static TYPE_VEGETATION = 1;
static TYPE_BUILDINGS = 2;
static TYPE_NPC = 3;
};
export class WorldChunk extends SceneObject
{
/**
* @type Map<String, TerrainTile>
*/
terrainStorage = new Map();
/**
* @type Map<String, VegetationTile>
*/
vegetationStorage = new Map();
/**
* @type Map<String, BuildingTile>
*/
buildingsStorage = new Map();
/**
* @type Map<String, any>
*/
npcStorage = new Map();
/**
* @type NavigationGridChunk
*/
navigationGridChunk = new NavigationGridChunk();
/**
* property to handle chunk visibility
*/
centralChunk = false;
/**
*
* @param {SceneObject} object
* @param {ChunkStorageTypes} storageType
* @param {String} objectId
*/
addToChunk(object, storageType, objectId)
{
switch (storageType) {
case ChunkStorageTypes.TYPE_TERRAIN:
this.terrainStorage.set(objectId, object);
break;
case ChunkStorageTypes.TYPE_VEGETATION:
this.vegetationStorage.set(objectId, object);
break;
case ChunkStorageTypes.TYPE_BUILDINGS:
this.buildingsStorage.set(objectId, object);
break;
default:
return false;
}
this.drawObject.addChild(object.drawObject);
return true;
}
/**
*
* @param {SceneObject} object
* @param {ChunkStorageTypes} storageType
* @param {String} objectId
*/
removeFromChunk(object, storageType, objectId)
{
switch (storageType) {
case ChunkStorageTypes.TYPE_TERRAIN:
this.terrainStorage.delete(objectId);
break;
case ChunkStorageTypes.TYPE_VEGETATION:
this.vegetationStorage.delete(objectId);
break;
case ChunkStorageTypes.TYPE_BUILDINGS:
this.buildingsStorage.delete(objectId);
break;
default:
return false;
}
this.drawObject.removeChild(object.drawObject);
return true;
};
/**
*
* @param {Number} xWorld
* @param {Number} yWorld
* @param {ChunkStorageTypes} storageType
* @returns SceneObject or undefined
*/
getFromChunk(xWorld, yWorld, storageType)
{
let coords = worldCoordinatesToChunkLocalCoordinates(xWorld, yWorld);
switch (storageType) {
case ChunkStorageTypes.TYPE_TERRAIN:
return this.terrainStorage.get(coords.x + "_" + coords.y);
case ChunkStorageTypes.TYPE_VEGETATION:
return this.vegetationStorage.get(coords.x + "_" + coords.y);
case ChunkStorageTypes.TYPE_BUILDINGS:
return this.buildingsStorage.get(coords.x + "_" + coords.y);
default:
return undefined;
}
}
};

View File

@ -1,79 +0,0 @@
import { BC_CAMERA, BC_CHUNKS_SETTINGS, BC_CURRENT_SCENE, BC_TERRAIN_SETTINGS } from "../../GlobalVariables/GlobalVariables";
import { fillWorldGenChunk, getWorldChunkById, setWorldChunkById, worldChunkExists } from "../WorldGen";
import { WorldChunk } from "../WorldChunk/WorldGenChunk";
export class WorldChunksVisibilityUpdater {
static _chunksFillingQueue = [];
static _currentIndex = -1;
/**
* @type Map<String, WorldChunk>
*/
static _visibleChunks = new Map();
static enableAutoWorldChunksGeneration = false;
static _chunksVisibilityRange = {
min: -2,
max: 3
};
// static {
// this.visibleChunks = new Map();
// };
static addChunkToFillingQueue(chunk, x, y) {
this._chunksFillingQueue.push({ chunk, x, y });
this._currentIndex++;
}
/**
* Ticker function
*/
static handleWorldChunkFilling() {
if (this._currentIndex < 0) return;
fillWorldGenChunk(
this._chunksFillingQueue[this._currentIndex].chunk,
this._chunksFillingQueue[this._currentIndex].x,
this._chunksFillingQueue[this._currentIndex].y
);
this._chunksFillingQueue.pop();
this._currentIndex--;
}
/**
* Ticker function
*/
static handleWorldChunksVisibility() {
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 cx = Math.floor(BC_CAMERA.position.x / w);
let cy = Math.floor(BC_CAMERA.position.y / h);
let chunkId = cx + "_" + cy;
if ((this._visibleChunks.has(chunkId) && !this._visibleChunks.get(chunkId).centralChunk) || !this._visibleChunks.has(chunkId)) {
for (const visChunk of this._visibleChunks) {
visChunk[1].drawObject.visible = false;
}
this._visibleChunks.clear();
for (let i = this._chunksVisibilityRange.min; i < this._chunksVisibilityRange.max; i++) {
for (let j = this._chunksVisibilityRange.min; j < this._chunksVisibilityRange.max; j++) {
let t_chunkId = (cx + i) + "_" + (cy + j);
if (worldChunkExists(t_chunkId)) {
let wChunk = getWorldChunkById(t_chunkId);
wChunk.centralChunk = (i === 0 && j === 0);
this._visibleChunks.set(t_chunkId, wChunk);
wChunk.drawObject.visible = true;
} else if (this.enableAutoWorldChunksGeneration) {
let newChunk = new WorldChunk(false);
BC_CURRENT_SCENE.addObjectToSceneWithInitialization(newChunk);
newChunk.drawObject.position.set(w * (cx + i), h * (cy + j));
this.addChunkToFillingQueue(newChunk, cx + i, cy + j);
this._visibleChunks.set(t_chunkId, newChunk);
newChunk.drawObject.visible = true;
newChunk.centralChunk = (i === 0 && j === 0);
setWorldChunkById(newChunk, t_chunkId);
}
}
}
}
}
}

View File

@ -1,269 +0,0 @@
import { Noise } from "noisejs";
import { Rectangle } from "../../pixi/pixi.mjs";
import { BC_CAMERA, BC_CHUNKS_SETTINGS, BC_CURRENT_SCENE, BC_SPRITES_SETTINGS, BC_TERRAIN_SETTINGS, PRNG } from "../GlobalVariables/GlobalVariables";
import { NumberCue, RGBColor } from "../Utils/DataTypes.utils";
import { ChunkStorageTypes, WorldChunk } from "./WorldChunk/WorldGenChunk";
import { TerrainTile, TerrainTileProps } from "./WorldObjects/TerrainTile/TerrainTile";
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 { NavigationGridChunk, NavigationGridTile } from "../World/NavigationGrid/NavigationGrid";
import { genTerrain } from "./TerrainGenerator/TerrainGenerator";
import { TerrainTilesMapPreDefinition } from "./TerrainPredefines/TerrainPredefines";
/**
* @type Map<String, WorldChunk>
*/
const WorldChunksStorage = new Map();
/* #### REWRITE PART START ####*/
const terrainSpriteList = {
0: { x: 20, y: 20 }, //water
1: { x: 0, y: 20 }, //sand
2: { x: 0, y: 0 }, //grass
3: { x: 20, y: 0 }, //stone
};
const terrainTypeList = {
0: "ter_water", //water
1: "ter_sand", //sand
2: "ter_grass", //grass
3: "ter_stone", //stone
};
const terrainNavigationCostList = {
0: 10, //water
1: 1.7, //sand
2: 1, //grass
3: 1.5, //stone
};
const grassVegetationSpriteList = {
0: { x: 10, y: 11 },
1: { x: 11, y: 11 },
2: { x: 12, y: 11 },
3: { x: 13, y: 11 },
4: { x: 14, y: 11 },
5: { x: 15, y: 11 },
6: { x: 16, y: 11 },
7: { x: 17, y: 11 },
8: { x: 18, y: 11 },
9: { x: 19, y: 11 },
10: { x: 0, y: 12 },
11: { x: 1, y: 12 },
12: { x: 2, y: 12 },
13: { x: 3, y: 12 },
14: { x: 7, y: 13 },
15: { x: 7, y: 12 },
16: { x: 8, y: 12 },
17: { x: 9, y: 12 },
};
const grassVegResourcesList = {
0: { type: "grass", num: 10 / 5 },
1: { type: "grass", num: 9 / 5 },
2: { type: "grass", num: 8 / 5 },
3: { type: "grass", num: 7 / 5 },
4: { type: "grass", num: 4 / 5 },
5: { type: "grass", num: 4 / 5 },
6: { type: "grass", num: 5 / 5 },
7: { type: "grass", num: 3 / 5 },
8: { type: "grass", num: 2 / 5 },
9: { type: "grass", num: 1 / 5 },
10: { type: "grass", num: 2 / 5 },
11: { type: "grass", num: 2 / 5 },
12: { type: "grass", num: 2 / 5 },
13: { type: "grass", num: 2 / 5 },
14: { type: "stone", num: 1 / 5 },
15: { type: "wood", num: 2 / 5 },
16: { type: "wood", num: 2 / 5 },
17: { type: "wood", num: 2 / 5 },
};
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) {
let ws = BC_TERRAIN_SETTINGS.tileSize * BC_TERRAIN_SETTINGS.scale;
let hs = BC_TERRAIN_SETTINGS.tileSize * BC_TERRAIN_SETTINGS.scale;
return { x: Math.floor(x / ws), y: Math.floor(y / hs) };
}
export function worldCoordinatesToChunkLocalCoordinates(x, y) {
let ws = BC_TERRAIN_SETTINGS.tileSize * BC_TERRAIN_SETTINGS.scale;
let hs = BC_TERRAIN_SETTINGS.tileSize * BC_TERRAIN_SETTINGS.scale;
if (x < 0 && y >= 0) {
return {
x: (BC_CHUNKS_SETTINGS.width - (Math.ceil(Math.abs(x) / ws) % BC_CHUNKS_SETTINGS.width)) % BC_CHUNKS_SETTINGS.width,
y: Math.floor(Math.abs(y) / hs) % BC_CHUNKS_SETTINGS.height,
};
} else if (x < 0 && y < 0)
return {
x: (BC_CHUNKS_SETTINGS.width - (Math.ceil(Math.abs(x) / ws) % BC_CHUNKS_SETTINGS.width)) % BC_CHUNKS_SETTINGS.width,
y: (BC_CHUNKS_SETTINGS.height - (Math.ceil(Math.abs(y) / hs) % BC_CHUNKS_SETTINGS.height)) % BC_CHUNKS_SETTINGS.height,
};
else if (x >= 0 && y < 0)
return {
x: Math.floor(Math.abs(x) / ws) % BC_CHUNKS_SETTINGS.width,
y: (BC_CHUNKS_SETTINGS.height - (Math.ceil(Math.abs(y) / hs) % BC_CHUNKS_SETTINGS.height)) % BC_CHUNKS_SETTINGS.height,
};
else {
return {
x: Math.floor(Math.abs(x) / ws) % BC_CHUNKS_SETTINGS.width,
y: Math.floor(Math.abs(y) / hs) % BC_CHUNKS_SETTINGS.height,
};
}
}
export function getWorldChunkAt(xWorld, yWorld) {
let t = worldCoordinatesToChunkIndex(xWorld, yWorld);
return WorldChunksStorage.get(t.x + "_" + t.y);
}
export function getWorldChunkById(id) {
return WorldChunksStorage.get(id);
}
/**
*
* @param {Number} xWorld
* @param {Number} yWorld
* @param {ChunkStorageTypes} storageType
* @returns {}
*/
export function getTileAt(xWorld, yWorld, storageType) {
let c = getWorldChunkAt(xWorld, yWorld);
if (!c) return undefined;
return c.getFromChunk(xWorld, yWorld, storageType);
}
export function worldChunkExists(id) {
return WorldChunksStorage.has(id);
}
export function setWorldChunkById(chunk, id) {
WorldChunksStorage.set(id, chunk);
}
let noise = new Noise(Math.floor(PRNG() * 188822321));
let noiseErosion = new Noise(Math.floor(PRNG() * 327749029));
let noiseBiomes = new Noise(Math.floor(PRNG() * 927472011));
let terrainCue = new NumberCue([0, 1, 2, 3, 3], [0.0, 0.25, 0.5, 0.75, 1.1]);
let terrainTintCue = new NumberCue([0.9, 1, 1, 0.95, 0.9, 1, 0.93, 1], [0.0, 0.45, 0.45, 0.5, 0.5, 0.9, 0.9, 1.1]);
/**
*
* @param {WorldChunk} chunk chunk to fill
* @param {Number} x ceiled coordinates of left-upper corner
* @param {Number} y ceiled coordinates of left-upper corner
*/
export function fillWorldGenChunk(chunk, x, y) {
let ii = 0;
let jj = 0;
let terrainData = genTerrain(BC_CHUNKS_SETTINGS.width * x, BC_CHUNKS_SETTINGS.width * (x + 1), BC_CHUNKS_SETTINGS.height * y, BC_CHUNKS_SETTINGS.height * (y + 1));
// console.log(terrainData);
for (let i = BC_CHUNKS_SETTINGS.width * x; i < BC_CHUNKS_SETTINGS.width * (x + 1); i++) {
jj = 0;
for (let j = BC_CHUNKS_SETTINGS.height * y; j < BC_CHUNKS_SETTINGS.height * (y + 1); j++) {
// let res = (noise.simplex2(i * 0.025, j * 0.025) + 1) / 2;
let res;
res = terrainData[ii * BC_CHUNKS_SETTINGS.width + jj];
// let resR = (noiseErosion.simplex2(i * 0.3, j * 0.3) + 1) / 2;
// let resB = (noiseBiomes.simplex2(i * 0.01, j * 0.01) + 1) / 2;
// if (resB > 0.7) {
// res = clampNumber(res - resR / 4, 0.0, 0.99);
// }
// if (resB > 0.5 && res < 0.9 && res >= 0.5) {
// res = clampNumber(res + resR / 4, 0.0, 0.99);
// }
let sTint = new RGBColor(255, 255, 255).multiplyByNumber(terrainTintCue.getValueAt(res)).toNumber();
res = Math.floor(terrainCue.getValueAt(res));
let terrainTile = new TerrainTile(false);
let tilePreDefines = TerrainTilesMapPreDefinition[res];
terrainTile.spriteSheetPath = "assets/images/world/world_terrain_atlas_overlay.png";
terrainTile.frame = tilePreDefines.textureVariations[Math.floor(PRNG() * (tilePreDefines.textureVariationsNumber - 1))];
terrainTile.props = new TerrainTileProps(terrainTypeList[res], res * 5, terrainNavigationCostList[res]);
terrainTile.worldPosition = new Point2D(
i * BC_TERRAIN_SETTINGS.scale * BC_TERRAIN_SETTINGS.tileSize,
j * BC_TERRAIN_SETTINGS.scale * BC_TERRAIN_SETTINGS.tileSize
);
addGameObjectToGameState(terrainTile);
terrainTile.drawObject.tint = sTint;
terrainTile.drawObject.zIndex = 1 + tilePreDefines.zIndex;
// terrainTile.drawObject.pivot.set(BC_SPRITES_SETTINGS.defaultSize * 0.5, BC_SPRITES_SETTINGS.defaultSize * 0.5);
terrainTile.drawObject.position.set(16 * BC_SPRITES_SETTINGS.scale * (ii) - 8 * BC_SPRITES_SETTINGS.scale, 16 * BC_SPRITES_SETTINGS.scale * (jj) - 8 * BC_SPRITES_SETTINGS.scale);
terrainTile.drawObject.scale.set(BC_SPRITES_SETTINGS.scale, BC_SPRITES_SETTINGS.scale);
chunk.addToChunk(terrainTile, ChunkStorageTypes.TYPE_TERRAIN, ii + "_" + jj);
chunk.navigationGridChunk.addToChunk(
new NavigationGridTile(
new PointInt2D(i * BC_TERRAIN_SETTINGS.scale * BC_TERRAIN_SETTINGS.tileSize, j * BC_TERRAIN_SETTINGS.scale * BC_TERRAIN_SETTINGS.tileSize),
terrainNavigationCostList[res],
terrainNavigationCostList[res] > 100,
terrainTile
),
ii + "_" + jj
);
// NavigationGrid.addToNavigationGrid(new PointInt2D(ii, jj), terrainNavigationCostList[res], terrainNavigationCostList[res] > 100);
if (res === 2 && PRNG() > 0.9) {
let rv = Math.floor(PRNG() * 18);
let vegetationTile = new VegetationTile(false);
vegetationTile.spriteSheetPath = "assets/images/world/vegetation_ts.png";
vegetationTile.frame = new Rectangle(16 * grassVegetationSpriteList[rv].x, 16 * grassVegetationSpriteList[rv].y, 16, 16);
vegetationTile.props = new VegetationTileProps("vegetation", grassVegResourcesList[rv]);
vegetationTile.worldPosition = new Point2D(
i * BC_TERRAIN_SETTINGS.scale * BC_TERRAIN_SETTINGS.tileSize,
j * BC_TERRAIN_SETTINGS.scale * BC_TERRAIN_SETTINGS.tileSize
);
addGameObjectToGameState(vegetationTile);
vegetationTile.drawObject.tint = sTint;
vegetationTile.drawObject.zIndex = 10;
vegetationTile.drawObject.position.set(16 * BC_SPRITES_SETTINGS.scale * ii, 16 * BC_SPRITES_SETTINGS.scale * jj);
vegetationTile.drawObject.scale.set(BC_SPRITES_SETTINGS.scale, BC_SPRITES_SETTINGS.scale);
chunk.addToChunk(vegetationTile, ChunkStorageTypes.TYPE_VEGETATION, ii + "_" + jj);
chunk.navigationGridChunk.changeNavigationGridTileSettings(ii + "_" + jj, (tile)=>{
tile.movementCost *= 1.5;
});
jj++;
continue;
}
jj++;
}
ii++;
}
}
export function createFirstWorldChunks() {
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;
for (let i = -2; i < 3; i++) {
for (let j = -2; j < 3; j++) {
let chunkXCeiled = Math.floor((BC_CAMERA.position.x + w * i) / w);
let chunkYCeiled = Math.floor((BC_CAMERA.position.y + h * j) / h);
let chunkId = chunkXCeiled + "_" + chunkYCeiled;
let chunk = new WorldChunk(false);
// chunk.navigationGridChunk = new NavigationGridChunk();
chunk.drawObject.position.set(w * chunkXCeiled, h * chunkYCeiled);
chunk.props = { id: chunkId };
BC_CURRENT_SCENE.addObjectToSceneWithInitialization(chunk);
fillWorldGenChunk(chunk, chunkXCeiled, chunkYCeiled);
WorldChunksStorage.set(chunkId, chunk);
}
}
WorldChunksVisibilityUpdater.enableAutoWorldChunksGeneration = true;
}
/* #### REWRITE PART END ####*/

View File

@ -1,41 +0,0 @@
import { Rectangle } from "../../../../pixi/pixi.mjs";
import { SceneObject } from "../../../SceneObjects/SceneObject";
import { getSpriteFromAtlas } from "../../../Utils/Sprites.utils";
export class BuildingTileProps
{
/**
* @type String
*/
type;
/**
* @type Number
*/
price;
/**
*
* @param {String} type
* @param {Number} price
*/
constructor(type = "", price = 0)
{
this.type = type;
this.price = price;
};
}
export class BuildingTile extends SceneObject
{
props = new BuildingTileProps();
spriteSheetPath = "";
frame = new Rectangle();
onInit()
{
super.onInit();
this.drawObject = getSpriteFromAtlas(this.spriteSheetPath, this.frame);
};
};

View File

@ -1,49 +0,0 @@
import { Rectangle } from "../../../../pixi/pixi.mjs";
import { SceneObject } from "../../../SceneObjects/SceneObject";
import { getSpriteFromAtlas } from "../../../Utils/Sprites.utils";
export class TerrainTileProps
{
/**
* @type String
*/
type;
/**
* @type Number
*/
temperature;
/**
* @type Number
*/
navigationCost = 1000;
/**
*
* @param {String} type
* @param {Number} temperature
* @param {Number} navigationCost
*/
constructor(type = "", temperature = 0, navigationCost = 0)
{
this.type = type;
this.temperature = temperature;
this.navigationCost = navigationCost;
};
}
export class TerrainTile extends SceneObject
{
props = new TerrainTileProps();
spriteSheetPath = "";
frame = new Rectangle();
onInit()
{
super.onInit();
this.drawObject = getSpriteFromAtlas(this.spriteSheetPath, this.frame);
};
};

View File

@ -1,53 +0,0 @@
import { Rectangle } from "../../../../pixi/pixi.mjs";
import { GameObject } from "../../../GameObject/GameObject";
import { PRNG } from "../../../GlobalVariables/GlobalVariables";
import { SceneObject } from "../../../SceneObjects/SceneObject";
import { getSpriteFromAtlas } from "../../../Utils/Sprites.utils";
import { ChunkStorageTypes } from "../../WorldChunk/WorldGenChunk";
export class VegetationTileProps
{
/**
* @type String
*/
type;
/**
* @type any
*/
resourcesList;
/**
*
* @param {String} type
* @param {any} resourcesList
*/
constructor(type = "", resourcesList = {})
{
this.type = type;
this.resourcesList = resourcesList;
};
}
export class VegetationTile extends SceneObject
{
props = new VegetationTileProps();
spriteSheetPath = "";
frame = new Rectangle();
/**
*
* @param {Boolean} tickAble
*/
constructor(tickAble = false)
{
super(tickAble);
}
onInit()
{
super.onInit();
this.drawObject = getSpriteFromAtlas(this.spriteSheetPath, this.frame);
};
};