Implementing fast-forward

This commit is contained in:
Dalibor Čarapić 2025-02-10 17:10:15 +01:00
parent f1148e1d07
commit 5e8b91ed81
6 changed files with 31 additions and 20 deletions

View File

@ -36,7 +36,7 @@ export class Engine {
Engine.NotificationManager.Notify('Loaded testing suite.', 'danger'); Engine.NotificationManager.Notify('Loaded testing suite.', 'danger');
Engine.TowerManager.ToggleChoosingTowerLocation('RESET'); Engine.TowerManager.ToggleChoosingTowerLocation('RESET');
Engine.TowerManager.PlaceTower(GameAssets.Towers[1], 6, 10, GameAssets.Towers[1].behaviour, true); Engine.TowerManager.PlaceTower(GameAssets.Towers[0], 6, 10, GameAssets.Towers[0].behaviour, true);
for (let i = 0; i < 29; i++) { for (let i = 0; i < 29; i++) {
this.GameScene.MissionStats.giveGem(new Gem(i % 4), true); this.GameScene.MissionStats.giveGem(new Gem(i % 4), true);
} }

View File

@ -131,8 +131,8 @@ export default class Creep extends GameObject {
this.sprite.scale.x *= -1; this.sprite.scale.x *= -1;
} }
} }
let deltaX = this.speed * elapsedMS * directionX; let deltaX = this.speed * elapsedMS * directionX * Engine.GameScene.gameSpeedMultiplier;
let deltaY = this.speed * elapsedMS * directionY; let deltaY = this.speed * elapsedMS * directionY * Engine.GameScene.gameSpeedMultiplier;
let increaseIndex = false; let increaseIndex = false;
if (deltaX > 0 && this.x + deltaX > targetX) { if (deltaX > 0 && this.x + deltaX > targetX) {

View File

@ -39,7 +39,7 @@ export default class Projectile extends GameObject {
super(); super();
this.x = x; this.x = x;
this.y = y; this.y = y;
this.timeToLive = timeToLive; this.timeToLive = timeToLive * (0.9 / 0.1);
this.pierce = pierce; this.pierce = pierce;
this.damage = damage; this.damage = damage;
this.gemResistanceModifications = gemResistanceModifications; this.gemResistanceModifications = gemResistanceModifications;
@ -53,7 +53,7 @@ export default class Projectile extends GameObject {
Engine.GameMaster.currentScene.stage.addChild(this.container); Engine.GameMaster.currentScene.stage.addChild(this.container);
this.angle = angle; this.angle = angle;
this.speed = 0.9; this.speed = 0.1;
} }
public destroy(): void { public destroy(): void {
super.destroy(); super.destroy();
@ -64,7 +64,7 @@ export default class Projectile extends GameObject {
if (this.deleteMe) return; if (this.deleteMe) return;
if (this.x > 2000 || this.x < 0 || this.y > 2000 || this.y < 0 || this.pierce <= 0 || this.timeToLive <= 0) if (this.x > 2000 || this.x < 0 || this.y > 2000 || this.y < 0 || this.pierce <= 0 || this.timeToLive <= 0)
return this.destroy(); return this.destroy();
this.timeToLive--; this.timeToLive -= Engine.GameScene.gameSpeedMultiplier;
Engine.Grid.creeps.forEach((creep) => { Engine.Grid.creeps.forEach((creep) => {
if (this.pierce <= 0) return; if (this.pierce <= 0) return;
if (creep && creep.container && this.checkCollision(creep)) { if (creep && creep.container && this.checkCollision(creep)) {
@ -77,14 +77,20 @@ export default class Projectile extends GameObject {
} }
} }
}); });
this.x += Math.cos(this.angle) * this.speed * elapsedMS; this.x += Math.cos(this.angle) * this.speed * elapsedMS * Engine.GameScene.gameSpeedMultiplier;
this.y += Math.sin(this.angle) * this.speed * elapsedMS; this.y += Math.sin(this.angle) * this.speed * elapsedMS * Engine.GameScene.gameSpeedMultiplier;
this.container.x = this.x; this.container.x = this.x;
this.container.y = this.y; this.container.y = this.y;
} }
public onCollide(creep) { public onCollide(creep) {
/*
Note:
Right now it is possible for the bullet to 'overshoot' the creep if the bullet speed is too fast and the position is updated so that the
new position is beyond the creep (i.e. the bullet is never 'in the creep').
This should be fixed so that we calculate the hit if the creep is in a line from the previous position to the new position.
*/
Engine.GameScene.events.emit(CreepEvents.TakenDamage, creep.id, this.damage, this.gemResistanceModifications); Engine.GameScene.events.emit(CreepEvents.TakenDamage, creep.id, this.damage, this.gemResistanceModifications);
} }

View File

@ -75,14 +75,14 @@ export function computeGemImprovements(tower: Tower) {
export function BasicTowerBehaviour(tower: Tower, elapsedMS: number) { export function BasicTowerBehaviour(tower: Tower, elapsedMS: number) {
if (tower.ticksUntilNextShot % 2 == 0) computeGemImprovements(tower); if (tower.ticksUntilNextShot % 2 == 0) computeGemImprovements(tower);
projectileCheck(tower, elapsedMS); projectileCheck(tower, elapsedMS);
if (tower.ticksUntilNextShot > 0) tower.ticksUntilNextShot--; if (tower.ticksUntilNextShot > 0) tower.ticksUntilNextShot -= Engine.GameScene.gameSpeedMultiplier;
let creepsInRange = tower.GetCreepsInRange(); let creepsInRange = tower.GetCreepsInRange();
if (creepsInRange.length > 0) { if (creepsInRange.length > 0) {
let focus = creepsInRange[0]; let focus = creepsInRange[0];
if (tower.ticksUntilNextShot <= 0) { if (tower.ticksUntilNextShot <= 0) {
let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2; let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2;
let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2; let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2;
tower.ticksUntilNextShot = tower.computedAttackSpeed; tower.ticksUntilNextShot = tower.computedAttackSpeed / Engine.GameScene.gameSpeedMultiplier;
tower.Shoot(calculateAngleToPoint(x, y, focus.x, focus.y)); tower.Shoot(calculateAngleToPoint(x, y, focus.x, focus.y));
} }
} }
@ -91,12 +91,12 @@ export function BasicTowerBehaviour(tower: Tower, elapsedMS: number) {
export function CircleTowerBehaviour(tower: Tower, elapsedMS: number) { export function CircleTowerBehaviour(tower: Tower, elapsedMS: number) {
if (tower.ticksUntilNextShot % 2 == 0) computeGemImprovements(tower); if (tower.ticksUntilNextShot % 2 == 0) computeGemImprovements(tower);
projectileCheck(tower, elapsedMS); projectileCheck(tower, elapsedMS);
if (tower.ticksUntilNextShot > 0) tower.ticksUntilNextShot--; if (tower.ticksUntilNextShot > 0) tower.ticksUntilNextShot -= Engine.GameScene.gameSpeedMultiplier;
let creepsInRange = tower.GetCreepsInRange(); let creepsInRange = tower.GetCreepsInRange();
if (creepsInRange.length > 0) { if (creepsInRange.length > 0) {
let focus = creepsInRange[0]; let focus = creepsInRange[0];
if (tower.ticksUntilNextShot <= 0) { if (tower.ticksUntilNextShot <= 0) {
tower.ticksUntilNextShot = tower.computedAttackSpeed; tower.ticksUntilNextShot = tower.computedAttackSpeed / Engine.GameScene.gameSpeedMultiplier;
let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2; let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2;
let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2; let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2;
tower.Shoot(calculateAngleToPoint(x, y, x, y + 10)); // Up tower.Shoot(calculateAngleToPoint(x, y, x, y + 10)); // Up

View File

@ -60,7 +60,7 @@ export default class WaveManager extends GameObject {
} }
public update(elapsedMS: number): void { public update(elapsedMS: number): void {
if (this.started == false) return; if (this.started == false) return;
this.ticks += elapsedMS; this.ticks += elapsedMS * Engine.GameScene.gameSpeedMultiplier;
this.creeps.forEach((creep) => { this.creeps.forEach((creep) => {
if (!creep.spawned && creep.tickToSpawnAt <= this.ticks) { if (!creep.spawned && creep.tickToSpawnAt <= this.ticks) {
creep.spawned = true; creep.spawned = true;

View File

@ -38,7 +38,8 @@ export class GameScene extends Scene {
public tooltip: Tooltip; public tooltip: Tooltip;
public towerPanel: TowerPanel; public towerPanel: TowerPanel;
public isPaused: boolean = false; public isPaused: boolean = false;
private isFastForwarded: boolean = false; public gameSpeedMultiplier: number = 1;
private pauseButton: Button; private pauseButton: Button;
private visualGems: VisualGemSlot[] = []; private visualGems: VisualGemSlot[] = [];
private currentRound: number = 0; private currentRound: number = 0;
@ -106,14 +107,12 @@ export class GameScene extends Scene {
this.changeRoundButton.onClick = () => { this.changeRoundButton.onClick = () => {
if (this.playerWon) return this.ReturnToMain(); if (this.playerWon) return this.ReturnToMain();
if (this.roundMode == RoundMode.Combat) { if (this.roundMode == RoundMode.Combat) {
// TODO: figure out how to actually double speed without causing bugs. if (this.gameSpeedMultiplier !== 1) {
if (this.isFastForwarded) { this.UpdateGameSpeedMultiplier(1);
this.isFastForwarded = false;
Engine.NotificationManager.Notify('Regular speed.', 'info');
} else { } else {
this.isFastForwarded = true; this.UpdateGameSpeedMultiplier(2);
Engine.NotificationManager.Notify('Fast forward activated.', 'info');
} }
return;
} }
if (this.isGameOver) return Engine.NotificationManager.Notify('No more waves.', 'danger'); if (this.isGameOver) return Engine.NotificationManager.Notify('No more waves.', 'danger');
if (this.roundMode == RoundMode.Misc) return; if (this.roundMode == RoundMode.Misc) return;
@ -341,4 +340,10 @@ export class GameScene extends Scene {
private ReturnToMain() { private ReturnToMain() {
Engine.GameMaster.changeScene(new MissionPickerScene()); Engine.GameMaster.changeScene(new MissionPickerScene());
} }
private UpdateGameSpeedMultiplier(newMultiplier: number) {
this.gameSpeedMultiplier = newMultiplier;
if (newMultiplier === 1) Engine.NotificationManager.Notify('Regular speed.', 'info');
else Engine.NotificationManager.Notify('Fast forward activated.', 'info');
}
} }