You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
6.0 KiB
214 lines
6.0 KiB
<script lang="ts">
|
|
import { GAME_EVENTS } from "./constants";
|
|
import { Game } from "./Game";
|
|
import { formatWebsocketData } from "./utils";
|
|
import GameCreation from "./GameCreation.svelte";
|
|
import GameComponent from "./GameComponent.svelte";
|
|
import type { StringDto } from "./dtos/StringDto";
|
|
import Matchmaking from "./Matchmaking.svelte";
|
|
import type { MatchmakingDto } from "./dtos/MatchmakingDto";
|
|
import { getUser, store } from "../../Auth";
|
|
import ColorPicker from "./ColorPicker.svelte";
|
|
import { APPSTATE } from "../../App.svelte";
|
|
|
|
export function inviteToGame(event: CustomEvent<string>) {
|
|
setAppState(APPSTATE.CREATE_GAME);
|
|
invitedUsername = event.detail;
|
|
}
|
|
|
|
export let fakeUser: boolean;
|
|
export let appState: string;
|
|
export let setAppState: (newState: APPSTATE | string) => void;
|
|
|
|
const SERVER_URL = `ws://${import.meta.env.VITE_HOST}:${
|
|
import.meta.env.VITE_BACK_PORT
|
|
}`;
|
|
|
|
let gamePlaying: boolean = false;
|
|
let connected: boolean = false;
|
|
let loggedIn: boolean = false;
|
|
let failedLogIn: boolean = false;
|
|
let socket: WebSocket;
|
|
let elementsColor: string = "#FFFFFF";
|
|
let backgroundColor: string = "#000000";
|
|
let game: Game;
|
|
let renderCanvas: HTMLCanvasElement;
|
|
let canvas: HTMLCanvasElement;
|
|
let context: CanvasRenderingContext2D;
|
|
let invitedUsername: string = "";
|
|
|
|
function setupSocket(
|
|
_renderCanvas: HTMLCanvasElement,
|
|
_canvas: HTMLCanvasElement,
|
|
_context: CanvasRenderingContext2D
|
|
) {
|
|
socket = new WebSocket(SERVER_URL);
|
|
renderCanvas = _renderCanvas;
|
|
canvas = _canvas;
|
|
context = _context;
|
|
game = new Game(
|
|
_renderCanvas,
|
|
canvas,
|
|
context,
|
|
elementsColor,
|
|
backgroundColor
|
|
);
|
|
|
|
socket.onmessage = function (e) {
|
|
const event_json = JSON.parse(e.data);
|
|
const event = event_json.event;
|
|
const data = event_json.data;
|
|
|
|
if (event == GAME_EVENTS.START_GAME) {
|
|
game.start(socket);
|
|
} else if (event == GAME_EVENTS.GAME_TICK) {
|
|
game.update(data);
|
|
} else if (event == GAME_EVENTS.GET_GAME_INFO) {
|
|
if (data && data.gameId != game.id) {
|
|
if (gamePlaying && data.gameId == "") {
|
|
resetMenus();
|
|
gamePlaying = false;
|
|
}
|
|
if (data.yourPaddleIndex !== -2) {
|
|
gamePlaying = true;
|
|
game.setInfo(data);
|
|
}
|
|
}
|
|
} else if (event == GAME_EVENTS.REGISTER_PLAYER) {
|
|
if (data) {
|
|
loggedIn = true;
|
|
setInterval(() => {
|
|
updateGameInfo();
|
|
}, 1000);
|
|
} else {
|
|
failedLogIn = true;
|
|
}
|
|
} else if (event == GAME_EVENTS.CREATE_GAME) {
|
|
if (data) gamePlaying = true;
|
|
} else if (event == GAME_EVENTS.MATCHMAKING) {
|
|
if (data.matchmaking && appState !== APPSTATE.MATCHMAKING) {
|
|
setAppState(APPSTATE.MATCHMAKING);
|
|
} else if (!data.matchmaking && appState === APPSTATE.MATCHMAKING) {
|
|
setAppState(APPSTATE.HOME);
|
|
}
|
|
} else if (event == GAME_EVENTS.READY) {
|
|
game.youAreReady = true;
|
|
} else {
|
|
console.log(
|
|
"Unknown event from server: " + event + " with data " + data
|
|
);
|
|
}
|
|
};
|
|
socket.onopen = onSocketOpen;
|
|
socket.onclose = onSocketClose;
|
|
}
|
|
|
|
async function onSocketOpen() {
|
|
if (!fakeUser) await getUser();
|
|
void logIn();
|
|
connected = true;
|
|
}
|
|
|
|
async function onSocketClose() {
|
|
connected = false;
|
|
setupSocket(renderCanvas, canvas, context);
|
|
}
|
|
|
|
function updateGameInfo() {
|
|
socket.send(formatWebsocketData(GAME_EVENTS.GET_GAME_INFO));
|
|
}
|
|
|
|
async function logIn() {
|
|
const data: { playerName: StringDto; socketKey: StringDto } = {
|
|
playerName: { value: $store.username },
|
|
socketKey: { value: $store.socketKey },
|
|
};
|
|
socket.send(formatWebsocketData(GAME_EVENTS.REGISTER_PLAYER, data));
|
|
}
|
|
|
|
function startMatchmaking() {
|
|
const data: MatchmakingDto = { matchmaking: true };
|
|
socket.send(formatWebsocketData(GAME_EVENTS.MATCHMAKING, data));
|
|
}
|
|
|
|
function stopMatchmaking() {
|
|
const data: MatchmakingDto = { matchmaking: false };
|
|
socket.send(formatWebsocketData(GAME_EVENTS.MATCHMAKING, data));
|
|
}
|
|
|
|
function resetMenus() {
|
|
setAppState(APPSTATE.HOME);
|
|
game.youAreReady = false;
|
|
}
|
|
|
|
$: {
|
|
if (game !== undefined) {
|
|
game.updateColors(elementsColor, backgroundColor);
|
|
}
|
|
}
|
|
|
|
$: {
|
|
if (socket && socket.readyState) {
|
|
if (appState === APPSTATE.MATCHMAKING) {
|
|
startMatchmaking();
|
|
} else if (appState !== APPSTATE.MATCHMAKING) {
|
|
stopMatchmaking();
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<main>
|
|
<GameComponent {game} {gamePlaying} {setupSocket} {socket} />
|
|
{#if gamePlaying}
|
|
<div />
|
|
{:else if loggedIn}
|
|
<h1>Choose a gamemode</h1>
|
|
<button on:click={startMatchmaking}>Matchmaking</button>
|
|
<button on:click={() => setAppState(APPSTATE.CREATE_GAME)}
|
|
>Play with a friend</button
|
|
>
|
|
<label for="colorPicker">Elements color:</label>
|
|
<ColorPicker bind:color={elementsColor} />
|
|
<label for="colorPicker">Background color:</label>
|
|
<ColorPicker bind:color={backgroundColor} />
|
|
|
|
{#if appState === APPSTATE.MATCHMAKING}
|
|
<div on:click={stopMatchmaking} on:keydown={stopMatchmaking}>
|
|
<Matchmaking {stopMatchmaking} />
|
|
</div>
|
|
{:else if appState === APPSTATE.CREATE_GAME}
|
|
<div
|
|
on:click={() => setAppState(APPSTATE.HOME)}
|
|
on:keydown={() => setAppState(APPSTATE.HOME)}
|
|
>
|
|
<GameCreation {socket} {invitedUsername} />
|
|
</div>
|
|
{/if}
|
|
{:else if !connected}
|
|
Connecting to game server...
|
|
{:else if failedLogIn}
|
|
Failed to log in to game server. Do you have multiple pages open at the same
|
|
time? If yes, please close them and try again.
|
|
{:else if !loggedIn}
|
|
Logging in to game server...
|
|
{/if}
|
|
</main>
|
|
|
|
<style>
|
|
main {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
}
|
|
|
|
h1 {
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
button {
|
|
font-size: 1.5rem;
|
|
padding: 1rem 2rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
</style>
|
|
|