import { client } from "../index.js"; import { Game } from "../api/game/Game.js"; import AbstractView from "./abstracts/AbstractView.js"; import { initShaderProgram } from "../3D/shaders.js" import { initBuffers } from "../3D/buffers.js" import "../3D/maths/gl-matrix-min.js" export default class extends AbstractView { constructor(params) { super(params, "Game"); this.game = new Game(client, params.id); this.keys_pressed = []; this.my_player = undefined; this.gl = null; this.shader_prog = null; this.buffers = null; this.programInfo = null; } initGL() { const canvas = document.getElementById('glcanva'); 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.programInfo = { program: this.shader_prog, attribLocations: { vertexPosition: this.gl.getAttribLocation(this.shader_prog, "aPos"), vertexNormal: this.gl.getAttribLocation(this.shader_prog, "aNormal"), }, uniformLocations: { projectionMatrix: this.gl.getUniformLocation(this.shader_prog, "uProj"), modelViewMatrix: this.gl.getUniformLocation(this.shader_prog, "uModView"), normalMatrix: this.gl.getUniformLocation(this.shader_prog, "uNormalMat"), }, }; this.gl.enable(this.gl.CULL_FACE); this.gl.cullFace(this.gl.BACK); } 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 = "glcanva"; document.getElementById("app").appendChild(canvas); this.initGL(); this.render_game(); } draw() { const canvas = document.getElementById('glcanva'); if(canvas === null) return 1; this.gl.clearColor(0.0, 0.0, 0.0, 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 fieldOfView = (90 * Math.PI) / 180; const aspect = this.gl.canvas.clientWidth / this.gl.canvas.clientHeight; const zNear = 0.1; const zFar = 100.0; const projectionMatrix = mat4.create(); mat4.perspective(projectionMatrix, fieldOfView, aspect, zNear, zFar); this.setPositionAttribute(); this.setNormalAttribute(); this.gl.useProgram(this.programInfo.program); this.gl.uniformMatrix4fv( this.programInfo.uniformLocations.projectionMatrix, false, projectionMatrix ); // rendering player bar this.renderCube(0.0, -5.0, -8.0, 0.0, 5); } renderCube(x, y, z, angle = 0, sx = 1, sy = 1, sz = 1) { const modelViewMatrix = mat4.create(); mat4.translate( modelViewMatrix, modelViewMatrix, [x, y, z] ); mat4.rotate( modelViewMatrix, modelViewMatrix, angle, [0, 1, 1], ); mat4.scale( modelViewMatrix, modelViewMatrix, [sx, sy, sz] ); const normalMatrix = mat4.create(); mat4.invert(normalMatrix, modelViewMatrix); mat4.transpose(normalMatrix, normalMatrix); this.gl.uniformMatrix4fv( this.programInfo.uniformLocations.modelViewMatrix, false, modelViewMatrix ); this.gl.uniformMatrix4fv( this.programInfo.uniformLocations.normalMatrix, false, normalMatrix, ); const vertexCount = 36; const type = this.gl.UNSIGNED_SHORT; const offset = 0; this.gl.drawElements(this.gl.TRIANGLES, vertexCount, type, offset); } 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( this.programInfo.attribLocations.vertexNormal, numComponents, type, normalize, stride, offset, ); this.gl.enableVertexAttribArray(this.programInfo.attribLocations.vertexNormal); } setPositionAttribute(programInfo) { 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( this.programInfo.attribLocations.vertexPosition, numComponents, type, normalize, stride, offset ); this.gl.enableVertexAttribArray(this.programInfo.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(); // 1 sec fps }, 1000 / 60); } async update_game_state() { document.getElementById("game-state").innerText = this.game.state; if (this.game.finished === false) await this.join_game(); } async postInit() { let error_code = await this.game.init(); if (error_code) return error_code; await this.update_game_state(); } async getHtml() { return /* HTML */ `
`; } }