summaryrefslogtreecommitdiff
path: root/client/src
diff options
context:
space:
mode:
authorElizabeth (Lizzy) Hunt <elizabeth.hunt@simponic.xyz>2023-08-26 17:57:05 -0600
committerGitHub <noreply@github.com>2023-08-26 17:57:05 -0600
commit8a4ab8d79b5ce1dabb431168398b5d5111fe326c (patch)
treee60767dc5295edf379cf421e20171dc418e548b7 /client/src
parentc6e9baa0009f7cce0f6ff156a3957ef04a8cb684 (diff)
parent6ce6946a4401d2ee6fa5cb747fab7d4c658a63c8 (diff)
downloadjumpstorm-8a4ab8d79b5ce1dabb431168398b5d5111fe326c.tar.gz
jumpstorm-8a4ab8d79b5ce1dabb431168398b5d5111fe326c.zip
Merge pull request #1 from Simponic/network
Network
Diffstat (limited to 'client/src')
-rw-r--r--client/src/JumpStorm.ts168
-rw-r--r--client/src/components/GameCanvas.svelte18
-rw-r--r--client/src/components/LeaderBoard.svelte2
-rw-r--r--client/src/main.ts4
-rw-r--r--client/src/routes/Home.svelte3
5 files changed, 160 insertions, 35 deletions
diff --git a/client/src/JumpStorm.ts b/client/src/JumpStorm.ts
index bd48483..6f9e24f 100644
--- a/client/src/JumpStorm.ts
+++ b/client/src/JumpStorm.ts
@@ -1,5 +1,6 @@
-import { Floor, Player } from "@engine/entities";
-import { Game } from "@engine/Game";
+import { Game } from '@engine/Game';
+import { Entity } from '@engine/entities';
+import { Grid } from '@engine/structures';
import {
WallBounds,
FacingDirection,
@@ -7,28 +8,141 @@ import {
Physics,
Input,
Collision,
-} from "@engine/systems";
+ NetworkUpdate
+} from '@engine/systems';
+import {
+ type MessageQueueProvider,
+ type MessagePublisher,
+ type MessageProcessor,
+ type Message,
+ type EntityAddBody,
+ MessageType,
+ type EntityUpdateBody
+} from '@engine/network';
+import { stringify, parse } from '@engine/utils';
-export class JumpStorm {
+class ClientMessageProcessor implements MessageProcessor {
private game: Game;
+
+ constructor(game: Game) {
+ this.game = game;
+ }
+
+ public process(message: Message) {
+ switch (message.type) {
+ case MessageType.NEW_ENTITIES:
+ const entityAdditions = message.body as unknown as EntityAddBody[];
+ entityAdditions.forEach((addBody) =>
+ this.game.addEntity(
+ Entity.from(addBody.entityName, addBody.id, addBody.args)
+ )
+ );
+ break;
+ case MessageType.REMOVE_ENTITIES:
+ const ids = message.body as unknown as string[];
+ ids.forEach((id) => this.game.removeEntity(id));
+ break;
+ case MessageType.UPDATE_ENTITIES:
+ const entityUpdates = message.body as unknown as EntityUpdateBody[];
+ entityUpdates.forEach(
+ ({ id, args }) => this.game.getEntity(id)?.setFrom(args)
+ );
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+class ClientSocketMessageQueueProvider implements MessageQueueProvider {
private socket: WebSocket;
+ private messages: Message[];
+
+ constructor(socket: WebSocket) {
+ this.socket = socket;
+ this.messages = [];
- constructor(ctx: CanvasRenderingContext2D) {
- this.game = new Game();
- this.socket = new WebSocket("ws://localhost:8080");
+ this.socket.addEventListener('message', (e) => {
+ const messages = parse<Message[]>(e.data);
+ this.messages = this.messages.concat(messages);
+ });
+ }
+
+ public getNewMessages() {
+ return this.messages;
+ }
+
+ public clearMessages() {
+ this.messages = [];
+ }
+}
+
+class ClientSocketMessagePublisher implements MessagePublisher {
+ private socket: WebSocket;
+ private messages: Message[];
+
+ constructor(socket: WebSocket) {
+ this.socket = socket;
+ this.messages = [];
+ }
+
+ public addMessage(message: Message) {
+ this.messages.push(message);
+ }
+
+ public publish() {
+ if (this.socket.readyState == WebSocket.OPEN) {
+ this.messages.forEach((message: Message) =>
+ this.socket.send(stringify(message))
+ );
+ this.messages = [];
+ }
+ }
+}
+
+export class JumpStorm {
+ private game: Game;
+ private clientId: string;
+
+ constructor(game: Game) {
+ this.game = game;
+ }
+
+ public async init(
+ ctx: CanvasRenderingContext2D,
+ httpMethod: string,
+ wsMethod: string,
+ host: string
+ ) {
+ this.clientId = await this.getAssignedCookie(
+ `${httpMethod}://${host}/assign`
+ );
+ const socket = new WebSocket(`${wsMethod}://${host}/game`);
+ const clientSocketMessageQueueProvider =
+ new ClientSocketMessageQueueProvider(socket);
+ const clientSocketMessagePublisher = new ClientSocketMessagePublisher(
+ socket
+ );
+ const clientMessageProcessor = new ClientMessageProcessor(this.game);
+
+ const inputSystem = new Input(this.clientId, clientSocketMessagePublisher);
+ this.addWindowEventListenersToInputSystem(inputSystem);
+
+ const grid = new Grid();
[
- this.createInputSystem(),
+ new NetworkUpdate(
+ clientSocketMessageQueueProvider,
+ clientSocketMessagePublisher,
+ clientMessageProcessor
+ ),
+ inputSystem,
new FacingDirection(),
new Physics(),
- new Collision(),
- new WallBounds(ctx.canvas.width),
- new Render(ctx),
+ new Collision(grid),
+ new WallBounds(),
+ new Render(ctx)
].forEach((system) => this.game.addSystem(system));
-
- [new Floor(160), new Player()].forEach((entity) =>
- this.game.addEntity(entity),
- );
}
public play() {
@@ -41,16 +155,26 @@ export class JumpStorm {
requestAnimationFrame(loop);
}
- private createInputSystem(): Input {
- const inputSystem = new Input();
-
- window.addEventListener("keydown", (e) => {
+ private addWindowEventListenersToInputSystem(input: Input) {
+ window.addEventListener('keydown', (e) => {
if (!e.repeat) {
- inputSystem.keyPressed(e.key);
+ input.keyPressed(e.key.toLowerCase());
}
});
- window.addEventListener("keyup", (e) => inputSystem.keyReleased(e.key));
- return inputSystem;
+ window.addEventListener('keyup', (e) =>
+ input.keyReleased(e.key.toLowerCase())
+ );
+ }
+
+ private async getAssignedCookie(endpoint: string): Promise<string> {
+ return fetch(endpoint)
+ .then((resp) => {
+ if (resp.ok) {
+ return resp.text();
+ }
+ throw resp;
+ })
+ .then((cookie) => cookie);
}
}
diff --git a/client/src/components/GameCanvas.svelte b/client/src/components/GameCanvas.svelte
index ae8c1b0..ea7dd15 100644
--- a/client/src/components/GameCanvas.svelte
+++ b/client/src/components/GameCanvas.svelte
@@ -1,24 +1,26 @@
<script lang="ts">
import { onMount } from "svelte";
import { loadAssets } from "@engine/config";
+ import { Game } from "@engine/Game";
import { JumpStorm } from "../JumpStorm";
-
+
let canvas: HTMLCanvasElement;
let ctx: CanvasRenderingContext2D;
export let width: number;
export let height: number;
- let jumpStorm: JumpStorm;
-
- onMount(() => {
+ onMount(async () => {
ctx = canvas.getContext("2d");
ctx.imageSmoothingEnabled = false;
- loadAssets().then(() => {
- jumpStorm = new JumpStorm(ctx);
- jumpStorm.play();
- });
+ await loadAssets();
+
+ const game = new Game();
+ const jumpStorm = new JumpStorm(game);
+
+ await jumpStorm.init(ctx, "http", "ws", document.location.host + "/api");
+ jumpStorm.play();
});
</script>
diff --git a/client/src/components/LeaderBoard.svelte b/client/src/components/LeaderBoard.svelte
index 8343c56..2f3e411 100644
--- a/client/src/components/LeaderBoard.svelte
+++ b/client/src/components/LeaderBoard.svelte
@@ -3,7 +3,7 @@
const MAX_ENTRIES = 8;
- export let entries: { name: string, score: number }[] = [];
+ export let entries: { name: string; score: number }[] = [];
</script>
<div class="leaderboard">
diff --git a/client/src/main.ts b/client/src/main.ts
index 5332616..aa7431f 100644
--- a/client/src/main.ts
+++ b/client/src/main.ts
@@ -1,7 +1,7 @@
-import App from "./App.svelte";
+import App from './App.svelte';
const app = new App({
- target: document.getElementById("app"),
+ target: document.getElementById('app')
});
export default app;
diff --git a/client/src/routes/Home.svelte b/client/src/routes/Home.svelte
index 9ada10e..71ad324 100644
--- a/client/src/routes/Home.svelte
+++ b/client/src/routes/Home.svelte
@@ -3,10 +3,9 @@
import LeaderBoard from "../components/LeaderBoard.svelte";
import { Miscellaneous } from "@engine/config";
-
+
let width: number = Miscellaneous.WIDTH;
let height: number = Miscellaneous.HEIGHT;
-
</script>
<div class="centered-game">