Skip to content
Snippets Groups Projects
Commit cf009e48 authored by Fredrik Fonn Hansen's avatar Fredrik Fonn Hansen :8ball:
Browse files

Add terrainCreation on backend

parent 14e8dd17
No related branches found
No related tags found
1 merge request!46Add terrainCreation on backend
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
}, },
"dependencies": { "dependencies": {
"firebase-admin": "^11.5.0", "firebase-admin": "^11.5.0",
"prettier": "^2.8.4" "prettier": "^2.8.4",
"simplex-noise": "^4.0.1"
} }
} }
...@@ -49,3 +49,12 @@ export const currentTurn = async (req: Request, res: Response): Promise<void> => ...@@ -49,3 +49,12 @@ export const currentTurn = async (req: Request, res: Response): Promise<void> =>
res.status(404).send('Game not found (or not created yet because lack of opponent)'); res.status(404).send('Game not found (or not created yet because lack of opponent)');
} }
}; };
export const getTerrain = async (req: Request, res: Response): Promise<void> => {
const game = gameHandler.getGameById(req.params.gameid);
if (game) {
res.status(200).send(game.getTerrain().getYValues());
} else {
res.status(404).send('Game not found');
}
}
const { createNoise2D } = require('simplex-noise');
function generateYValues(maxY: number, numValues: number): number[] {
const yValues: number[] = [];
const noiseScale = 0.0025;
const noise2D = createNoise2D();
for (let i = 0; i < numValues; i++) {
const x = i;
const t = x / (numValues - 1); // Normalize x to range [0, 1]
const noiseValue = noise2D(x * noiseScale, t * noiseScale); // Generate Simplex noise value for this point
const y = maxY * (0.5 + 0.5 * noiseValue); // Scale and shift the noise value to fit in the [0, maxY] range
yValues.push(y);
}
return yValues;
}
export default generateYValues;
\ No newline at end of file
/** /**
* A simple function for logging messages to the console. * log() is a function for logging messages to the console in a standard format.
* *
* @param message The message to log * @param message The message to log
* @returns void * @returns void
*/ */
export function log(message: string): void { export function log(message: string): void {
const time = new Date().toLocaleTimeString(); const time = new Date().toLocaleTimeString();
const file = new Error().stack?.split('at ')[2].split(' ')[0]; const file = new Error().stack?.split('at ')[2].split(' ')[0];
...@@ -12,3 +11,33 @@ export function log(message: string): void { ...@@ -12,3 +11,33 @@ export function log(message: string): void {
const paddedFile = file?.padEnd(maxLength, ' '); const paddedFile = file?.padEnd(maxLength, ' ');
console.log(time + ' | ' + paddedFile + '| ' + message); console.log(time + ' | ' + paddedFile + '| ' + message);
} }
/**
* slopePreview() is a helper function for visualizing the terrain generated by the generateYValues() function.
* It takes an array of y-values and prints a preview of the terrain to the console.
*
* @param yValues An array of y-values
* @param maxY The maximum y-value in the array
* @param width The width of the terrain preview
* @param height The height of the terrain preview
*/
export default function slopePreview(yValues: number[], maxY: number, width: number, height: number) {
const terrain: string[][] = [];
for (let i = 0; i < height; i++) {
terrain[i] = [];
for (let j = 0; j < width; j++) {
terrain[i][j] = ' ';
}
}
for (let i = 0; i < yValues.length; i++) {
const x = Math.floor((i / (yValues.length - 1)) * width);
const y = height - 1 - Math.floor((yValues[i] / maxY) * height);
terrain[y][x] = '#';
}
const terrainString = terrain.map(row => row.join('')).join('\n');
console.log(terrainString);
}
\ No newline at end of file
import { User } from '../../types/User'; import { User } from '../../types/User';
import { ILobby } from './ILobby'; import { ILobby } from './ILobby';
import { IStats } from './IStats'; import { IStats } from './IStats';
import { ITerrain } from './ITerrain';
// interface for a game instance // interface for a game instance
export interface IGame { export interface IGame {
users: [User, IStats][];
currentTurn: number;
lobby: ILobby;
gameStatus: boolean;
gameId: string;
terrain: ITerrain;
notifyUsers(): void; notifyUsers(): void;
setIsFinished(status: boolean): void; setIsFinished(status: boolean): void;
...@@ -28,9 +36,6 @@ export interface IGame { ...@@ -28,9 +36,6 @@ export interface IGame {
getUsers(): [User, IStats][]; getUsers(): [User, IStats][];
users: [User, IStats][]; getTerrain(): ITerrain;
currentTurn: number;
lobby: ILobby;
gameStatus: boolean;
gameId: string;
} }
export interface ITerrain {
yValues: number[];
xPoints: number;
maxY: number;
generate(): number[];
getYValues(): number[];
}
...@@ -6,19 +6,23 @@ import { log } from '../functions/console'; ...@@ -6,19 +6,23 @@ import { log } from '../functions/console';
import { IGame } from '../interfaces/IGame'; import { IGame } from '../interfaces/IGame';
import { ILobby } from '../interfaces/ILobby'; import { ILobby } from '../interfaces/ILobby';
import { IStats } from '../interfaces/IStats'; import { IStats } from '../interfaces/IStats';
import { ITerrain } from '../interfaces/ITerrain';
import { Stats } from './Stats'; import { Stats } from './Stats';
import { Terrain } from './Terrain';
export class Game implements IGame { export class Game implements IGame {
currentTurn: number; currentTurn: number;
lobby: ILobby; lobby: ILobby;
gameStatus: boolean; gameStatus: boolean;
gameId: string; gameId: string;
terrain: ITerrain;
users: [User, IStats][]; // left [0] and right [1] user users: [User, IStats][]; // left [0] and right [1] user
constructor(lobby: ILobby) { constructor(lobby: ILobby) {
this.lobby = lobby; this.lobby = lobby;
this.gameStatus = false; // game not finished this.gameStatus = false; // game not finished
this.gameId = Math.random().toString(36); this.gameId = Math.random().toString(36);
this.terrain = new Terrain();
// insert the lobby users into the game and create a new stats object for each user // insert the lobby users into the game and create a new stats object for each user
this.users = lobby.getUsers().map((user) => [user, new Stats()]); this.users = lobby.getUsers().map((user) => [user, new Stats()]);
...@@ -39,6 +43,9 @@ export class Game implements IGame { ...@@ -39,6 +43,9 @@ export class Game implements IGame {
this.notifyUsers(); // TODO: implement this method this.notifyUsers(); // TODO: implement this method
log('Game ' + this.gameId + ' created.'); log('Game ' + this.gameId + ' created.');
} }
getTerrain(): ITerrain {
return this.terrain;
}
getUsers(): [User, IStats][] { getUsers(): [User, IStats][] {
return this.users; return this.users;
...@@ -49,8 +56,7 @@ export class Game implements IGame { ...@@ -49,8 +56,7 @@ export class Game implements IGame {
} }
notifyUsers(): void { notifyUsers(): void {
log('Notifying users... [TODO]'); log('[TODO] Notifying users...');
// throw new Error('Method not implemented.');
} }
setGameStatus(status: boolean): void { setGameStatus(status: boolean): void {
......
import generateYValues from '../functions/TerrainGenerator';
import { ITerrain } from '../interfaces/ITerrain';
export class Terrain implements ITerrain {
yValues: number[];
maxY: number;
xPoints: number;
constructor(maxY: number = 15, numValues: number = 1000) {
this.maxY = maxY;
this.xPoints = numValues;
this.yValues = this.generate();
}
generate(): number[] {
return generateYValues(this.maxY, this.xPoints);
}
getYValues(): number[] {
return this.yValues;
}
}
\ No newline at end of file
...@@ -6,5 +6,6 @@ const router = express.Router(); ...@@ -6,5 +6,6 @@ const router = express.Router();
router.get('/:lobbyId', gameController.gameId); router.get('/:lobbyId', gameController.gameId);
router.post('/:gameid/move', gameController.move); router.post('/:gameid/move', gameController.move);
router.get('/:gameid/currentTurn', gameController.currentTurn); router.get('/:gameid/currentTurn', gameController.currentTurn);
router.get('/:gameid/terrain', gameController.getTerrain);
export default router; export default router;
...@@ -2762,6 +2762,11 @@ simple-update-notifier@^1.0.7: ...@@ -2762,6 +2762,11 @@ simple-update-notifier@^1.0.7:
dependencies: dependencies:
semver "~7.0.0" semver "~7.0.0"
simplex-noise@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/simplex-noise/-/simplex-noise-4.0.1.tgz#1573a4eaa46ce488bdf5f1e7ab3a1f798126781f"
integrity sha512-zl/+bdSqW7HJOQ0oDbxrNYaF4F5ik0i7M6YOYmEoIJNtg16NpvWaTTM1Y7oV/7T0jFljawLgYPS81Uu2rsfo1A==
slash@^3.0.0: slash@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment