fix consistency issues, define creep and how wave manager interacts/manages them

This commit is contained in:
koneko 2024-10-03 23:32:57 +02:00
parent bc5878b6d3
commit 21f5f7d5b3
7 changed files with 134 additions and 43 deletions

View File

@ -2,32 +2,46 @@
"name": "Mission 1", "name": "Mission 1",
"description": "This is the first mission", "description": "This is the first mission",
"gameMap": { "gameMap": {
"rows": 10, "rows": 15,
"columns": 10, "columns": 15,
"cells": [ "cells": [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 0, 0, 0, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 0, 0, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
], ],
"paths": [ "paths": [
[ [
[0, 2], [0, 3],
[1, 2], [1, 3],
[2, 2], [2, 3],
[3, 3],
[3, 2], [3, 2],
[4, 2], [4, 2],
[5, 2], [5, 2],
[6, 2], [6, 2],
[7, 2], [7, 2],
[8, 2], [7, 3],
[9, 2] [7, 4],
[8, 4],
[9, 4]
] ]
] ]
}, },

View File

@ -3,7 +3,7 @@ export type MissionDefinition = {
description: string; description: string;
mapImageUrl: string; mapImageUrl: string;
gameMap: GameMapDefinition; gameMap: GameMapDefinition;
missionRounds: MissionRoundDefinition[]; rounds: MissionRoundDefinition[];
}; };
export type GameMapDefinition = { export type GameMapDefinition = {

View File

@ -4,13 +4,17 @@ import GameScene from '../scenes/GameScene';
import GameObject from './GameObject'; import GameObject from './GameObject';
import * as PIXI from 'pixi.js'; import * as PIXI from 'pixi.js';
import SceneBase from '../scenes/SceneBase'; import SceneBase from '../scenes/SceneBase';
import Assets from './Assets';
export default class Game extends GameObject { export default class Game extends GameObject {
private _currentScene: SceneBase | null = null; private _currentScene: SceneBase | null = null;
constructor(bounds: PIXI.Rectangle) { constructor(bounds: PIXI.Rectangle) {
super(bounds); super(bounds);
this.onMainMenu(); let params = new URLSearchParams(location.href);
if (params.entries().next().value[1] == 'game') {
this.setScene(new GameScene(Assets.Missions[0], this.bounds));
} else this.onMainMenu();
} }
private onMainMenu() { private onMainMenu() {

View File

@ -1,10 +1,56 @@
import { CreepType, PathDefinition } from '../base/Definitions';
import GameObject from '../base/GameObject'; import GameObject from '../base/GameObject';
import * as PIXI from 'pixi.js'; import * as PIXI from 'pixi.js';
export default class Creep extends GameObject { export function CreepStats(ctype: CreepType): object {
constructor(bounds?: PIXI.Rectangle) { switch (ctype) {
super(bounds); case CreepType.Basic:
return {
health: 2,
speed: 0.45,
special: null,
resistance: {
physical: 0,
divine: 0,
fire: 0,
ice: 0,
frostfire: 0,
},
};
case CreepType.Fast:
throw new Error('Fast creep not defined.');
default:
return {
health: null,
speed: null,
special: null,
resistance: {
physical: null,
divine: null,
fire: null,
ice: null,
frostfire: null,
},
};
} }
}
export default class Creep extends GameObject {
public creepType: CreepType;
private path: PathDefinition;
private pathIndex: number = 0;
private health: number;
private x: number; // X and Y are local to the grid, not canvas
private y: number;
constructor(
creepType: CreepType,
path: PathDefinition,
bounds?: PIXI.Rectangle
) {
super(bounds);
this.creepType = creepType;
this.path = path;
}
public update() {}
protected draw() { protected draw() {
this.container.removeChildren(); this.container.removeChildren();

View File

@ -0,0 +1,36 @@
import {
CreepType,
MissionRoundDefinition,
PathDefinition,
} from '../base/Definitions';
import Creep from './Creep';
export default class WaveManager {
// Doesn't need to extend GameObject since it does not render
private currentWave: number;
private creeps: Creep[] = [];
private rounds: MissionRoundDefinition[];
private paths: PathDefinition[];
private spawnIntervalTicks: number;
private firstCreepSpawnTick: number;
public ticks: number = 0;
constructor(rounds: MissionRoundDefinition[], paths: PathDefinition[]) {
this.rounds = rounds;
this.paths = paths;
}
private updateCreeps() {
this.creeps.forEach((creep) => {
creep.update();
// TODO: updating here is fine, change to make spawning emit an event
// which GameScene will catch and send to Grid who will draw the creep
// based on the coordinates that the creep calculates.
});
}
public update(fps): void {
if (this.creeps.length != 0) this.updateCreeps();
this.ticks++;
if (this.ticks == 200) {
this.creeps.push(new Creep(CreepType.Basic, this.paths[0]));
}
}
}

View File

@ -1,13 +0,0 @@
import Creep from './Creep';
export default class WaveManager {
// Doesn't need to extend GameObject since it does not render
private totalWaves: number;
private currentWave: number;
private creeps: Creep[];
private spawnIntervalTicks: number;
private firstCreepSpawnTick: number;
constructor(totalWaves) {
this.totalWaves = totalWaves;
}
}

View File

@ -2,7 +2,7 @@ import Button from '../base/Button';
import { MissionDefinition } from '../base/Definitions'; import { MissionDefinition } from '../base/Definitions';
import { Grid } from '../components/Grid'; import { Grid } from '../components/Grid';
import MissionStats from '../components/MissionStats'; import MissionStats from '../components/MissionStats';
import WaveManager from '../components/WaveManger'; import WaveManager from '../components/WaveManager';
import SceneBase from './SceneBase'; import SceneBase from './SceneBase';
import * as PIXI from 'pixi.js'; import * as PIXI from 'pixi.js';
@ -10,19 +10,21 @@ export default class GameScene extends SceneBase {
private ticker: PIXI.Ticker; private ticker: PIXI.Ticker;
private stats: MissionStats; private stats: MissionStats;
private grid: Grid; private grid: Grid;
private WaveManager: WaveManager; public waveManager: WaveManager;
constructor(mission: MissionDefinition, bounds: PIXI.Rectangle) { constructor(mission: MissionDefinition, bounds: PIXI.Rectangle) {
super(bounds); super(bounds);
this.ticker = new PIXI.Ticker(); this.waveManager = new WaveManager(
mission.rounds,
mission.gameMap.paths
);
this.stats = new MissionStats(100, 200);
this.grid = new Grid(mission.gameMap);
this.ticker = new PIXI.Ticker(); this.ticker = new PIXI.Ticker();
this.ticker.maxFPS = 60; this.ticker.maxFPS = 60;
this.ticker.minFPS = 30; this.ticker.minFPS = 30;
this.ticker.add(this.update); this.ticker.add(() => this.update(this.ticker.FPS)); // bruh
this.ticker.start(); this.ticker.start();
this.stats = new MissionStats(100, 200);
this.grid = new Grid(mission.gameMap);
this.WaveManager = new WaveManager(mission);
this.draw(); this.draw();
} }
@ -47,7 +49,9 @@ export default class GameScene extends SceneBase {
this.ticker.destroy(); this.ticker.destroy();
} }
public update() {} public update(fps) {
this.waveManager.update(fps);
}
protected draw() { protected draw() {
console.log('Drawing Game Scene ', this.bounds); console.log('Drawing Game Scene ', this.bounds);