From 2a1fe1d0a97e2b1f44f96fff1d86e177a1dee23e Mon Sep 17 00:00:00 2001 From: Maciej Samborski Date: Fri, 27 Dec 2024 14:05:20 +0100 Subject: [PATCH] Added Input support --- assets/character.png | Bin 0 -> 1057 bytes assets/wall.png | Bin 0 -> 4335 bytes src/js/common.js | 44 ++++++++++++++++++++++++----- src/js/common.ts | 61 +++++++++++++++++++++++++++++++++------ src/js/draw.ts | 2 +- src/js/graphics.js | 25 ++++++++++++---- src/js/graphics.ts | 30 ++++++++++++++++---- src/js/input.js | 35 +++++++++++++++++++++++ src/js/input.ts | 39 +++++++++++++++++++++++++ src/js/script.js | 51 +++++++++++++++++++++++++++------ src/js/script.ts | 66 ++++++++++++++++++++++++++++++++++++------- 11 files changed, 307 insertions(+), 46 deletions(-) create mode 100644 assets/character.png create mode 100644 assets/wall.png create mode 100644 src/js/input.js create mode 100644 src/js/input.ts diff --git a/assets/character.png b/assets/character.png new file mode 100644 index 0000000000000000000000000000000000000000..4f0fe76073c3ed3a6659b7ac9dea6fa89877e053 GIT binary patch literal 1057 zcmV++1m63JP)Px&+et)0RCt{2THjC8P#8Uz2o_Wf$p#S{O9@YmEWwyLqnJG}`vZJ6{u%ma{9}A} zS>oFw8kdDYLN*@=p_Gge*a8YnD=}Oj#_igz>qhK%i`tVcU4Pv6p7WjWyZ3ejB1DJ~ zAwq-*5h6s05FtW@2oe4>urME=Sr2Tl)hb)@en8cNQVJ(0W!I)i?FqA+TWEK z4c4{^P1o&XreTPEF2e;<9N;7kz(p9k4%0AP=S{NDtX^X70%?c+>5+v7?_{Y z`nKN!P|O!d`#3~(<4)^~sP`jZW9^R&kO=?)Q>=aa>vyLCpo_d0;TNx7Vt0R!vTHU- z1n`Rf#>Y=RuXhqwIq?4V8$6u6L(#P^kU3zA4cWzQpPvKhjy@ota3=y6Kt$iJIITk&yh{5Fwn}&gDRmJD! zWdQBBJLT#+%GGtOtgX4)oHQ*cW1~_dFF-O1JX%@;(EVELy!-`2sd=34?g5L7_;9f8 zYWH+ z&Fp)vh^c7nx zKJK!-->@fhNF;Hc>5EUXY)KoMK4+)7XRisV_q6Fn+XmYUD+-m7ob-ph5b9z zKsK&q3J4d-NQ2M>a9TY~7hD+!^b&#E1)&aueg#ifF_h+jel{=W3oMLzffNCR3u1f( z!-q}#}-Ls^6Bdf4h00000NkvXXu0mjfR^8@; literal 0 HcmV?d00001 diff --git a/assets/wall.png b/assets/wall.png new file mode 100644 index 0000000000000000000000000000000000000000..b80d69a93ca51e8fefd52b0d9ba7ab82b476b3f6 GIT binary patch literal 4335 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 { return [this.x, this.y, this.z]; } @@ -124,6 +145,24 @@ class Vec4 { this.w -= other.w; } + multScalar(scalar: number) { + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + this.w *= scalar; + } + + multScalarNew(scalar: number): Vec4 { + let vec = new Vec4(this.x, this.y, this.z, this.w); + + vec.x *= scalar; + vec.y *= scalar; + vec.z *= scalar; + vec.w *= scalar; + + return vec; + } + div(other: Vec4) { if ( other.x == 0 || other.y == 0 || @@ -157,6 +196,10 @@ class Vec4 { return vec; } + + reduce(): Vec3 { + return new Vec3(this.x, this.y, this.z); + } } type Mat4Init = number | Float32Array; @@ -199,15 +242,6 @@ class Mat4 { } static isometric(): Mat4 { - //let m = new Mat4(new Float32Array([ - // Math.sqrt(3), 0, -Math.sqrt(3), 0, - // 1, 2, 1, 0, - // Math.sqrt(2), -Math.sqrt(2), Math.sqrt(2), 0, - // 0, 0, 0, 1, - //])); - - //m.multScalar(1 / Math.sqrt(6)); - let m = new Mat4(new Float32Array([ 1, -1, 0, 0, 1, 1, 0, 0, @@ -251,6 +285,15 @@ class Mat4 { return new Mat4(data); } + static translate(t: Vec3): Mat4 { + return new Mat4(new Float32Array([ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + t.x, t.y, t.z, 1, + ])); + } + x(n: Mat4X) { return this.data[n]; } diff --git a/src/js/draw.ts b/src/js/draw.ts index 8879fff..8863560 100644 --- a/src/js/draw.ts +++ b/src/js/draw.ts @@ -87,7 +87,7 @@ export function drawRectangle(gfx: Graphics, corners: [Vec3, Vec3, Vec3, Vec3], } -export function drawIsometricCube(gfx: Graphics, position: Vec3, exts: Vec3, color: Color) { +export function drawIsometricCube(gfx: Graphics, position: Vec3, exts: Vec3, color: Color | Texture) { let points = [ position, new Vec3(position.x, position.y + exts.y, position.z), diff --git a/src/js/graphics.js b/src/js/graphics.js index 64d9a0b..d52313c 100644 --- a/src/js/graphics.js +++ b/src/js/graphics.js @@ -1,4 +1,5 @@ -function fullscreenCanvas(gfx, id) { +import { Vec4 } from "./common.js"; +export function fullscreenCanvas(gfx, id) { const canvas = document.getElementById(id); canvas.width = window.innerWidth; canvas.height = window.innerHeight; @@ -38,7 +39,7 @@ function createProgram(ctx, vertexShaderSource, fragmentShaderSource) { } return program; } -class Graphics { +export class Graphics { ctx; program; attribs = new Map(); @@ -80,7 +81,7 @@ class Graphics { return loc; } } -class Attribute { +export class Attribute { loc; buffer; // TODO: maybe use undefined as default value? @@ -107,7 +108,7 @@ class Attribute { ctx.vertexAttribPointer(this.loc, this.size, this.type, this.normalized, this.stride, this.offset); } } -class Texture { +export class Texture { tex; constructor(tex) { this.tex = tex; @@ -141,4 +142,18 @@ async function loadTexture(path) { img.src = path; }); } -export { Texture, fullscreenCanvas, Graphics, Attribute }; +export class Camera { + position; + movement; + dt = 0; + constructor(position) { + this.position = position; + this.movement = new Vec4(0, 0, 0, 0); + } + update(dt) { + this.dt = dt; + let newPosition = this.movement.multScalarNew(this.dt); + this.position.x += (newPosition.x + newPosition.y) / 1.5; + this.position.y += newPosition.z + newPosition.w; + } +} diff --git a/src/js/graphics.ts b/src/js/graphics.ts index 4214bdd..b638221 100644 --- a/src/js/graphics.ts +++ b/src/js/graphics.ts @@ -1,4 +1,6 @@ -function fullscreenCanvas(gfx: Graphics, id: string) { +import {Vec3, Vec4} from "./common.js"; + +export function fullscreenCanvas(gfx: Graphics, id: string) { const canvas = document.getElementById(id) as HTMLCanvasElement; canvas.width = window.innerWidth; canvas.height = window.innerHeight; @@ -49,7 +51,7 @@ function createProgram(ctx: WebGL2RenderingContext, vertexShaderSource: string | return program; } -class Graphics { +export class Graphics { ctx: WebGL2RenderingContext; program: WebGLProgram; attribs: Map = new Map(); @@ -104,7 +106,7 @@ class Graphics { } } -class Attribute { +export class Attribute { loc: GLint; buffer: WebGLBuffer; @@ -142,7 +144,7 @@ class Attribute { } } -class Texture { +export class Texture { tex: WebGLTexture | null; constructor(tex: WebGLTexture) { @@ -184,4 +186,22 @@ async function loadTexture(path: string): Promise { }); } -export { Texture, fullscreenCanvas, Graphics, Attribute } +export class Camera { + position: Vec3; + movement: Vec4; + dt: number = 0; + + constructor(position: Vec3) { + this.position = position; + this.movement = new Vec4(0, 0, 0, 0); + } + + update(dt: number) { + this.dt = dt; + + let newPosition = this.movement.multScalarNew(this.dt); + this.position.x += (newPosition.x + newPosition.y) / 1.5; + this.position.y += newPosition.z + newPosition.w; + } +} + diff --git a/src/js/input.js b/src/js/input.js new file mode 100644 index 0000000..646dbbf --- /dev/null +++ b/src/js/input.js @@ -0,0 +1,35 @@ +class KeyAction { + key; + keyup; + keydown; + data; + constructor(key, ku, kd, data) { + this.key = key; + this.keyup = ku; + this.keydown = kd; + this.data = data; + } +} +export class Input { + handlers = new Map(); + constructor() { + window.addEventListener("keyup", e => { + this.handlers.forEach(ka => { + if (ka.keyup !== null && ka.key == e.code) { + ka.keyup(ka.data); + } + }); + }); + window.addEventListener("keydown", e => { + this.handlers.forEach(ka => { + if (ka.keydown !== null && ka.key == e.code) { + ka.keydown(ka.data); + } + }); + }); + } + //TODO: add modifier key support + addKeyAction(key, modifiers, data, keydown, keyup) { + this.handlers.set(key, new KeyAction(key, keydown, keyup, data)); + } +} diff --git a/src/js/input.ts b/src/js/input.ts new file mode 100644 index 0000000..ee34396 --- /dev/null +++ b/src/js/input.ts @@ -0,0 +1,39 @@ +type Action = ((data: any) => void); + +class KeyAction { + key: string; + keyup: Action | null; + keydown: Action | null; + data: any; + constructor(key: string, ku: Action | null, kd: Action | null, data: any) { + this.key = key; + this.keyup = ku; + this.keydown = kd; + this.data = data; + } +} + +export class Input { + handlers: Map = new Map(); + constructor() { + window.addEventListener("keyup", e => { + this.handlers.forEach(ka => { + if (ka.keyup !== null && ka.key == e.code) { + ka.keyup(ka.data); + } + }); + }); + window.addEventListener("keydown", e => { + this.handlers.forEach(ka => { + if (ka.keydown !== null && ka.key == e.code) { + ka.keydown(ka.data); + } + }); + }); + } + + //TODO: add modifier key support + addKeyAction(key: string, modifiers: [string] | [], data: any, keydown: Action | null, keyup: Action | null) { + this.handlers.set(key, new KeyAction(key, keydown, keyup, data)); + } +} diff --git a/src/js/script.js b/src/js/script.js index 8a154ec..f5c1c71 100644 --- a/src/js/script.js +++ b/src/js/script.js @@ -1,7 +1,8 @@ import { initializeContext, Vec3, Mat4 } from "./common.js"; -import { Graphics, fullscreenCanvas, Texture } from "./graphics.js"; +import { Graphics, fullscreenCanvas, Texture, Camera } from "./graphics.js"; import * as drawing from "./draw.js"; import * as wasm from "./wasm.js"; +import { Input } from "./input.js"; const vertexShader = `#version 300 es in vec3 a_position; @@ -11,9 +12,16 @@ const vertexShader = `#version 300 es out vec4 v_color; uniform mat4 u_matrix; uniform bool u_isTex; + + mat4 Iso = mat4( + 1, -1, 0, 0, + 1, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ); void main() { - vec4 transformed = u_matrix * vec4(a_position.xyz, 1.0); + vec4 transformed = u_matrix * Iso * vec4(a_position.xyz, 1.0); gl_Position = transformed; @@ -43,8 +51,9 @@ const fragmentShader = `#version 300 es } } `; -function draw(gfx, angle, tex) { +function draw(gfx, camera, dt, tex) { gfx.clear(0, 0, 0, 0); + camera.update(dt); let right = gfx.ctx.canvas.width; let left = 0; let top = gfx.ctx.canvas.height; @@ -52,8 +61,8 @@ function draw(gfx, angle, tex) { let near = -100; let far = 100; let mo = Mat4.orthographic(left, right, bottom, top, near, far); - let mi = Mat4.isometric(); - let m = mi.multNew(mo); + let mt = Mat4.translate(camera.position); + let m = mo.multNew(mt); //m = m.multNew(Mat4.rotation_x(angle)); //m = m.multNew(Mat4.rotation_y(angle)); //m = m.multNew(Mat4.rotation_z(angle)); @@ -65,10 +74,32 @@ function draw(gfx, angle, tex) { if ((i + j) % 2) drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [1, 1, 1, 1]); else - drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [0, 0, 0, 1]); + drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, tex); } } } +function addDefaultKeybinds(input, camera) { + input.addKeyAction("KeyA", [], camera, (c) => { + c.movement.x = 0; + }, (c) => { + c.movement.x = 1; + }); + input.addKeyAction("KeyD", [], camera, c => { + c.movement.y = 0; + }, (c) => { + c.movement.y = -1; + }); + input.addKeyAction("KeyW", [], camera, c => { + c.movement.z = 0; + }, (c) => { + c.movement.z = -1; + }); + input.addKeyAction("KeyS", [], camera, c => { + c.movement.w = 0; + }, (c) => { + c.movement.w = 1; + }); +} (async () => { const canvasId = "game"; const ctx = initializeContext(canvasId); @@ -85,19 +116,21 @@ function draw(gfx, angle, tex) { gfx.createUniform("u_matrix"); gfx.createUniform("u_isTex"); let city = await Texture.load(ctx, "../../assets/genetica/rt/City Night.jpg"); - let angle = 0; + let wall = await Texture.load(ctx, "../../assets/wall.png"); + let camera = new Camera(new Vec3(0, 0, 0)); let prevTimestamp = 0; const frame = (timestamp) => { const deltaTime = (timestamp - prevTimestamp) / 1000; prevTimestamp = timestamp; fullscreenCanvas(gfx, "game"); - draw(gfx, angle, city); - angle += Math.PI * deltaTime * 0.5; + draw(gfx, camera, deltaTime, wall); window.requestAnimationFrame(frame); }; window.requestAnimationFrame((timestamp) => { prevTimestamp = timestamp; window.requestAnimationFrame(frame); }); + let input = new Input(); + addDefaultKeybinds(input, camera); let wasmgl = new wasm.WASMGL(await wasm.loadWasmModule("./src/wasm/module.wasm")); })(); diff --git a/src/js/script.ts b/src/js/script.ts index ac2e9e4..b2a0c8e 100644 --- a/src/js/script.ts +++ b/src/js/script.ts @@ -1,7 +1,8 @@ -import { initializeContext, Vec2, Vec3, Mat4 } from "./common.js"; -import { Graphics, fullscreenCanvas, Texture } from "./graphics.js"; +import { initializeContext, Vec3, Mat4 } from "./common.js"; +import { Graphics, fullscreenCanvas, Texture, Camera } from "./graphics.js"; import * as drawing from "./draw.js"; import * as wasm from "./wasm.js"; +import { Input } from "./input.js"; const vertexShader = `#version 300 es @@ -13,9 +14,16 @@ const vertexShader = out vec4 v_color; uniform mat4 u_matrix; uniform bool u_isTex; + + mat4 Iso = mat4( + 1, -1, 0, 0, + 1, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ); void main() { - vec4 transformed = u_matrix * vec4(a_position.xyz, 1.0); + vec4 transformed = u_matrix * Iso * vec4(a_position.xyz, 1.0); gl_Position = transformed; @@ -50,8 +58,10 @@ const fragmentShader = -function draw(gfx: Graphics, angle: number, tex: Texture) { +function draw(gfx: Graphics, camera: Camera, dt: number, tex: Texture) { gfx.clear(0, 0, 0, 0); + camera.update(dt); + let right = gfx.ctx.canvas.width; let left = 0; @@ -61,8 +71,9 @@ function draw(gfx: Graphics, angle: number, tex: Texture) { let far = 100; let mo = Mat4.orthographic(left, right, bottom, top, near, far); - let mi = Mat4.isometric(); - let m = mi.multNew(mo); + let mt = Mat4.translate(camera.position); + + let m = mo.multNew(mt); //m = m.multNew(Mat4.rotation_x(angle)); //m = m.multNew(Mat4.rotation_y(angle)); //m = m.multNew(Mat4.rotation_z(angle)); @@ -81,11 +92,42 @@ function draw(gfx: Graphics, angle: number, tex: Texture) { if ((i + j) % 2) drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [1, 1, 1, 1]); else - drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [0, 0, 0, 1]); + drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, tex); } } } +function addDefaultKeybinds(input: Input, camera: Camera) { + input.addKeyAction("KeyA", [], camera, + (c) => { + c.movement.x = 0; + }, + (c) => { + c.movement.x = 1; + }); + + input.addKeyAction("KeyD", [], camera, c => { + c.movement.y = 0; + }, + (c) => { + c.movement.y = -1; + }); + + input.addKeyAction("KeyW", [], camera, c => { + c.movement.z = 0; + }, + (c) => { + c.movement.z = -1; + }); + + input.addKeyAction("KeyS", [], camera, c => { + c.movement.w = 0; + }, + (c) => { + c.movement.w = 1; + }); +} + (async () => { const canvasId = "game"; const ctx = initializeContext(canvasId); @@ -107,16 +149,17 @@ function draw(gfx: Graphics, angle: number, tex: Texture) { gfx.createUniform("u_isTex"); let city = await Texture.load(ctx, "../../assets/genetica/rt/City Night.jpg"); + let wall = await Texture.load(ctx, "../../assets/wall.png"); + + let camera = new Camera(new Vec3(0, 0, 0)); - let angle = 0; let prevTimestamp = 0; const frame = (timestamp: number) => { const deltaTime = (timestamp - prevTimestamp)/1000; prevTimestamp = timestamp; fullscreenCanvas(gfx, "game"); - draw(gfx, angle, city); - angle += Math.PI * deltaTime * 0.5; + draw(gfx, camera, deltaTime, wall); window.requestAnimationFrame(frame); } @@ -126,5 +169,8 @@ function draw(gfx: Graphics, angle: number, tex: Texture) { window.requestAnimationFrame(frame); }); + let input = new Input(); + addDefaultKeybinds(input, camera); + let wasmgl: wasm.WASMGL = new wasm.WASMGL(await wasm.loadWasmModule("./src/wasm/module.wasm")); })();