fixed preloading and integrated vis
This commit is contained in:
@@ -3,6 +3,8 @@ import { OptionsComponent } from '../options/options.component';
|
||||
import { SimMain } from './sim/SimMain';
|
||||
import { GdRoot } from './data/GdRoot';
|
||||
import { SimCommand } from './sim/commands/SimCommand';
|
||||
import { VisMain } from './vis/VisMain';
|
||||
import { SplashComponent } from '../splash/splash.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-game',
|
||||
@@ -10,33 +12,30 @@ import { SimCommand } from './sim/commands/SimCommand';
|
||||
styleUrls: ['./game.component.css'],
|
||||
imports: [OptionsComponent],
|
||||
})
|
||||
export class GameComponent implements OnInit {
|
||||
simMain!: SimMain;
|
||||
private optionsOpen = false;
|
||||
private isPaused = false;
|
||||
private lastFrameTime = 0;
|
||||
private tileSize = 10; // Size of each tile in pixels
|
||||
export class GameComponent {
|
||||
simMain: SimMain = new SimMain();
|
||||
visMain!: VisMain;
|
||||
|
||||
@ViewChild('gameCanvas') canvasRef!: ElementRef<HTMLCanvasElement>;
|
||||
@ViewChild('canvasWrapper') wrapperRef!: ElementRef<HTMLDivElement>;
|
||||
private logicalWidth = 800;
|
||||
private logicalHeight = 600;
|
||||
scaleX: number = 1;
|
||||
scaleY: number = 1;
|
||||
pixelScale: number = 1;
|
||||
optionsOpen: boolean = false;
|
||||
|
||||
async ngOnInit() {
|
||||
async ngAfterViewInit() {
|
||||
const gdRoot = await this.loadGdRoot();
|
||||
this.simMain = new SimMain(gdRoot);
|
||||
requestAnimationFrame(this.gameLoop.bind(this));
|
||||
this.simMain.setGdRoot(gdRoot);
|
||||
this.visMain = new VisMain(this.simMain, SplashComponent.assetPreloader, this.wrapperRef.nativeElement, this.canvasRef.nativeElement);
|
||||
window.addEventListener('resize', _ => this.visMain.onResized());
|
||||
}
|
||||
|
||||
start() {
|
||||
this.simMain.start(performance.now());
|
||||
this.visMain.start();
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.simMain.stop();
|
||||
this.visMain.start();
|
||||
}
|
||||
|
||||
step() {
|
||||
@@ -48,14 +47,13 @@ export class GameComponent implements OnInit {
|
||||
}
|
||||
|
||||
fastForward() {
|
||||
this.simMain.fastForwardToEnd();
|
||||
this.simMain.executeToEnd();
|
||||
}
|
||||
|
||||
async loadGdRoot(): Promise<GdRoot> {
|
||||
const data = await fetch('/assets/data/gdRoot.json').then((r) => r.json());
|
||||
// if (!isGdRoot(data)) {
|
||||
// throw new Error("Invalid GdRoot!");
|
||||
// }
|
||||
const data = await fetch('/assets/data/gdRoot.json').then((r) =>
|
||||
r.json()
|
||||
);
|
||||
const gdRoot: GdRoot = data;
|
||||
return gdRoot;
|
||||
}
|
||||
@@ -64,126 +62,15 @@ export class GameComponent implements OnInit {
|
||||
this.simMain.setGdRoot(await this.loadGdRoot());
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.resizeCanvas();
|
||||
requestAnimationFrame(this.update);
|
||||
window.addEventListener('resize', this.resizeCanvas.bind(this));
|
||||
}
|
||||
|
||||
update = (now: number) => {
|
||||
if (!this.simMain) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.simMain.update(now)
|
||||
|
||||
const lastStepTime = this.simMain.isRunning
|
||||
? this.simMain.lastStepTime
|
||||
: now;
|
||||
const t = this.simMain.isRunning
|
||||
? Math.max(
|
||||
Math.min((now - lastStepTime) / this.simMain.interval, 1),
|
||||
0
|
||||
)
|
||||
: 1;
|
||||
|
||||
this.renderFrame(t);
|
||||
|
||||
requestAnimationFrame(this.update);
|
||||
};
|
||||
|
||||
renderFrame(t: number) {
|
||||
const ctx = this.canvasRef.nativeElement.getContext('2d');
|
||||
if (!ctx) return;
|
||||
|
||||
const canvas = this.canvasRef.nativeElement;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
|
||||
resizeCanvas(): void {
|
||||
const wrapper = this.wrapperRef.nativeElement;
|
||||
const canvas = this.canvasRef.nativeElement;
|
||||
|
||||
const targetAspect = this.logicalWidth / this.logicalHeight;
|
||||
const maxW = wrapper.clientWidth;
|
||||
const maxH = wrapper.clientHeight;
|
||||
|
||||
let width = maxW;
|
||||
let height = width / targetAspect;
|
||||
|
||||
if (height > maxH) {
|
||||
height = maxH;
|
||||
width = height * targetAspect;
|
||||
}
|
||||
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
this.scaleX = canvas.width / this.logicalWidth; // e.g. 800
|
||||
this.scaleY = canvas.height / this.logicalHeight; // e.g. 600
|
||||
|
||||
// Optionally use the smaller of the two for uniform scaling
|
||||
this.pixelScale = Math.min(this.scaleX, this.scaleY);
|
||||
}
|
||||
|
||||
toScreen(x: number, y: number): [number, number] {
|
||||
return [x * this.pixelScale, y * this.pixelScale];
|
||||
}
|
||||
|
||||
fromScreen(px: number, py: number): [number, number] {
|
||||
return [px / this.pixelScale, py / this.pixelScale];
|
||||
}
|
||||
|
||||
onCanvasClick(event: MouseEvent) {
|
||||
const canvas = this.canvasRef.nativeElement;
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const scaleX = canvas.width / rect.width;
|
||||
const scaleY = canvas.height / rect.height;
|
||||
|
||||
const px = (event.clientX - rect.left) * scaleX;
|
||||
const py = (event.clientY - rect.top) * scaleY;
|
||||
|
||||
const [gx, gy] = this.fromScreen(px, py);
|
||||
}
|
||||
|
||||
private gameLoop(currentTime: number): void {
|
||||
if (this.lastFrameTime === 0) {
|
||||
this.lastFrameTime = currentTime;
|
||||
}
|
||||
const deltaTime = (currentTime - this.lastFrameTime) / 1000;
|
||||
this.lastFrameTime = currentTime;
|
||||
|
||||
// Only update the game state if not paused
|
||||
if (!this.isPaused) {
|
||||
this.updateGame(deltaTime);
|
||||
requestAnimationFrame(this.gameLoop.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
private updateGame(deltaTime: number): void {
|
||||
// Implement your game update logic here using deltaTime
|
||||
}
|
||||
|
||||
// Called when opening options: pause the game
|
||||
public openOptions(): void {
|
||||
this.optionsOpen = true;
|
||||
this.pauseGame();
|
||||
this.stop();
|
||||
}
|
||||
|
||||
// Called when closing options: resume the game
|
||||
public closeOptions(): void {
|
||||
this.optionsOpen = false;
|
||||
this.resumeGame();
|
||||
}
|
||||
|
||||
private pauseGame(): void {
|
||||
this.isPaused = true;
|
||||
}
|
||||
|
||||
private resumeGame(): void {
|
||||
this.isPaused = false;
|
||||
// Reset the lastFrameTime to avoid a huge delta on resume
|
||||
this.lastFrameTime = performance.now();
|
||||
requestAnimationFrame(this.gameLoop.bind(this));
|
||||
this.start();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user