From b4c6b97ca4ba2fe5545532cc7eeae54f69bc9f1c Mon Sep 17 00:00:00 2001 From: TorgaW Date: Thu, 11 Apr 2024 02:49:14 +0300 Subject: [PATCH] fixed day-night cycle colors and changed world generation --- src/App.svelte | 3 + src/Game/Camera/Camera.js | 4 +- src/Game/Game.js | 10 +- src/Game/GlobalVariables/GlobalVariables.js | 6 +- src/Game/Utils/Math.utils.js | 7 + src/Game/World/DayNightCycle.js | 5 +- src/Game/WorldGeneration/ChunkFillQueue.js | 24 ++++ src/Game/WorldGeneration/WorldGeneration.js | 53 ++++++-- src/Test.js | 135 ++++++++++++++++++++ 9 files changed, 230 insertions(+), 17 deletions(-) create mode 100644 src/Game/WorldGeneration/ChunkFillQueue.js create mode 100644 src/Test.js diff --git a/src/App.svelte b/src/App.svelte index cab2516..0e323a6 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -74,6 +74,9 @@ ambientSound = s.ambient; musicSound = s.music; }); + + import {search} from "./Test"; + search();
diff --git a/src/Game/Camera/Camera.js b/src/Game/Camera/Camera.js index 14766f0..a00c33e 100644 --- a/src/Game/Camera/Camera.js +++ b/src/Game/Camera/Camera.js @@ -1,5 +1,6 @@ import { BC_CAMERA, BC_VIEWPORT } from "../GlobalVariables/GlobalVariables"; import { UICameraInfo } from "../UIPipes/UIPipes"; +import { interpolate, interpolateCos } from "../Utils/Math.utils"; export function moveVertically(tick, keyCode) { BC_CAMERA.position.y += (tick.deltaMS / 1000) * 800 * (keyCode === "KeyS" ? 1 : -1); @@ -15,8 +16,9 @@ export function moveHorizontally(tick, keyCode) { }); } -export function calculateViewportFromCamera() { +export function calculateViewportFromCamera(tick) { // BC_VIEWPORT.pivot.set(0.5, 0.5); + BC_CAMERA.zoom = interpolate(BC_CAMERA.zoom, BC_CAMERA.targetZoom, (tick.deltaMS / 1000) * 45); BC_VIEWPORT.position.set( Math.floor(((window.innerWidth / 2.0 / BC_CAMERA.zoom) - BC_CAMERA.position.x) * BC_CAMERA.zoom), Math.floor(((window.innerHeight / 2.0 / BC_CAMERA.zoom) - BC_CAMERA.position.y) * BC_CAMERA.zoom) diff --git a/src/Game/Game.js b/src/Game/Game.js index 0389366..bdd317f 100644 --- a/src/Game/Game.js +++ b/src/Game/Game.js @@ -23,6 +23,7 @@ import { import { handleBuildingsIncome, incBuildingCount } from "./Buildings/Buildings"; import { handleDayNightCycle } from "./World/DayNightCycle"; import { ambientDay, ambientMusic, ambientNight, handleSounds } from "./Sound/Sound"; +import { handleChunkFilling } from "./WorldGeneration/ChunkFillQueue"; export function generateWorld() { @@ -34,12 +35,12 @@ function setupGlobalInput() { window.addEventListener("wheel", (event) => { const delta = Math.sign(event.deltaY); if (delta > 0) { - BC_CAMERA.zoom = Number(clampNumber(BC_CAMERA.zoom - 0.1, 0.6, 1.2).toFixed(2)); + BC_CAMERA.targetZoom = Number(clampNumber(BC_CAMERA.targetZoom - BC_CAMERA.zoomStep, BC_CAMERA.minZoom, BC_CAMERA.maxZoom).toFixed(2)); } else { - BC_CAMERA.zoom = Number(clampNumber(BC_CAMERA.zoom + 0.1, 0.6, 1.2).toFixed(2)); + BC_CAMERA.targetZoom = Number(clampNumber(BC_CAMERA.targetZoom + BC_CAMERA.zoomStep, BC_CAMERA.minZoom, BC_CAMERA.maxZoom).toFixed(2)); } UICameraInfo.update((s) => { - s.zoom = BC_CAMERA.zoom; + s.zoom = BC_CAMERA.targetZoom; }); }); } @@ -223,6 +224,8 @@ export async function initGame() { await app.init({ resizeTo: window, antialias: false }); document.body.appendChild(app.canvas); setBC_APP(app); + app.ticker.targetFPMS = 0.14; + app.ticker.maxFPS = 140; await loadGameAssets(); UIMainPipe.update((s) => { @@ -249,6 +252,7 @@ export async function initGame() { app.ticker.add(inputControllerTick); app.ticker.add(calculateViewportFromCamera); app.ticker.add(updateChunksVisibility); + app.ticker.add(handleChunkFilling); app.ticker.add(profileFPS); app.ticker.add(handleBuildingsIncome); diff --git a/src/Game/GlobalVariables/GlobalVariables.js b/src/Game/GlobalVariables/GlobalVariables.js index 8cb55ec..ddb9fd8 100644 --- a/src/Game/GlobalVariables/GlobalVariables.js +++ b/src/Game/GlobalVariables/GlobalVariables.js @@ -60,7 +60,11 @@ export let BC_CHUNKS_SETTINGS = { export const BC_CAMERA = { position: {x: 0.0, y: 0.0}, offset_position: {x: 0.0, y: 0.0}, - zoom: 1.0 + zoom: 1.0, + targetZoom: 1.0, + minZoom: 0.25, + maxZoom: 1.2, + zoomStep: 0.05, }; export let PRNG = new Alea(); diff --git a/src/Game/Utils/Math.utils.js b/src/Game/Utils/Math.utils.js index 907732e..a6839b1 100644 --- a/src/Game/Utils/Math.utils.js +++ b/src/Game/Utils/Math.utils.js @@ -75,6 +75,13 @@ export function interpolate(x, y, a) { return x * (1 - a) + y * a; } +/** + * careful with delta time! it can be laggy + * @param {Number} x + * @param {Number} y + * @param {Number} a + * @returns + */ export function interpolateCos(x, y, a) { let m = (1-Math.cos(a*Math.PI))/2; return (x*(1-m)+y*m); diff --git a/src/Game/World/DayNightCycle.js b/src/Game/World/DayNightCycle.js index 5957703..ced6283 100644 --- a/src/Game/World/DayNightCycle.js +++ b/src/Game/World/DayNightCycle.js @@ -21,13 +21,14 @@ let dayColorsCue = new RGBCue( [ new RGBColor(1, 22, 46), new RGBColor(1, 66, 109), + new RGBColor(230, 109, 109), new RGBColor(255, 255, 255), new RGBColor(255, 255, 192), - new RGBColor(136, 99, 77), + new RGBColor(230, 134, 77), new RGBColor(1, 66, 109), new RGBColor(1, 22, 46), ], - [0.0, 0.15, 0.4, 0.75, 0.8, 0.9, 1.0], + [0.0, 0.15, 0.2, 0.4, 0.8, 0.85, 0.9, 1.0], "cos" ); diff --git a/src/Game/WorldGeneration/ChunkFillQueue.js b/src/Game/WorldGeneration/ChunkFillQueue.js new file mode 100644 index 0000000..db1ae04 --- /dev/null +++ b/src/Game/WorldGeneration/ChunkFillQueue.js @@ -0,0 +1,24 @@ +import { WorldChunk } from "../WorldChunk/WorldChunk"; +import { fillChunk } from "./WorldGeneration"; + +let chunkFillQueue = []; +let currentChunkIndex = -1; + +/** + * + * @param {WorldChunk} chunk + */ +export function addChunkToFillQueue(chunk, x, y) +{ + chunkFillQueue.push({chunk, x, y}); + currentChunkIndex++; +} + +export function handleChunkFilling(tick) { + // console.log(tick.deltaMS); + if(currentChunkIndex < 0) return; + fillChunk(chunkFillQueue[currentChunkIndex].chunk, chunkFillQueue[currentChunkIndex].x, chunkFillQueue[currentChunkIndex].y); + chunkFillQueue.pop(); + currentChunkIndex--; + +} diff --git a/src/Game/WorldGeneration/WorldGeneration.js b/src/Game/WorldGeneration/WorldGeneration.js index 3350b09..5c29149 100644 --- a/src/Game/WorldGeneration/WorldGeneration.js +++ b/src/Game/WorldGeneration/WorldGeneration.js @@ -1,12 +1,13 @@ import { Noise } from "noisejs"; import { BC_CAMERA, BC_CHUNKS_SETTINGS, BC_SPRITES_SETTINGS, BC_TERRAIN_SETTINGS, PRNG } from "../GlobalVariables/GlobalVariables"; -import { integerDivision } from "../Utils/Math.utils"; +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 { Vault } from "../Utils/DataTypes.utils"; +import { NumberCue, RGBColor, Vault } from "../Utils/DataTypes.utils"; +import { addChunkToFillQueue } from "./ChunkFillQueue"; // import {WorldChunk} from "../Types/WorldGenerationTypes"; const terrainSpriteList = { @@ -152,8 +153,8 @@ export function updateChunksVisibility() { vis_chunk.chunkRef.chunk.visible = false; }); VISIBLE_CHUNKS.clear(); - for (let i = -1; i < 2; i++) { - for (let j = -1; j < 2; j++) { + 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)); @@ -173,7 +174,8 @@ export function updateChunksVisibility() { new Vault("vegetation"), new Vault("buildings") ); - fillChunk(chunk0, cx + i, cy + j); + // 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)); @@ -357,24 +359,52 @@ export function createFirstWorldChunks() { enableAutoGeneration = true; } -let noise = new Noise(Math.floor(PRNG() * 18882232)); +let noise = new Noise(Math.floor(PRNG() * 188822321)); +let noiseErosion = new Noise(Math.floor(PRNG() * 327749029)); +let noiseBiomes = new Noise(Math.floor(PRNG() * 927472011)); -function fillChunk(chunk, x, y) { +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.04, j * 0.04) + 1) / 2; + 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 = Math.pow(res, 1.2); - res = Math.floor(res * 4); + // 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(16 * terrainSpriteList[res].x, 16 * 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]}); @@ -387,6 +417,7 @@ function fillChunk(chunk, x, y) { ); 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; @@ -400,6 +431,7 @@ function fillChunk(chunk, x, y) { ); 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; @@ -413,6 +445,7 @@ function fillChunk(chunk, x, y) { ); 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; diff --git a/src/Test.js b/src/Test.js new file mode 100644 index 0000000..e3a2fed --- /dev/null +++ b/src/Test.js @@ -0,0 +1,135 @@ +let cols = 5; //columns in the grid +let rows = 5; //rows in the grid + +let grid = new Array(cols); //array of all the grid points + +let openSet = []; //array containing unevaluated grid points +let closedSet = []; //array containing completely evaluated grid points + +let start; //starting grid point +let end; // ending grid point (goal) +let path = []; + +//heuristic we will be using - Manhattan distance +//for other heuristics visit - https://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html +function heuristic(position0, position1) { + let d1 = Math.abs(position1.x - position0.x); + let d2 = Math.abs(position1.y - position0.y); + + return d1 + d2; +} + +//constructor function to create all the grid points as objects containind the data for the points +function GridPoint(x, y) { + this.x = x; //x location of the grid point + this.y = y; //y location of the grid point + this.f = 0; //total cost function + this.g = 0; //cost function from start to the current grid point + this.h = 0; //heuristic estimated cost function from current grid point to the goal + this.neighbors = []; // neighbors of the current grid point + this.parent = undefined; // immediate source of the current grid point + + // update neighbors array for a given grid point + this.updateNeighbors = function (grid) { + let i = this.x; + let j = this.y; + if (i < cols - 1) { + this.neighbors.push(grid[i + 1][j]); + } + if (i > 0) { + this.neighbors.push(grid[i - 1][j]); + } + if (j < rows - 1) { + this.neighbors.push(grid[i][j + 1]); + } + if (j > 0) { + this.neighbors.push(grid[i][j - 1]); + } + }; +} + +//initializing the grid +function init() { + //making a 2D array + for (let i = 0; i < cols; i++) { + grid[i] = new Array(rows); + } + + for (let i = 0; i < cols; i++) { + for (let j = 0; j < rows; j++) { + grid[i][j] = new GridPoint(i, j); + } + } + + for (let i = 0; i < cols; i++) { + for (let j = 0; j < rows; j++) { + grid[i][j].updateNeighbors(grid); + } + } + + start = grid[0][0]; + end = grid[cols - 1][rows - 1]; + + openSet.push(start); + + console.log(grid); +} + +//A star search implementation + +export function search() { + init(); + while (openSet.length > 0) { + //assumption lowest index is the first one to begin with + let lowestIndex = 0; + for (let i = 0; i < openSet.length; i++) { + if (openSet[i].f < openSet[lowestIndex].f) { + lowestIndex = i; + } + } + let current = openSet[lowestIndex]; + + if (current === end) { + let temp = current; + path.push(temp); + while (temp.parent) { + path.push(temp.parent); + temp = temp.parent; + } + console.log("DONE!"); + // return the traced path + return path.reverse(); + } + + //remove current from openSet + openSet.splice(lowestIndex, 1); + //add current to closedSet + closedSet.push(current); + + let neighbors = current.neighbors; + + for (let i = 0; i < neighbors.length; i++) { + let neighbor = neighbors[i]; + + if (!closedSet.includes(neighbor)) { + let possibleG = current.g + 1; + + if (!openSet.includes(neighbor)) { + openSet.push(neighbor); + } else if (possibleG >= neighbor.g) { + continue; + } + + neighbor.g = possibleG; + neighbor.h = heuristic(neighbor, end); + neighbor.f = neighbor.g + neighbor.h; + neighbor.parent = current; + } + } + } + + //no solution by default + return []; +} + +// console.log(search()); \ No newline at end of file