Skip to content

Commit

Permalink
Scene: Preserve camera on resize
Browse files Browse the repository at this point in the history
  • Loading branch information
RyanGrieb committed Nov 16, 2023
1 parent 38f74a5 commit 9bdf5ac
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 33 deletions.
7 changes: 7 additions & 0 deletions client/src/Game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,11 @@ export class Game {
if (this.currentScene) {
this.currentScene.redraw();
}
this.canvasContext.fillStyle = options.canvasColor ?? "white";
this.canvasContext.fillRect(0, 0, this.canvas.width, this.canvas.height);
this.canvasContext.font = "12px Times new Roman";
this.canvasContext.imageSmoothingEnabled = false;

}, 300);
});

Expand Down Expand Up @@ -464,6 +468,9 @@ export class Game {
//FIXME: Use cache for meausring text..

let text = textOptions.text;
if (!text) {
return;
}

canvasContext.save();

Expand Down
27 changes: 27 additions & 0 deletions client/src/scene/Camera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,27 @@ export class Camera {
private lastMouseY: number;
private mouseHeld: boolean;
private locked: boolean;
private wasdControls: boolean;
private mouseControls: boolean;

public static fromCamera(camera: Camera) {
const newCamera = new Camera({
wasd_controls: camera.hasWASDControls(),
mouse_controls: camera.hasMouseControls(),
});

newCamera.setPosition(camera.getX(), camera.getY());
newCamera.setZoom(camera.getZoomAmount());
return newCamera;
}

constructor(options: CameraOptions) {
this.keysHeld = [];
this.x = 0;
this.y = 0;

this.wasdControls = options.wasd_controls;
this.mouseControls = options.mouse_controls;
this.xVelAmount = 0;
this.yVelAmount = 0;
this.zoomAmount = 1;
Expand Down Expand Up @@ -144,6 +159,18 @@ export class Camera {
}
}

public hasWASDControls() {
return this.wasdControls;
}

public hasMouseControls() {
return this.mouseControls;
}

public setZoom(amount: number) {
this.zoomAmount = amount;
}

public zoomToLocation(x: number, y: number, zoomAmount: number) {
this.setPosition(-x + Game.getWidth() / 2, -y + Game.getHeight() / 2);
this.zoom(Game.getWidth() / 2, Game.getHeight() / 2, zoomAmount, false);
Expand Down
11 changes: 10 additions & 1 deletion client/src/scene/Scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ export abstract class Scene {

protected storedEvents: Map<string, Function[]>;
protected firstLoad: boolean;
private sceneObjects: SceneObject[];
private camera: Camera;
private oldCamera: Camera;
private sceneObjects: SceneObject[];
private name: string;

constructor() {
Expand Down Expand Up @@ -82,6 +83,10 @@ export abstract class Scene {
}
});

if (this.camera) {
this.oldCamera = this.camera;
}

this.camera = undefined;
this.sceneObjects = [];
this.storedEvents.clear();
Expand Down Expand Up @@ -124,6 +129,10 @@ export abstract class Scene {
return this.camera;
}

public restoreCamera() {
this.camera = Camera.fromCamera(this.oldCamera);
}

public sortSceneObjects() {
this.sceneObjects.sort((obj1, obj2) => {
return obj1.getZIndex() - obj2.getZIndex();
Expand Down
24 changes: 16 additions & 8 deletions client/src/scene/type/InGameScene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@ export class InGameScene extends Scene {
public onInitialize(): void {
GameMap.init();
this.players = [];

const camera = new Camera({
wasd_controls: false,
mouse_controls: true,
//initial_position: [1, 1],
});
this.setCamera(camera);
if (this.firstLoad) {
const camera = new Camera({
wasd_controls: false,
mouse_controls: true,
//initial_position: [1, 1],
});
this.setCamera(camera);
} else {
this.restoreCamera();
}

// Initialize all existing players
WebsocketClient.sendMessage({ event: "connectedPlayers" });
Expand Down Expand Up @@ -82,6 +85,7 @@ export class InGameScene extends Scene {
height: 42,
fontColor: "white",
onClicked: () => {
console.log("next turn!");
WebsocketClient.sendMessage({ event: "nextTurnRequest" });
},
});
Expand Down Expand Up @@ -145,7 +149,11 @@ export class InGameScene extends Scene {
);
});*/

WebsocketClient.sendMessage({ event: "loadedIn" });
//FIXME: re-create cities if they already exist (resizing, loading in existing game).

if (this.firstLoad) {
WebsocketClient.sendMessage({ event: "loadedIn" });
}
});
}

Expand Down
24 changes: 2 additions & 22 deletions server/src/Game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ import { State } from "./state/State";
import { WebSocket } from "ws";
import { ServerEvents } from "./Events";

import fs from "fs";
import YAML from "yaml";

/**
* Game class is responsible for managing the state of the game, and players.
*/
Expand All @@ -14,21 +11,13 @@ export class Game {
private static currentState: State;
private static states: Map<string, State>;
private static players: Map<string, Player>;
private static cityBuildings: Record<string, any>[];

/**
* Initializes the game by setting up server event listeners for various events.
*/
public static init() {
this.states = new Map<string, State>();

// Load available buildings from config file
const buildingsYMLData = YAML.parse(
fs.readFileSync("./config/buildings.yml", "utf-8")
);
//Convert civsData from YAML to JSON:
this.cityBuildings = JSON.parse(JSON.stringify(buildingsYMLData.buildings));

// Set up the listener for the "setState" event. Changes the game-state.
ServerEvents.on({
eventName: "setState",
Expand Down Expand Up @@ -124,17 +113,8 @@ export class Game {
return undefined;
}

public static getBuildingDataByName(name: string) {
for (const building of this.cityBuildings) {
if (
(building.name as string).toLocaleLowerCase() ===
name.toLocaleLowerCase()
) {
return building;
}
}

return undefined;
public static getCurrentStateAs<T extends State>(): T {
return this.currentState as T;
}

private static getPlayerJSONS() {
Expand Down
17 changes: 17 additions & 0 deletions server/src/Player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export class Player {
private loadedIn: boolean;
/** The callback to execute when the player has loaded into the game. */
private loadedInCallback: () => void;
/** The callback to execute when the player resizes their window. */
private resizeWindowCallback: () => void;
private requestedNextTurn: boolean;
private civilizationData: Record<string, any>;
private cities: City[];
Expand Down Expand Up @@ -58,6 +60,17 @@ export class Player {
},
globalEvent: true,
});

ServerEvents.on({
eventName: "resizeWindow",
parentObject: this,
callback: (data, websocket) => {
if (this.wsConnection != websocket) return;

this.resizeWindowCallback.call(undefined);
},
globalEvent: true,
});
}

/**
Expand All @@ -80,6 +93,10 @@ export class Player {
this.loadedInCallback = callback;
}

public onResizeWindow(callback: () => void) {
this.resizeWindowCallback = callback;
}

public setRequestedNextTurn(value: boolean) {
this.requestedNextTurn = value;
}
Expand Down
4 changes: 3 additions & 1 deletion server/src/city/City.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Game } from "../Game";
import { Player } from "../Player";
import { GameMap } from "../map/GameMap";
import { Tile } from "../map/Tile";
import { InGameState } from "../state/type/InGameState";

export interface CityOptions {
tile: Tile;
Expand Down Expand Up @@ -71,7 +72,8 @@ export class City {

public addBuilding(name: string) {
// Get the building data from YML
const buildingData = Game.getBuildingDataByName(name);
const buildingData =
Game.getCurrentStateAs<InGameState>().getBuildingDataByName(name);

// Apply any effects to the building if any (faith, culture, bonuses, etc.)):
//...
Expand Down
1 change: 1 addition & 0 deletions server/src/map/Tile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export class Tile {
}

public setCity(city: City) {
this.addTileType("city");
this.city = city;
}

Expand Down
25 changes: 24 additions & 1 deletion server/src/state/type/InGameState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,32 @@ import { Game } from "../../Game";
import { ServerEvents } from "../../Events";
import { State } from "../State";
import { GameMap } from "../../map/GameMap";
import { Server } from "http";
import { Unit } from "../../Unit";
import { City } from "../../city/City";
import { Job, gracefulShutdown, scheduleJob } from "node-schedule";

import fs from "fs";
import YAML from "yaml";

export class InGameState extends State {
private turnTimeJob: Job;
private currentTurn: number;
private totalTurnTime: number;
private turnTime: number;
private cityBuildings: Record<string, any>[];

public onInitialize() {
this.totalTurnTime = 60; //TODO: Allow modification
this.currentTurn = 0;
this.turnTime = 0;

// Load available buildings from config file
const buildingsYMLData = YAML.parse(
fs.readFileSync("./config/buildings.yml", "utf-8")
);
//Convert civsData from YAML to JSON:
this.cityBuildings = JSON.parse(JSON.stringify(buildingsYMLData.buildings));

// Set loading screen for players
Game.getPlayers().forEach((player) => {
player.sendNetworkEvent({ event: "setScene", scene: "loading_scene" });
Expand Down Expand Up @@ -176,6 +186,19 @@ export class InGameState extends State {
});
}

public getBuildingDataByName(name: string) {
for (const building of this.cityBuildings) {
if (
(building.name as string).toLocaleLowerCase() ===
name.toLocaleLowerCase()
) {
return building;
}
}

return undefined;
}

// Decrease trunTime by -1 every 1 second
private beginTurnTimer() {
this.turnTimeJob = scheduleJob("* * * * * *", () => {
Expand Down

0 comments on commit 9bdf5ac

Please sign in to comment.