ported Vis
This commit is contained in:
60
src/app/components/game/vis/VisEnemy.ts
Normal file
60
src/app/components/game/vis/VisEnemy.ts
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import { AssetPreloaderService } from "../../../assetPreloaderService";
|
||||||
|
import { EEnemySize } from "../data/EEnemySize";
|
||||||
|
import { GdRoot } from "../data/GdRoot";
|
||||||
|
import { SimEnemy } from "../sim/SimEnemy";
|
||||||
|
import { Vector2 } from "../util/Vector2";
|
||||||
|
|
||||||
|
export class VisEnemy {
|
||||||
|
positions: Vector2[];
|
||||||
|
directions: Vector2[];
|
||||||
|
image: HTMLCanvasElement;
|
||||||
|
context: CanvasRenderingContext2D;
|
||||||
|
private simEnemy: SimEnemy;
|
||||||
|
private angle: number | null = null;
|
||||||
|
private gdRoot: GdRoot;
|
||||||
|
assets: AssetPreloaderService;
|
||||||
|
|
||||||
|
constructor(gdRoot: GdRoot, assets: AssetPreloaderService, simEnemy: SimEnemy, width: number, height: number) {
|
||||||
|
this.assets = assets;
|
||||||
|
this.gdRoot = gdRoot;
|
||||||
|
this.simEnemy = simEnemy;
|
||||||
|
this.image = document.createElement("canvas");
|
||||||
|
this.image.width = width;
|
||||||
|
this.image.height = height;
|
||||||
|
this.context = this.image.getContext("2d")!;
|
||||||
|
this.positions = [simEnemy.position, simEnemy.position];
|
||||||
|
this.directions = [simEnemy.direction, simEnemy.direction];
|
||||||
|
}
|
||||||
|
|
||||||
|
public advanceStep() {
|
||||||
|
const prevPos = this.positions[1];
|
||||||
|
const prevDir = this.directions[1];
|
||||||
|
this.positions = [prevPos, this.simEnemy.position];
|
||||||
|
this.directions = [prevDir, this.simEnemy.direction];
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(t: number) {
|
||||||
|
const directions = this.directions;
|
||||||
|
const dir = Vector2.lerp(directions[0], directions[1], t);
|
||||||
|
const angle = Math.atan2(dir.x, -dir.y) - Math.PI / 2;
|
||||||
|
if (this.angle == angle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.angle = angle;
|
||||||
|
const ctx = this.context;
|
||||||
|
ctx.clearRect(0, 0, this.image.width, this.image.height);
|
||||||
|
ctx.save();
|
||||||
|
ctx.translate(this.image.width / 2, this.image.height / 2);
|
||||||
|
ctx.rotate(angle);
|
||||||
|
switch (this.simEnemy.size) {
|
||||||
|
case EEnemySize.Tiny:
|
||||||
|
ctx.scale(0.75, 0.75);
|
||||||
|
break;
|
||||||
|
case EEnemySize.Huge:
|
||||||
|
ctx.scale(2, 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ctx.drawImage(this.assets.getImage("enemy-" + (this.simEnemy.index | 0) + ".svg"), -this.image.width / 2, -this.image.height / 2, this.image.width, this.image.height);
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
298
src/app/components/game/vis/VisLevel.ts
Normal file
298
src/app/components/game/vis/VisLevel.ts
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
import { AssetPreloaderService } from "../../../assetPreloaderService";
|
||||||
|
import { GdRoot } from "../data/GdRoot";
|
||||||
|
import { ECellType } from "../sim/ECellType";
|
||||||
|
import { SimCell } from "../sim/SimCell";
|
||||||
|
import { SimEnemy } from "../sim/SimEnemy";
|
||||||
|
import { SimLevel } from "../sim/SimLevel";
|
||||||
|
import { SimMain } from "../sim/SimMain";
|
||||||
|
import { SimProjectile } from "../sim/SimProjectile";
|
||||||
|
import { Hex } from "../util/Hex";
|
||||||
|
import { Vector2 } from "../util/Vector2";
|
||||||
|
import { VisEnemy } from "./VisEnemy";
|
||||||
|
import { VisMain } from "./VisMain";
|
||||||
|
import { VisProjectile } from "./VisProjectile";
|
||||||
|
|
||||||
|
export class VisLevel {
|
||||||
|
private screenCellWidth: number = -1;
|
||||||
|
private screenCellHeight: number = -1;
|
||||||
|
private screenXOffset: number = -1;
|
||||||
|
private screenYOffset: number = -1;
|
||||||
|
private hexSize: number = -1;
|
||||||
|
private lastStep: number = -1;
|
||||||
|
private projectileMap: Map<SimProjectile, VisProjectile>;
|
||||||
|
private enemyMap: Map<SimEnemy, VisEnemy>;
|
||||||
|
private background: HTMLCanvasElement | null = null;
|
||||||
|
private simLevel: SimLevel | null = null;
|
||||||
|
private visMain: VisMain;
|
||||||
|
private simMain: SimMain;
|
||||||
|
private gdRoot: GdRoot;
|
||||||
|
assets: AssetPreloaderService;
|
||||||
|
|
||||||
|
constructor(visMain: VisMain, simMain: SimMain, gdRoot: GdRoot, assets: AssetPreloaderService) {
|
||||||
|
this.assets = assets;
|
||||||
|
this.visMain = visMain;
|
||||||
|
this.simMain = simMain;
|
||||||
|
this.gdRoot = gdRoot
|
||||||
|
this.enemyMap = new Map<SimEnemy, VisEnemy>();
|
||||||
|
this.projectileMap = new Map<SimProjectile, VisProjectile>();
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public reset() {
|
||||||
|
this.projectileMap.clear();
|
||||||
|
this.enemyMap.clear();
|
||||||
|
this.background = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public draw() {
|
||||||
|
const ctx = this.visMain.context;
|
||||||
|
const simLevel = this.simMain.currentLevel;
|
||||||
|
if (simLevel == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const gdLevel = this.gdRoot.levels[simLevel.index];
|
||||||
|
|
||||||
|
if (simLevel != this.simLevel) {
|
||||||
|
this.reset();
|
||||||
|
this.simLevel = simLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.drawBackground();
|
||||||
|
ctx.globalCompositeOperation = "source-over";
|
||||||
|
|
||||||
|
simLevel.cells.forEach((cell: SimCell) => {
|
||||||
|
if (cell.distance > gdLevel.radius) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.drawCell(cell);
|
||||||
|
});
|
||||||
|
|
||||||
|
simLevel.enemies.forEach((enemy: SimEnemy) => {
|
||||||
|
this.drawEnemy(enemy);
|
||||||
|
});
|
||||||
|
|
||||||
|
simLevel.projectiles.forEach((projectile: SimProjectile) => {
|
||||||
|
this.drawProjectile(projectile);
|
||||||
|
});
|
||||||
|
|
||||||
|
ctx.fillStyle = "white";
|
||||||
|
ctx.fillText("Currency: " + simLevel.currency, 5, 15);
|
||||||
|
ctx.fillText("Current wave: " + simLevel.currentWave, 5, 35);
|
||||||
|
ctx.fillText("Enemies left: " + simLevel.enemiesLeftToSpawn, 5, 55);
|
||||||
|
ctx.fillText("Current step: " + simLevel.currentStep, 5, 75);
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateSize() {
|
||||||
|
const simLevel = this.simMain.currentLevel;
|
||||||
|
if (simLevel == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gdLevel = this.gdRoot.levels[simLevel.index];
|
||||||
|
const minSize = Math.min(this.visMain.canvas.height, this.visMain.canvas.width * Math.sqrt(3) / 2);
|
||||||
|
this.hexSize = Math.floor(minSize / (4 * (gdLevel.radius - 1) - 4));
|
||||||
|
this.screenCellHeight = Math.ceil(2 * this.hexSize);
|
||||||
|
this.screenCellHeight = Math.ceil(this.screenCellHeight * 0.5) * 2;
|
||||||
|
this.screenCellWidth = Math.ceil(Math.sqrt(3) / 2 * this.screenCellHeight);
|
||||||
|
this.screenCellWidth = Math.ceil(this.screenCellWidth * 0.5) * 2;
|
||||||
|
this.screenXOffset = this.screenCellWidth * (gdLevel.radius + 0.5);
|
||||||
|
this.screenYOffset = this.screenCellHeight * (gdLevel.radius + 0.5);
|
||||||
|
|
||||||
|
const width = this.screenCellWidth * (gdLevel.radius * 2 + 1);
|
||||||
|
const height = this.screenCellHeight * (gdLevel.radius * 2 + 1);
|
||||||
|
this.screenXOffset += (this.visMain.canvas.width - width) * 0.5;
|
||||||
|
this.screenYOffset += (this.visMain.canvas.height - height) * 0.5;
|
||||||
|
|
||||||
|
this.screenXOffset = Math.floor(this.screenXOffset);
|
||||||
|
this.screenYOffset = Math.floor(this.screenYOffset);
|
||||||
|
this.background = null;
|
||||||
|
this.enemyMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateEveryFrame(currentStep: number) {
|
||||||
|
const simLevel = this.simMain.currentLevel;
|
||||||
|
if (simLevel == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const t = currentStep - Math.floor(currentStep);
|
||||||
|
|
||||||
|
const deadEnemies: SimEnemy[] = [];
|
||||||
|
simLevel.enemies.forEach((simEnemy: SimEnemy) => {
|
||||||
|
if (simEnemy.dead) {
|
||||||
|
deadEnemies.push(simEnemy);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const visEnemy = this.enemyMap.get(simEnemy);
|
||||||
|
if (!visEnemy) {
|
||||||
|
this.enemyMap.set(simEnemy, new VisEnemy(this.gdRoot, this.assets, simEnemy, this.screenCellWidth, this.screenCellHeight));
|
||||||
|
}
|
||||||
|
else if (Math.floor(currentStep) != Math.floor(this.lastStep)) {
|
||||||
|
visEnemy.advanceStep();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
visEnemy.update(t);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
for (const deadEnemy of deadEnemies) {
|
||||||
|
this.enemyMap.delete(deadEnemy);
|
||||||
|
}
|
||||||
|
|
||||||
|
const deadProjectiles: SimProjectile[] = [];
|
||||||
|
simLevel.projectiles.forEach((simProjectile: SimProjectile) => {
|
||||||
|
if (simProjectile.dead) {
|
||||||
|
deadProjectiles.push(simProjectile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const visProjectile = this.projectileMap.get(simProjectile);
|
||||||
|
if (!visProjectile) {
|
||||||
|
this.projectileMap.set(simProjectile, new VisProjectile(simProjectile));
|
||||||
|
}
|
||||||
|
else if (Math.floor(currentStep) != Math.floor(this.lastStep)) {
|
||||||
|
visProjectile.advanceStep();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
for (const deadProjectile of deadProjectiles) {
|
||||||
|
this.projectileMap.delete(deadProjectile);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastStep = currentStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getScreenCoords(hex: Hex): Vector2 {
|
||||||
|
const coord = Hex.toPixel(hex, this.hexSize);
|
||||||
|
return new Vector2(coord.x + this.screenXOffset - this.screenCellWidth / 2, coord.y + this.screenYOffset - this.screenCellHeight / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getHexFromScreenCoords(coords: Vector2): Hex {
|
||||||
|
const x = coords.x - this.screenXOffset;
|
||||||
|
const y = coords.y - this.screenYOffset;
|
||||||
|
return Hex.fromPixel(new Vector2(x, y), this.hexSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private drawBackground() {
|
||||||
|
const ctx = this.visMain.context;
|
||||||
|
const simLevel = this.simMain.currentLevel;
|
||||||
|
if (simLevel == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gdLevel = this.gdRoot.levels[simLevel.index];
|
||||||
|
if (this.background == null) {
|
||||||
|
const backgroundCanvas = this.visMain.canvas.cloneNode() as HTMLCanvasElement;
|
||||||
|
const backgroundContext = backgroundCanvas.getContext("2d")!;
|
||||||
|
this.background = backgroundCanvas;
|
||||||
|
simLevel.cells.forEach((cell: SimCell) => {
|
||||||
|
if (cell.distance > gdLevel.radius) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cell.blockedType != -1 && cell.type == ECellType.Blocked) {
|
||||||
|
this.drawCellImage(backgroundContext, cell, "cell-blocked-" + (cell.blockedType | 0) + ".svg");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
backgroundContext.globalCompositeOperation = "source-atop";
|
||||||
|
backgroundContext.fillStyle = this.visMain.wallPattern;
|
||||||
|
backgroundContext.fillRect(0, 0, this.visMain.canvas.width, this.visMain.canvas.height);
|
||||||
|
|
||||||
|
const cellCanvas = this.visMain.canvas.cloneNode() as HTMLCanvasElement;
|
||||||
|
const cellContext = cellCanvas.getContext("2d")!;
|
||||||
|
simLevel.cells.forEach((cell: SimCell) => {
|
||||||
|
if (cell.distance > gdLevel.radius) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cell.type != ECellType.Entry) {
|
||||||
|
this.drawCellImage(cellContext, cell, "cell.svg");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
backgroundContext.globalCompositeOperation = "destination-over";
|
||||||
|
backgroundContext.drawImage(cellCanvas, 0, 0);
|
||||||
|
backgroundContext.globalCompositeOperation = "source-over";
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.drawImage(this.background, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private drawProjectile(simProjectile: SimProjectile) {
|
||||||
|
const visProjectile = this.projectileMap.get(simProjectile);
|
||||||
|
if (!visProjectile) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const t = this.lastStep - Math.floor(this.lastStep);
|
||||||
|
const positions = visProjectile.positions;
|
||||||
|
if (!positions) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const pos = Vector2.lerp(positions[0], positions[1], t);
|
||||||
|
const width = this.screenCellWidth * simProjectile.size;
|
||||||
|
const height = this.screenCellHeight * simProjectile.size;
|
||||||
|
this.visMain.context.drawImage(this.assets.getImage("projectile.svg"),
|
||||||
|
this.screenXOffset + pos.x * this.hexSize - width / 2,
|
||||||
|
this.screenYOffset + pos.y * this.hexSize - height / 2,
|
||||||
|
width,
|
||||||
|
height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private drawEnemy(simEnemy: SimEnemy) {
|
||||||
|
const visEnemy = this.enemyMap.get(simEnemy);
|
||||||
|
if (!visEnemy) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const t = this.lastStep - Math.floor(this.lastStep);
|
||||||
|
const positions = visEnemy.positions;
|
||||||
|
if (!positions) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const pos = Vector2.lerp(positions[0], positions[1], t);
|
||||||
|
this.visMain.context.drawImage(
|
||||||
|
visEnemy.image,
|
||||||
|
this.screenXOffset + pos.x * this.hexSize - this.screenCellWidth / 2,
|
||||||
|
this.screenYOffset + pos.y * this.hexSize - this.screenCellHeight / 2,
|
||||||
|
this.screenCellWidth,
|
||||||
|
this.screenCellHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
private drawCell(cell: SimCell) {
|
||||||
|
const simLevel = this.simMain.currentLevel;
|
||||||
|
if (simLevel == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.visMain.context.fillStyle = "rgba(192, 192, 192, 0.25)";
|
||||||
|
if (cell.type == ECellType.Entry) {
|
||||||
|
this.drawCellImage(this.visMain.context, cell, "cell-entry-" + (cell.blockedType | 0) + ".svg");
|
||||||
|
}
|
||||||
|
|
||||||
|
const highlightedCell = simLevel.cells[simLevel.highlightedIndex];
|
||||||
|
if (!!highlightedCell) {
|
||||||
|
let draw = highlightedCell.index == cell.index;
|
||||||
|
if (draw && highlightedCell.pathsToTarget != null) {
|
||||||
|
for (const routeIdx in highlightedCell.pathsToTarget) {
|
||||||
|
for (const idx in highlightedCell.pathsToTarget[routeIdx]) {
|
||||||
|
if (highlightedCell.pathsToTarget[routeIdx][idx] == highlightedCell.index) {
|
||||||
|
draw = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (draw) {
|
||||||
|
this.drawCellImage(this.visMain.context, highlightedCell, "cell-highlighted.svg");
|
||||||
|
this.visMain.context.fillStyle = "rgba(0, 0, 0, 1)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cell.tower != null) {
|
||||||
|
this.drawCellImage(this.visMain.context, cell, "tower-" + (cell.tower.index | 0) + ".svg");
|
||||||
|
}
|
||||||
|
|
||||||
|
const coords = this.getScreenCoords(cell.hex);
|
||||||
|
this.visMain.context.fillText("(" + cell.hex.col + ", " + cell.hex.row + ")", coords.x + 10, coords.y + this.screenCellHeight / 2 + 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
private drawCellImage(context: CanvasRenderingContext2D, cell: SimCell, name: string) {
|
||||||
|
const coords = this.getScreenCoords(cell.hex);
|
||||||
|
context.drawImage(this.assets.getImage(name), coords.x, coords.y, this.screenCellWidth, this.screenCellHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
106
src/app/components/game/vis/VisMain.ts
Normal file
106
src/app/components/game/vis/VisMain.ts
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
import { AssetPreloaderService } from "../../../assetPreloaderService";
|
||||||
|
import { SplashComponent } from "../../splash/splash.component";
|
||||||
|
import { SimMain } from "../sim/SimMain";
|
||||||
|
import { VisLevel } from "./VisLevel";
|
||||||
|
|
||||||
|
export class VisMain {
|
||||||
|
canvas: HTMLCanvasElement;
|
||||||
|
context: CanvasRenderingContext2D;
|
||||||
|
wallPattern: CanvasPattern;
|
||||||
|
visLevel: VisLevel;
|
||||||
|
simMain: SimMain;
|
||||||
|
private startTimestamp: number = 0;
|
||||||
|
private active: boolean = true;
|
||||||
|
private ready: boolean = false;
|
||||||
|
private gap: number = 0;
|
||||||
|
assets: AssetPreloaderService;
|
||||||
|
|
||||||
|
constructor(simMain: SimMain, assets: AssetPreloaderService, canvas: HTMLCanvasElement) {
|
||||||
|
this.assets = assets;
|
||||||
|
this.simMain = simMain;
|
||||||
|
this.canvas = canvas;
|
||||||
|
this.context = this.canvas.getContext("2d")!;
|
||||||
|
this.context.globalCompositeOperation = "source-over";
|
||||||
|
this.wallPattern = this.createPattern(assets.getImage("wall.png"), 48);
|
||||||
|
this.visLevel = new VisLevel(this, this.simMain, this.simMain.gdRoot, assets);
|
||||||
|
const host = this;
|
||||||
|
requestAnimationFrame(function step(timestamp) {
|
||||||
|
host.step(timestamp);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private createPattern(image: HTMLImageElement, size: number): CanvasPattern {
|
||||||
|
const tempCanvas = document.createElement("canvas");
|
||||||
|
const tempContext = tempCanvas.getContext("2d")!;
|
||||||
|
|
||||||
|
tempCanvas.width = size;
|
||||||
|
tempCanvas.height = size;
|
||||||
|
tempContext.drawImage(image, 0, 0, image.width, image.height, 0, 0, size, size);
|
||||||
|
|
||||||
|
return this.context.createPattern(tempCanvas, 'repeat')!;
|
||||||
|
}
|
||||||
|
|
||||||
|
private step(timestamp: number) {
|
||||||
|
if (!this.active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const host = this;
|
||||||
|
requestAnimationFrame((timestamp: number) => {
|
||||||
|
host.step(timestamp);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!this.startTimestamp) {
|
||||||
|
this.startTimestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const simLevel = this.simMain.currentLevel;
|
||||||
|
if (!simLevel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let targetStep = (timestamp - this.startTimestamp) * this.simMain.gdRoot.simulation.stepsPerSecond / 1000 - this.gap;
|
||||||
|
if (simLevel.paused) {
|
||||||
|
this.gap += targetStep - simLevel.currentStep;
|
||||||
|
targetStep = simLevel.currentStep;
|
||||||
|
}
|
||||||
|
this.simMain.executeUntilStep(targetStep);
|
||||||
|
this.visLevel.updateEveryFrame(targetStep);
|
||||||
|
this.onRender();
|
||||||
|
};
|
||||||
|
|
||||||
|
public onResized() {
|
||||||
|
const gameHost = document.getElementById("game-host") as HTMLDivElement;
|
||||||
|
const width = gameHost.clientWidth;
|
||||||
|
const height = gameHost.clientHeight;
|
||||||
|
const ratio = window.devicePixelRatio;
|
||||||
|
this.canvas.width = width * ratio;
|
||||||
|
this.canvas.height = height * ratio;
|
||||||
|
this.canvas.style.width = width + "px";
|
||||||
|
this.canvas.style.height = height + "px";
|
||||||
|
this.context.scale(ratio, ratio);
|
||||||
|
this.visLevel.updateSize();
|
||||||
|
};
|
||||||
|
|
||||||
|
private onRender() {
|
||||||
|
this.clear();
|
||||||
|
const ctx = this.context;
|
||||||
|
ctx.font = "12px Tahoma";
|
||||||
|
const simLevel = this.simMain.currentLevel;
|
||||||
|
if (!!simLevel) {
|
||||||
|
if (!this.ready) {
|
||||||
|
this.onResized();
|
||||||
|
this.ready = true;
|
||||||
|
}
|
||||||
|
this.visLevel.draw();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private clear() {
|
||||||
|
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private stop() {
|
||||||
|
this.active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/app/components/game/vis/VisProjectile.ts
Normal file
16
src/app/components/game/vis/VisProjectile.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { SimProjectile } from "../sim/SimProjectile";
|
||||||
|
import { Vector2 } from "../util/Vector2";
|
||||||
|
|
||||||
|
export class VisProjectile {
|
||||||
|
positions: Vector2[];
|
||||||
|
private simProjectile: SimProjectile;
|
||||||
|
|
||||||
|
constructor(simProjectile: SimProjectile) {
|
||||||
|
this.simProjectile = simProjectile;
|
||||||
|
this.positions = [simProjectile.position, simProjectile.position];
|
||||||
|
}
|
||||||
|
|
||||||
|
public advanceStep() {
|
||||||
|
this.positions = [this.positions[1], this.simProjectile.position];
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user