import { client } from "../index.js"; import { Game } from "../api/game/Game.js"; import AbstractView from "./abstracts/AbstractView.js"; import { initShaderProgram, shaderInfos } from "../3D/shaders.js" import { initBuffers } from "../3D/buffers.js" import "../3D/maths/gl-matrix-min.js" import { MyPlayer } from "../api/game/MyPlayer.js"; import { lang } from "../index.js"; export default class extends AbstractView { constructor(params) { super(params, "Game"); this.game = new Game(client, params.id, this.update_goal); this.keys_pressed = []; this.my_player = undefined; this.gl = null; this.shader_prog = null; this.buffers = null; this.cam_pos = [0, 400, 0]; this.cam_target = [0, 0, 0]; this.cam_up = [0, 0, -1]; } keyReleaseHandler(event) { let idx = this.keys_pressed.indexOf(event.key); if(idx != -1) this.keys_pressed.splice(idx, 1); } keyPressHandler(event) { if(!this.keys_pressed.includes(event.key)) this.keys_pressed.push(event.key); } initGL() { const canvas = document.getElementById('canva'); this.gl = canvas.getContext("webgl"); if(this.gl === null) { alert("Unable to initialize WebGL. Your browser or machine may not support it. You may also be a bozo"); return; } this.shader_prog = initShaderProgram(this.gl); this.buffers = initBuffers(this.gl); this.gl.enable(this.gl.CULL_FACE); this.gl.cullFace(this.gl.BACK); } update_goal(data) { document.getElementById(`goal-${data.player}`).innerText = data.nb_goal; } register_key() { this.keyPressHandler = this.keyPressHandler.bind(this); this.keyReleaseHandler = this.keyReleaseHandler.bind(this); document.addEventListener('keydown', this.keyPressHandler); document.addEventListener('keyup', this.keyReleaseHandler); } unregister_key() { document.removeEventListener('keydown', this.keyPressHandler); document.removeEventListener('keyup', this.keyReleaseHandler); } async join_game() { await this.game.join() let canvas = document.createElement("canvas"); canvas.height = this.game.config.size_x; canvas.width = this.game.config.size_y; canvas.id = "canva"; document.getElementById("app").appendChild(canvas); let index = this.game.players.findIndex((player) => player.id === client.me.id); if (index !== -1) { let my_player = this.game.players[index]; this.my_player = new MyPlayer(client, this.game, my_player.rail, my_player.nb_goal, my_player.position, ); this.game.players[index] = this.my_player; } this.register_key(); this.initGL(); this.render_game(); } draw() { const canvas = document.getElementById('canva'); if(canvas === null) return 1; this.gl.clearColor(0.1, 0.1, 0.1, 1.0); this.gl.clearDepth(1.0); this.gl.enable(this.gl.DEPTH_TEST); this.gl.depthFunc(this.gl.LEQUAL); this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); const projectionMatrix = mat4.create(); const viewMatrix = mat4.create(); mat4.perspective(projectionMatrix, (90 * Math.PI) / 180, this.gl.canvas.clientWidth / this.gl.canvas.clientHeight, 0.1, 10000000.0); mat4.lookAt(viewMatrix, this.cam_pos, this.cam_target, this.cam_up); this.setPositionAttribute(); this.setNormalAttribute(); this.gl.useProgram(shaderInfos.program); this.gl.uniformMatrix4fv(shaderInfos.uniformLocations.projectionMatrix, false, projectionMatrix); this.gl.uniformMatrix4fv(shaderInfos.uniformLocations.viewMatrix, false, viewMatrix); this.game.render(this.gl); } setNormalAttribute() { const numComponents = 3; const type = this.gl.FLOAT; const normalize = false; const stride = 0; const offset = 0; this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.normal); this.gl.vertexAttribPointer( shaderInfos.attribLocations.vertexNormal, numComponents, type, normalize, stride, offset, ); this.gl.enableVertexAttribArray(shaderInfos.attribLocations.vertexNormal); } setPositionAttribute() { const numComponents = 3; const type = this.gl.FLOAT; const normalize = false; const stride = 0; const offset = 0; this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.vertex); this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.buffers.index); this.gl.vertexAttribPointer( shaderInfos.attribLocations.vertexPosition, numComponents, type, normalize, stride, offset ); this.gl.enableVertexAttribArray(shaderInfos.attribLocations.vertexPosition); } render_game() { let loop_id = setInterval(() => { if (this.game === undefined) clearInterval(loop_id); if (this.my_player) this.my_player.update_paddle(this.keys_pressed); this.draw(); this.game?.time.new_frame(); }, 1000 / 60); } async update_game_state() { document.getElementById("game-state").innerText = this.game.state; if (this.game.finished === false) await this.join_game(); } display_players_list() { let players_list = document.getElementById("players_list"); this.game.players.forEach(player => { let tr = document.createElement("tr"); let name = document.createElement("td"); let goal = document.createElement("td"); name.id = `username-${player.id}`; goal.id = `goal-${player.id}`; name.innerText = player.username; goal.innerText = player.nb_goal; tr.appendChild(name); tr.appendChild(goal); players_list.appendChild(tr); }); } toggle2D() { window.location.replace(location.href.substring(0, location.href.lastIndexOf('/')) + "/0"); } async postInit() { let error_code = await this.game.init(); if (error_code) return error_code; await this.update_game_state(); this.display_players_list(); document.getElementById("game-mode").onclick = this.toggle2D; } async leavePage() { if (this.game.finished === false) { this.game.leave(); this.game = undefined; } this.unregister_key(); } async getHtml() { return /* HTML */ `
${lang.get("gamePlayersListName")} | ${lang.get("gameGoalTaken")} |
---|