import { Noise } from "noisejs"; import { BC_CAMERA, BC_CHUNKS_SETTINGS, BC_SPRITES_SETTINGS, BC_TERRAIN_SETTINGS, PRNG } from "../GlobalVariables/GlobalVariables"; import { clampNumber, integerDivision, mapRange } from "../Utils/Math.utils"; import { addToViewport } from "../Utils/World.utils"; import { WorldChunk, createWorldChunkContainer } from "../WorldChunk/WorldChunk"; import { getSpriteFromAtlas } from "../Utils/Sprites.utils"; import * as PIXI from "../../pixi/pixi.mjs"; import { BuildingsObjectProps, TerrainObjectProps, VegetationObjectProps, VisibleChunkProps } from "./ObjectsPropsSchemes"; import { NumberCue, RGBColor, Vault } from "../Utils/DataTypes.utils"; import { addChunkToFillQueue } from "./ChunkFillQueue"; // import {WorldChunk} from "../Types/WorldGenerationTypes"; const terrainSpriteList = { 0: { x: 21, y: 21 }, //water 1: { x: 2, y: 21 }, //sand 2: { x: 2, y: 2 }, //grass 3: { x: 21, y: 2 }, //stone }; const terrainTypeList = { 0: "ter_water", //water 1: "ter_sand", //sand 2: "ter_grass", //grass 3: "ter_stone", //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 sandVegetationSpriteList = { 0: { x: 14, y: 10 }, 1: { x: 7, y: 13 }, 2: { x: 6, y: 13 }, 3: { x: 5, y: 13 }, 4: { x: 4, y: 13 }, 5: { x: 3, y: 13 }, }; const stoneVegetationSpriteList = { 0: { x: 5, y: 13 }, 1: { x: 4, y: 13 }, 2: { x: 3, y: 13 }, }; 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 }, }; const sandVegResourcesList = { 0: { type: "grass", num: 4 / 5 }, 1: { type: "stone", num: 1 / 5 }, 2: { type: "stone", num: 3 / 5 }, 3: { type: "stone", num: 4 / 5 }, 4: { type: "stone", num: 5 / 5 }, 5: { type: "stone", num: 5 / 5 }, }; const stoneVegResourcesList = { 0: { type: "stone", num: 4 / 5 }, 1: { type: "stone", num: 5 / 5 }, 2: { type: "stone", num: 5 / 5 }, }; export const WORLD_CHUNKS = new Vault(); let VISIBLE_CHUNKS = new Vault(); 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; 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.floor(Math.abs(x) / ws) % BC_CHUNKS_SETTINGS.width) - 1, y: Math.floor(Math.abs(y) / hs) % BC_CHUNKS_SETTINGS.height, }; else if (x < 0 && y < 0) return { x: BC_CHUNKS_SETTINGS.width - (Math.floor(Math.abs(x) / ws) % BC_CHUNKS_SETTINGS.width) - 1, y: BC_CHUNKS_SETTINGS.height - (Math.floor(Math.abs(y) / hs) % BC_CHUNKS_SETTINGS.height) - 1, }; else if (x > 0 && y < 0) return { x: Math.floor(Math.abs(x) / ws) % BC_CHUNKS_SETTINGS.width, y: BC_CHUNKS_SETTINGS.height - (Math.floor(Math.abs(y) / hs) % BC_CHUNKS_SETTINGS.height) - 1, }; else return { x: Math.floor(Math.abs(x) / ws) % BC_CHUNKS_SETTINGS.width, y: Math.floor(Math.abs(y) / hs) % BC_CHUNKS_SETTINGS.height, }; } /** * * @param {Number} x world coordinates * @param {Number} y world coordinates */ export function getChunk(x, y) { let t = worldCoordinatesToChunkIndex(x, y); if (WORLD_CHUNKS.existsKey(t.x + "_" + t.y)) return WORLD_CHUNKS.get(t.x + "_" + t.y); else return undefined; } let enableAutoGeneration = false; export function updateChunksVisibility() { 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 ((VISIBLE_CHUNKS.existsKey(chunkId) && !VISIBLE_CHUNKS.get(chunkId).central) || !VISIBLE_CHUNKS.existsKey(chunkId)) { VISIBLE_CHUNKS.forAll((vis_chunk) => { vis_chunk.chunkRef.chunk.visible = false; }); VISIBLE_CHUNKS.clear(); for (let i = -2; i < 3; i++) { for (let j = -2; j < 3; j++) { let t_chunkId = cx + i + "_" + (cy + j); if (WORLD_CHUNKS.existsKey(t_chunkId)) { VISIBLE_CHUNKS.set(t_chunkId, new VisibleChunkProps(WORLD_CHUNKS.get(t_chunkId), i === 0 && j === 0)); VISIBLE_CHUNKS.get(t_chunkId).chunkRef.chunk.visible = true; } else if (enableAutoGeneration) { // console.log(t_chunkId); let newChunk = createWorldChunkContainer(); // chunkRef.isRenderGroup = true; newChunk.position.set(w * (cx + i), h * (cy + j)); // console.log(w * chunkXCeiled, h * chunkYCeiled); let chunk0 = new WorldChunk( newChunk, newChunk.getChildAt(0), newChunk.getChildAt(1), newChunk.getChildAt(2), // newChunk.getChildAt(3), new Vault("terrain"), new Vault("vegetation"), new Vault("buildings") ); // fillChunk(chunk0, cx + i, cy + j); addChunkToFillQueue(chunk0, cx + i, cy + j); WORLD_CHUNKS.set(t_chunkId, chunk0); addToViewport(newChunk); VISIBLE_CHUNKS.set(t_chunkId, new VisibleChunkProps(WORLD_CHUNKS.get(t_chunkId), i === 0 && j === 0)); VISIBLE_CHUNKS.get(t_chunkId).chunkRef.chunk.visible = true; } } } } } /** * * @param {WorldChunk} chunk from WORLD_CHUNKS * @param {PIXI.Container} object * @param {TerrainObjectProps} props * @param {Number} ceiledX * @param {Number} ceiledY */ export function addToTerrain(chunk, object, props, ceiledX, ceiledY) { chunk.terrainLayer.addChild(object); chunk.terrainObjectsVault.set(ceiledX + "_" + ceiledY, new TerrainObjectProps(object, { ...props })); } /** * * @param {WorldChunk} chunk from WORLD_CHUNKS * @param {PIXI.Container} object * @param {VegetationObjectProps} props * @param {Number} ceiledX * @param {Number} ceiledY */ export function addToVegetation(chunk, object, props, ceiledX, ceiledY) { chunk.vegetationLayer.addChild(object); chunk.vegetationObjectsVault.set(ceiledX + "_" + ceiledY, new VegetationObjectProps(object, { ...props })); } /** * * @param {WorldChunk} chunk from WORLD_CHUNKS * @param {PIXI.Container} object * @param {BuildingsObjectProps} props * @param {Number} ceiledX * @param {Number} ceiledY */ export function addToBuildings(chunk, object, props, ceiledX, ceiledY) { chunk.buildingsLayer.addChild(object); chunk.buildingsObjectsVault.set(ceiledX + "_" + ceiledY, new BuildingsObjectProps(object, { ...props })); } /** * * @param {Number} x world coordinates * @param {Number} y world coordinates * @param {PIXI.Container} object object to remove */ export function removeFromTerrain(x, y, object) { let chunkIndex = worldCoordinatesToChunkIndex(x, y); let chunkId = chunkIndex.x + "_" + chunkIndex.y; if (WORLD_CHUNKS.existsKey(chunkId)) { let objLocalPos = worldCoordinatesToChunkIndexesCoordinates(x, y); let objId = objLocalPos.x + "_" + objLocalPos.y; WORLD_CHUNKS.get(chunkId).terrainLayer.removeChild(object); WORLD_CHUNKS.get(chunkId).terrainObjectsVault.del(objId); object.destroy(); } } /** * * @param {Number} x world coordinates * @param {Number} y world coordinates * @param {PIXI.Container} object object to remove */ export function removeFromVegetation(x, y, object) { let chunkIndex = worldCoordinatesToChunkIndex(x, y); let chunkId = chunkIndex.x + "_" + chunkIndex.y; if (WORLD_CHUNKS.existsKey(chunkId)) { let objLocalPos = worldCoordinatesToChunkIndexesCoordinates(x, y); let objId = objLocalPos.x + "_" + objLocalPos.y; WORLD_CHUNKS.get(chunkId).vegetationLayer.removeChild(object); WORLD_CHUNKS.get(chunkId).vegetationObjectsVault.del(objId); object.destroy(); } } /** * * @param {Number} x world coordinates * @param {Number} y world coordinates * @param {PIXI.Container} object object to remove */ export function removeFromBuildings(x, y, object) { let chunkIndex = worldCoordinatesToChunkIndex(x, y); let chunkId = chunkIndex.x + "_" + chunkIndex.y; if (WORLD_CHUNKS.existsKey(chunkId)) { let objLocalPos = worldCoordinatesToChunkIndexesCoordinates(x, y); let objId = objLocalPos.x + "_" + objLocalPos.y; WORLD_CHUNKS.get(chunkId).buildingsLayer.removeChild(object); WORLD_CHUNKS.get(chunkId).buildingsObjectsVault.del(objId); object.destroy(); } } /** * * @param {Number} x world coordinates * @param {Number} y world coordinates */ export function getObjectFromTerrainLayer(x, y) { // let t_ceiled = {x: Math.floor(t.x / (BC_TERRAIN_SETTINGS.tileSize*BC_TERRAIN_SETTINGS.scale)), y: Math.floor(t.y / (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 ws = BC_TERRAIN_SETTINGS.tileSize * BC_TERRAIN_SETTINGS.scale; let hs = BC_TERRAIN_SETTINGS.tileSize * BC_TERRAIN_SETTINGS.scale; let chunkId = Math.floor(x / w) + "_" + Math.floor(y / h); let objectId = Math.floor(x / ws) + "_" + Math.floor(y / hs); if (WORLD_CHUNKS.existsKey(chunkId)) return WORLD_CHUNKS.get(chunkId).terrainObjectsVault.get(objectId); } /** * * @param {Number} x world coordinates * @param {Number} y world coordinates */ export function getObjectFromVegetationLayer(x, y) { // let t_ceiled = {x: Math.floor(t.x / (BC_TERRAIN_SETTINGS.tileSize*BC_TERRAIN_SETTINGS.scale)), y: Math.floor(t.y / (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 ws = BC_TERRAIN_SETTINGS.tileSize * BC_TERRAIN_SETTINGS.scale; let hs = BC_TERRAIN_SETTINGS.tileSize * BC_TERRAIN_SETTINGS.scale; let chunkId = Math.floor(x / w) + "_" + Math.floor(y / h); let objectId = Math.floor(x / ws) + "_" + Math.floor(y / hs); if (WORLD_CHUNKS.existsKey(chunkId)) return WORLD_CHUNKS.get(chunkId).vegetationObjectsVault.get(objectId); } /** * * @param {Number} x world coordinates * @param {Number} y world coordinates */ export function getObjectFromBuildingsLayer(x, y) { // let t_ceiled = {x: Math.floor(t.x / (BC_TERRAIN_SETTINGS.tileSize*BC_TERRAIN_SETTINGS.scale)), y: Math.floor(t.y / (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 ws = BC_TERRAIN_SETTINGS.tileSize * BC_TERRAIN_SETTINGS.scale; let hs = BC_TERRAIN_SETTINGS.tileSize * BC_TERRAIN_SETTINGS.scale; let chunkId = Math.floor(x / w) + "_" + Math.floor(y / h); let objectId = Math.floor(x / ws) + "_" + Math.floor(y / hs); if (WORLD_CHUNKS.existsKey(chunkId)) return WORLD_CHUNKS.get(chunkId).buildingsObjectsVault.get(objectId); } 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 = -1; i < 2; i++) { for (let j = -1; j < 2; 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; // console.log(chunkId); let chunkRef = createWorldChunkContainer(); // chunkRef.isRenderGroup = true; chunkRef.position.set(w * chunkXCeiled, h * chunkYCeiled); // console.log(w * chunkXCeiled, h * chunkYCeiled); let chunk0 = new WorldChunk( chunkRef, chunkRef.getChildAt(0), chunkRef.getChildAt(1), chunkRef.getChildAt(2), // chunkRef.getChildAt(3), new Vault("terrain"), new Vault("vegetation"), new Vault("buildings") ); fillChunk(chunk0, chunkXCeiled, chunkYCeiled); WORLD_CHUNKS.set(chunkId, chunk0); chunkRef.visible = false; addToViewport(chunkRef); // console.log(WORLD_CHUNKS) // console.log(chunkXCeiled, chunkYCeiled); } } enableAutoGeneration = true; } 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.45, 0.5, 0.9, 1.0]); 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.0]); export function fillChunk(chunk, x, y) { let ii = 0; let jj = 0; 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 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); } // res = Math.pow(res, 2); // console.log(resR); // let resB = (noiseBiomes.perlin2(i * 0.01, j * 0.01) + 1) / 2; // console.log(Math.pow(resB, 0.5)); // console.log(res); // res = clampNumber(res * resB, 0.0, 0.99); // if(resB < 0.5) // { // res = clampNumber(res / 2 , 0.0, 0.99); // } // else if(resB < 0.9) // { // res = clampNumber(res * 2, 0.0, 0.99); // } // res = Math.pow(res, 0.9); let sTint = new RGBColor(255, 255, 255).multiplyByNumber(terrainTintCue.getValueAt(res)).toNumber(); res = Math.floor(terrainCue.getValueAt(res)); let sprite = getSpriteFromAtlas( "assets/images/world/world_terrain_atlas.png", new PIXI.Rectangle(terrainSpriteList[res].x, terrainSpriteList[res].y, 16, 16) ); sprite.position.set(16 * BC_SPRITES_SETTINGS.scale * ii, 16 * BC_SPRITES_SETTINGS.scale * jj); sprite.scale.set(BC_SPRITES_SETTINGS.scale, BC_SPRITES_SETTINGS.scale); sprite.tint = sTint; addToTerrain(chunk, sprite, { type: terrainTypeList[res] }, i, j); // console.log(ii, jj); // addToTerrain(sprite, {x: i, y: j}, {type: terrainTypeList[res]}); if (res === 2 && PRNG() > 0.9) { let rv = Math.floor(PRNG() * 18); let veg = getSpriteFromAtlas( "assets/images/world/vegetation_ts.png", new PIXI.Rectangle(16 * grassVegetationSpriteList[rv].x, 16 * grassVegetationSpriteList[rv].y, 16, 16) ); veg.position.set(16 * BC_SPRITES_SETTINGS.scale * ii, 16 * BC_SPRITES_SETTINGS.scale * jj); veg.scale.set(BC_SPRITES_SETTINGS.scale, BC_SPRITES_SETTINGS.scale); veg.tint = sTint; addToVegetation(chunk, veg, { ...grassVegResourcesList[rv] }, i, j); jj++; continue; } if (res === 1 && PRNG() > 0.99) { let rv = Math.floor(PRNG() * 6); let veg = getSpriteFromAtlas( "assets/images/world/vegetation_ts.png", new PIXI.Rectangle(16 * sandVegetationSpriteList[rv].x, 16 * sandVegetationSpriteList[rv].y, 16, 16) ); veg.position.set(16 * BC_SPRITES_SETTINGS.scale * ii, 16 * BC_SPRITES_SETTINGS.scale * jj); veg.scale.set(BC_SPRITES_SETTINGS.scale, BC_SPRITES_SETTINGS.scale); veg.tint = sTint; addToVegetation(chunk, veg, { ...sandVegResourcesList[rv] }, i, j); jj++; continue; } if (res === 3 && PRNG() > 0.9) { let rv = Math.floor(PRNG() * 3); let veg = getSpriteFromAtlas( "assets/images/world/vegetation_ts.png", new PIXI.Rectangle(16 * stoneVegetationSpriteList[rv].x, 16 * stoneVegetationSpriteList[rv].y, 16, 16) ); veg.position.set(16 * BC_SPRITES_SETTINGS.scale * ii, 16 * BC_SPRITES_SETTINGS.scale * jj); veg.scale.set(BC_SPRITES_SETTINGS.scale, BC_SPRITES_SETTINGS.scale); veg.tint = sTint; addToVegetation(chunk, veg, { ...stoneVegResourcesList[rv] }, i, j); jj++; continue; } jj++; } ii++; } }