From d5be7270409a639a3a0568e46692ff293db02dfa Mon Sep 17 00:00:00 2001 From: schmelczerandras Date: Sat, 18 Jul 2020 22:02:09 +0200 Subject: [PATCH] Add input handling --- README.md | 4 ++ frontend/.vscode/settings.json | 5 ++ frontend/package.json | 1 + frontend/src/index.html | 31 +++++----- frontend/src/index.ts | 4 +- .../src/scripting/helper/keyboard-listener.ts | 21 ------- frontend/src/scripting/main.ts | 20 ------- frontend/src/scripting/shared/vec2.ts | 4 -- frontend/src/scripting/shared/world-map.ts | 18 ------ .../scripts/commands/command-broadcaster.ts | 13 +++++ .../src/scripts/commands/command-generator.ts | 14 +++++ .../src/scripts/commands/command-receiver.ts | 5 ++ frontend/src/scripts/commands/command.ts | 3 + .../src/scripts/commands/types/key-down.ts | 7 +++ frontend/src/scripts/commands/types/key-up.ts | 7 +++ .../scripts/commands/types/primary-action.ts | 8 +++ .../commands/types/secondary-action.ts | 8 +++ frontend/src/scripts/commands/types/swipe.ts | 8 +++ .../drawing/pipeline.ts | 0 .../drawing/renderer.ts | 43 ++++---------- frontend/src/scripts/game-logic/game-logic.ts | 54 ++++++++++++++++++ .../{scripting => scripts}/helper/timing.ts | 0 .../src/scripts/identity/identity-manager.ts | 4 ++ .../src/scripts/input/keyboard-listener.ts | 19 +++++++ frontend/src/scripts/input/mouse-listener.ts | 56 +++++++++++++++++++ frontend/src/scripts/input/touch-listener.ts | 42 ++++++++++++++ frontend/src/scripts/main.ts | 48 ++++++++++++++++ .../shared => scripts/math}/line.ts | 0 frontend/src/scripts/math/vec2.ts | 27 +++++++++ frontend/src/scripts/objects/game-object.ts | 7 +++ .../src/scripts/objects/object-container.ts | 8 +++ frontend/src/scripts/objects/types/camera.ts | 3 + .../src/scripts/transport/serializable.ts | 9 +++ frontend/src/shaders/dist.frag | 19 +++++++ frontend/src/{styling => styles}/main.scss | 0 frontend/webpack.config.js | 10 +++- 36 files changed, 417 insertions(+), 113 deletions(-) create mode 100644 frontend/.vscode/settings.json delete mode 100644 frontend/src/scripting/helper/keyboard-listener.ts delete mode 100644 frontend/src/scripting/main.ts delete mode 100644 frontend/src/scripting/shared/vec2.ts delete mode 100644 frontend/src/scripting/shared/world-map.ts create mode 100644 frontend/src/scripts/commands/command-broadcaster.ts create mode 100644 frontend/src/scripts/commands/command-generator.ts create mode 100644 frontend/src/scripts/commands/command-receiver.ts create mode 100644 frontend/src/scripts/commands/command.ts create mode 100644 frontend/src/scripts/commands/types/key-down.ts create mode 100644 frontend/src/scripts/commands/types/key-up.ts create mode 100644 frontend/src/scripts/commands/types/primary-action.ts create mode 100644 frontend/src/scripts/commands/types/secondary-action.ts create mode 100644 frontend/src/scripts/commands/types/swipe.ts rename frontend/src/{scripting => scripts}/drawing/pipeline.ts (100%) rename frontend/src/{scripting => scripts}/drawing/renderer.ts (62%) create mode 100644 frontend/src/scripts/game-logic/game-logic.ts rename frontend/src/{scripting => scripts}/helper/timing.ts (100%) create mode 100644 frontend/src/scripts/identity/identity-manager.ts create mode 100644 frontend/src/scripts/input/keyboard-listener.ts create mode 100644 frontend/src/scripts/input/mouse-listener.ts create mode 100644 frontend/src/scripts/input/touch-listener.ts create mode 100644 frontend/src/scripts/main.ts rename frontend/src/{scripting/shared => scripts/math}/line.ts (100%) create mode 100644 frontend/src/scripts/math/vec2.ts create mode 100644 frontend/src/scripts/objects/game-object.ts create mode 100644 frontend/src/scripts/objects/object-container.ts create mode 100644 frontend/src/scripts/objects/types/camera.ts create mode 100644 frontend/src/scripts/transport/serializable.ts rename frontend/src/{styling => styles}/main.scss (100%) diff --git a/README.md b/README.md index b4b1b2b..0ef7251 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,7 @@ A good-looking 2D adventure. - lightweight object storage - 502 error page for ingress - vs code glsl formatter +- docker engine dashboard? +- local dev env +- vs code config +- prettier script diff --git a/frontend/.vscode/settings.json b/frontend/.vscode/settings.json new file mode 100644 index 0000000..c178efe --- /dev/null +++ b/frontend/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "typescript.tsdk": "node_modules\\typescript\\lib", + "editor.tabSize": 2, + "editor.formatOnSave": true +} diff --git a/frontend/package.json b/frontend/package.json index 7399b98..5a4e037 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -48,6 +48,7 @@ "ts-loader": "^8.0.1", "twgl.js": "^4.15.2", "typescript": "^3.8.3", + "uuid": "^8.2.0", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", "webpack-dev-server": "^3.10.3" diff --git a/frontend/src/index.html b/frontend/src/index.html index d96135b..1774dc2 100644 --- a/frontend/src/index.html +++ b/frontend/src/index.html @@ -1,20 +1,23 @@ - - + + - - + + - - + + - Test - - -
- - -
- + Test + + +
+ + +
+ diff --git a/frontend/src/index.ts b/frontend/src/index.ts index 0d23ac2..aadeadf 100644 --- a/frontend/src/index.ts +++ b/frontend/src/index.ts @@ -1,4 +1,4 @@ -import './styling/main.scss'; -import { main } from './scripting/main'; +import './styles/main.scss'; +import { main } from './scripts/main'; main(); diff --git a/frontend/src/scripting/helper/keyboard-listener.ts b/frontend/src/scripting/helper/keyboard-listener.ts deleted file mode 100644 index 6c946ee..0000000 --- a/frontend/src/scripting/helper/keyboard-listener.ts +++ /dev/null @@ -1,21 +0,0 @@ -export class KeyboardListener { - private keysDown: Set = new Set(); - - constructor() { - document.addEventListener('keydown', (event) => { - this.keysDown.add(event.key); - }); - - document.addEventListener('keyup', (event) => { - this.keysDown.delete(event.key); - }); - } - - isKeyDown(key: string): boolean { - return ( - this.keysDown.has(key) || - this.keysDown.has(key.toLowerCase()) || - this.keysDown.has(key.toUpperCase()) - ); - } -} diff --git a/frontend/src/scripting/main.ts b/frontend/src/scripting/main.ts deleted file mode 100644 index 70cb939..0000000 --- a/frontend/src/scripting/main.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Renderer } from './drawing/renderer'; -import { KeyboardListener } from './helper/keyboard-listener'; - -import passthroughVertexShader from '../shaders/passthrough.vert'; -import distanceFragmentShader from '../shaders/dist.frag'; - -export const main = async () => { - try { - const canvas: HTMLCanvasElement = document.querySelector('canvas#main'); - - const renderer = new Renderer(canvas, [ - passthroughVertexShader, - distanceFragmentShader, - ]); - - renderer.start(); - } catch (e) { - console.error(e); - } -}; diff --git a/frontend/src/scripting/shared/vec2.ts b/frontend/src/scripting/shared/vec2.ts deleted file mode 100644 index 48ea69a..0000000 --- a/frontend/src/scripting/shared/vec2.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface Vec2 { - x: number; - y: number; -} diff --git a/frontend/src/scripting/shared/world-map.ts b/frontend/src/scripting/shared/world-map.ts deleted file mode 100644 index 9deccb4..0000000 --- a/frontend/src/scripting/shared/world-map.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Line } from './line'; - -export class WorldMap { - private lines: Array = []; - - constructor() { - const delta = 0.01; - for (let i = delta; i < 30; i += delta) { - const linePoints = { - a: { x: i - delta, y: Math.sin(i - delta) }, - b: { x: i, y: Math.sin(i) }, - }; - /*Vec2 tangent = lines[i].b - lines[i].a; - lines[i].normal = vec2(-lines[i].normal.x * tangent.y, lines[i].normal.x * tangent.x); - linePoints.normal = */ - } - } -} diff --git a/frontend/src/scripts/commands/command-broadcaster.ts b/frontend/src/scripts/commands/command-broadcaster.ts new file mode 100644 index 0000000..8703fcf --- /dev/null +++ b/frontend/src/scripts/commands/command-broadcaster.ts @@ -0,0 +1,13 @@ +import { CommandReceiver } from './command-receiver'; +import { CommandGenerator } from './command-generator'; + +export class CommandBroadcaster { + constructor( + commandGenerators: Array, + commandReceivers: Array + ) { + commandReceivers.forEach((r) => + commandGenerators.forEach((g) => g.subscribe(r)) + ); + } +} diff --git a/frontend/src/scripts/commands/command-generator.ts b/frontend/src/scripts/commands/command-generator.ts new file mode 100644 index 0000000..01fb65b --- /dev/null +++ b/frontend/src/scripts/commands/command-generator.ts @@ -0,0 +1,14 @@ +import { CommandReceiver } from './command-receiver'; +import { Command } from './command'; + +export class CommandGenerator { + private subscribers: Array = []; + + public subscribe(subscriber: CommandReceiver): void { + this.subscribers.push(subscriber); + } + + protected sendCommand(command: Command): void { + this.subscribers.forEach((s) => s.sendCommand(command)); + } +} diff --git a/frontend/src/scripts/commands/command-receiver.ts b/frontend/src/scripts/commands/command-receiver.ts new file mode 100644 index 0000000..bf6e119 --- /dev/null +++ b/frontend/src/scripts/commands/command-receiver.ts @@ -0,0 +1,5 @@ +import { Command } from './command'; + +export interface CommandReceiver { + sendCommand(command: Command): void; +} diff --git a/frontend/src/scripts/commands/command.ts b/frontend/src/scripts/commands/command.ts new file mode 100644 index 0000000..f53a31a --- /dev/null +++ b/frontend/src/scripts/commands/command.ts @@ -0,0 +1,3 @@ +import { Typed } from '../transport/serializable'; + +export abstract class Command extends Typed {} diff --git a/frontend/src/scripts/commands/types/key-down.ts b/frontend/src/scripts/commands/types/key-down.ts new file mode 100644 index 0000000..6adcc0b --- /dev/null +++ b/frontend/src/scripts/commands/types/key-down.ts @@ -0,0 +1,7 @@ +import { Command } from '../command'; + +export class KeyDownCommand extends Command { + public constructor(public readonly key: string) { + super(); + } +} diff --git a/frontend/src/scripts/commands/types/key-up.ts b/frontend/src/scripts/commands/types/key-up.ts new file mode 100644 index 0000000..b70f7f7 --- /dev/null +++ b/frontend/src/scripts/commands/types/key-up.ts @@ -0,0 +1,7 @@ +import { Command } from '../command'; + +export class KeyUpCommand extends Command { + public constructor(public readonly key: string) { + super(); + } +} diff --git a/frontend/src/scripts/commands/types/primary-action.ts b/frontend/src/scripts/commands/types/primary-action.ts new file mode 100644 index 0000000..6a9d443 --- /dev/null +++ b/frontend/src/scripts/commands/types/primary-action.ts @@ -0,0 +1,8 @@ +import { Command } from '../command'; +import { Vec2 } from '../../math/vec2'; + +export class PrimaryActionCommand extends Command { + public constructor(public readonly position: Vec2) { + super(); + } +} diff --git a/frontend/src/scripts/commands/types/secondary-action.ts b/frontend/src/scripts/commands/types/secondary-action.ts new file mode 100644 index 0000000..369701c --- /dev/null +++ b/frontend/src/scripts/commands/types/secondary-action.ts @@ -0,0 +1,8 @@ +import { Command } from '../command'; +import { Vec2 } from '../../math/vec2'; + +export class SecondaryActionCommand extends Command { + public constructor(public readonly position: Vec2) { + super(); + } +} diff --git a/frontend/src/scripts/commands/types/swipe.ts b/frontend/src/scripts/commands/types/swipe.ts new file mode 100644 index 0000000..929129e --- /dev/null +++ b/frontend/src/scripts/commands/types/swipe.ts @@ -0,0 +1,8 @@ +import { Command } from '../command'; +import { Vec2 } from '../../math/vec2'; + +export class SwipeCommand extends Command { + public constructor(public readonly delta: Vec2) { + super(); + } +} diff --git a/frontend/src/scripting/drawing/pipeline.ts b/frontend/src/scripts/drawing/pipeline.ts similarity index 100% rename from frontend/src/scripting/drawing/pipeline.ts rename to frontend/src/scripts/drawing/pipeline.ts diff --git a/frontend/src/scripting/drawing/renderer.ts b/frontend/src/scripts/drawing/renderer.ts similarity index 62% rename from frontend/src/scripting/drawing/renderer.ts rename to frontend/src/scripts/drawing/renderer.ts index b507900..11b27f7 100644 --- a/frontend/src/scripting/drawing/renderer.ts +++ b/frontend/src/scripts/drawing/renderer.ts @@ -1,17 +1,20 @@ -import * as twgl from 'twgl.js'; +const twgl = require('twgl.js'); + import { TimeIt } from '../helper/timing'; -import { KeyboardListener } from '../helper/keyboard-listener'; -import { Vec2 } from '../shared/vec2'; +import { Vec2 } from '../math/vec2'; +import { ObjectContainer } from '../objects/object-container'; export class Renderer { private gl: WebGL2RenderingContext; private programInfo: any; private bufferInfo: any; private vao: any; - private cameraPosition: Vec2 = { x: 0, y: 0 }; - private keys: KeyboardListener = new KeyboardListener(); - constructor(private canvas: HTMLCanvasElement, shaderSources: Array) { + constructor( + private canvas: HTMLCanvasElement, + private objects: ObjectContainer, + shaderSources: Array + ) { twgl.setDefaults({ attribPrefix: 'a_' }); this.gl = this.canvas.getContext('webgl2'); @@ -39,13 +42,7 @@ export class Renderer { ); } - start() { - requestAnimationFrame(this.timedRender); - } - - private timedRender = TimeIt(this.render.bind(this), 240); - - private render(time: number) { + public render(time: number) { const gl = this.gl; twgl.resizeCanvasToDisplaySize(this.canvas); @@ -53,24 +50,8 @@ export class Renderer { gl.clear(gl.COLOR_BUFFER_BIT); - if (this.keys.isKeyDown('w')) { - this.cameraPosition.y += 10; - } - - if (this.keys.isKeyDown('s')) { - this.cameraPosition.y -= 10; - } - - if (this.keys.isKeyDown('a')) { - this.cameraPosition.x -= 10; - } - - if (this.keys.isKeyDown('d')) { - this.cameraPosition.x += 10; - } - const uniforms = { - cameraPosition: [this.cameraPosition.x, this.cameraPosition.y], + cameraPosition: this.objects.camera.position.list, viewBoxSize: [this.gl.canvas.width, this.gl.canvas.height], resolution: [this.gl.canvas.width, this.gl.canvas.height], }; @@ -81,7 +62,5 @@ export class Renderer { twgl.setUniforms(this.programInfo, uniforms); twgl.drawBufferInfo(this.gl, this.bufferInfo); - - requestAnimationFrame(this.timedRender); } } diff --git a/frontend/src/scripts/game-logic/game-logic.ts b/frontend/src/scripts/game-logic/game-logic.ts new file mode 100644 index 0000000..60cc378 --- /dev/null +++ b/frontend/src/scripts/game-logic/game-logic.ts @@ -0,0 +1,54 @@ +import { Command } from '../commands/command'; +import { CommandReceiver } from '../commands/command-receiver'; +import { ObjectContainer } from '../objects/object-container'; +import { KeyDownCommand } from '../commands/types/key-down'; +import { KeyUpCommand } from '../commands/types/key-up'; +import { SwipeCommand } from '../commands/types/swipe'; + +export class GameLogic implements CommandReceiver { + private commandBuffer: Array = []; + private keysDown: Set = new Set(); + + constructor(private objects: ObjectContainer) {} + + public step(time: DOMHighResTimeStamp) { + while (this.commandBuffer.length > 0) { + const command = this.commandBuffer.pop(); + console.log(command); + + if (command instanceof KeyDownCommand) { + this.keysDown.add(command.key); + } + + if (command instanceof KeyUpCommand) { + this.keysDown.delete(command.key); + } + + if (command instanceof SwipeCommand) { + this.objects.camera.position = this.objects.camera.position.subtract( + command.delta.scale(200) + ); + } + } + + if (this.keysDown.has('w')) { + this.objects.camera.position.y += 10; + } + + if (this.keysDown.has('s')) { + this.objects.camera.position.y -= 10; + } + + if (this.keysDown.has('a')) { + this.objects.camera.position.x -= 10; + } + + if (this.keysDown.has('d')) { + this.objects.camera.position.x += 10; + } + } + + public sendCommand(command: Command) { + this.commandBuffer.push(command); + } +} diff --git a/frontend/src/scripting/helper/timing.ts b/frontend/src/scripts/helper/timing.ts similarity index 100% rename from frontend/src/scripting/helper/timing.ts rename to frontend/src/scripts/helper/timing.ts diff --git a/frontend/src/scripts/identity/identity-manager.ts b/frontend/src/scripts/identity/identity-manager.ts new file mode 100644 index 0000000..49b5ad8 --- /dev/null +++ b/frontend/src/scripts/identity/identity-manager.ts @@ -0,0 +1,4 @@ +export class IdentityManager { + public static sourceId: string; + public static targetId: string; +} diff --git a/frontend/src/scripts/input/keyboard-listener.ts b/frontend/src/scripts/input/keyboard-listener.ts new file mode 100644 index 0000000..a94ed88 --- /dev/null +++ b/frontend/src/scripts/input/keyboard-listener.ts @@ -0,0 +1,19 @@ +import { CommandGenerator } from '../commands/command-generator'; +import { KeyDownCommand } from '../commands/types/key-down'; +import { KeyUpCommand } from '../commands/types/key-up'; + +export class KeyboardListener extends CommandGenerator { + constructor(target: Element = document.body) { + super(); + + target.addEventListener('keydown', (event: KeyboardEvent) => { + const key = event.key.toLowerCase(); + this.sendCommand(new KeyDownCommand(key)); + }); + + target.addEventListener('keyup', (event: KeyboardEvent) => { + const key = event.key.toLowerCase(); + this.sendCommand(new KeyUpCommand(key)); + }); + } +} diff --git a/frontend/src/scripts/input/mouse-listener.ts b/frontend/src/scripts/input/mouse-listener.ts new file mode 100644 index 0000000..e14ff81 --- /dev/null +++ b/frontend/src/scripts/input/mouse-listener.ts @@ -0,0 +1,56 @@ +import { CommandGenerator } from '../commands/command-generator'; +import { PrimaryActionCommand } from '../commands/types/primary-action'; +import { SecondaryActionCommand } from '../commands/types/secondary-action'; +import { Vec2 } from '../math/vec2'; +import { SwipeCommand } from '../commands/types/swipe'; + +export class MouseListener extends CommandGenerator { + private previousPosition: Vec2 = null; + private isMouseDown = false; + + constructor(private target: Element = document.body) { + super(); + + target.addEventListener('mousedown', (event: MouseEvent) => { + const position = this.positionFromEvent(event); + + this.previousPosition = position; + this.isMouseDown = true; + + if (event.button == 0) { + this.sendCommand(new PrimaryActionCommand(position)); + } + }); + + target.addEventListener('mousemove', (event: MouseEvent) => { + if (this.isMouseDown) { + const position = this.positionFromEvent(event); + this.sendCommand( + new SwipeCommand(this.previousPosition.subtract(position)) + ); + this.previousPosition = position; + } + }); + + target.addEventListener('mouseup', (event: MouseEvent) => { + this.isMouseDown = false; + }); + + target.addEventListener('mouseleave', (event: MouseEvent) => { + this.isMouseDown = false; + }); + + target.addEventListener('contextmenu', (event: MouseEvent) => { + event.preventDefault(); + const position = this.positionFromEvent(event); + this.sendCommand(new SecondaryActionCommand(position)); + }); + } + + private positionFromEvent(event: MouseEvent): Vec2 { + return new Vec2( + -event.clientX / this.target.clientWidth, + event.clientY / this.target.clientHeight + ); + } +} diff --git a/frontend/src/scripts/input/touch-listener.ts b/frontend/src/scripts/input/touch-listener.ts new file mode 100644 index 0000000..b441a7c --- /dev/null +++ b/frontend/src/scripts/input/touch-listener.ts @@ -0,0 +1,42 @@ +import { CommandGenerator } from '../commands/command-generator'; +import { PrimaryActionCommand } from '../commands/types/primary-action'; +import { SecondaryActionCommand } from '../commands/types/secondary-action'; +import { Vec2 } from '../math/vec2'; +import { SwipeCommand } from '../commands/types/swipe'; + +export class TouchListener extends CommandGenerator { + private previousPosition: Vec2 = null; + + constructor(private target: Element = document.body) { + super(); + + target.addEventListener('touchstart', (event: TouchEvent) => { + const touchCount = event.touches.length; + const position = this.positionFromEvent(event); + this.previousPosition = position; + + if (touchCount == 1) { + this.sendCommand(new PrimaryActionCommand(position)); + } else { + this.sendCommand(new SecondaryActionCommand(position)); + } + }); + + target.addEventListener('touchmove', (event: TouchEvent) => { + const position = this.positionFromEvent(event); + + this.sendCommand( + new SwipeCommand(position.subtract(this.previousPosition)) + ); + + this.previousPosition = position; + }); + } + + private positionFromEvent(event: TouchEvent): Vec2 { + return new Vec2( + event.touches[0].clientX / this.target.clientWidth, + -event.touches[0].clientY / this.target.clientHeight + ); + } +} diff --git a/frontend/src/scripts/main.ts b/frontend/src/scripts/main.ts new file mode 100644 index 0000000..5458188 --- /dev/null +++ b/frontend/src/scripts/main.ts @@ -0,0 +1,48 @@ +import { Renderer } from './drawing/renderer'; + +import passthroughVertexShader from '../shaders/passthrough.vert'; +import distanceFragmentShader from '../shaders/dist.frag'; +import { KeyboardListener } from './input/keyboard-listener'; +import { MouseListener } from './input/mouse-listener'; +import { TouchListener } from './input/touch-listener'; +import { CommandBroadcaster } from './commands/command-broadcaster'; +import { GameLogic } from './game-logic/game-logic'; +import { GameObject } from './objects/game-object'; +import { ObjectContainer } from './objects/object-container'; +import { Camera } from './objects/types/camera'; + +const startGameLoop = (gameLogic: GameLogic, renderer: Renderer) => { + const loop = (time: DOMHighResTimeStamp) => { + gameLogic.step(time); + renderer.render(time); + requestAnimationFrame(loop); + }; + requestAnimationFrame(loop); +}; + +export const main = async () => { + try { + const canvas: HTMLCanvasElement = document.querySelector('canvas#main'); + + const objects = new ObjectContainer(new Camera()); + + const gameLogic = new GameLogic(objects); + new CommandBroadcaster( + [ + new KeyboardListener(document.body), + new MouseListener(canvas), + new TouchListener(canvas), + ], + [gameLogic] + ); + + const renderer = new Renderer(canvas, objects, [ + passthroughVertexShader, + distanceFragmentShader, + ]); + + startGameLoop(gameLogic, renderer); + } catch (e) { + console.error(e); + } +}; diff --git a/frontend/src/scripting/shared/line.ts b/frontend/src/scripts/math/line.ts similarity index 100% rename from frontend/src/scripting/shared/line.ts rename to frontend/src/scripts/math/line.ts diff --git a/frontend/src/scripts/math/vec2.ts b/frontend/src/scripts/math/vec2.ts new file mode 100644 index 0000000..f47bd39 --- /dev/null +++ b/frontend/src/scripts/math/vec2.ts @@ -0,0 +1,27 @@ +import { Typed } from '../transport/serializable'; + +export class Vec2 extends Typed { + public constructor(public x: number = 0.0, public y: number = null) { + super(); + + if (this.y === null) { + this.y = this.x; + } + } + + public scale(scalar: number): Vec2 { + return new Vec2(this.x * scalar, this.y * scalar); + } + + public add(other: Vec2): Vec2 { + return new Vec2(this.x + other.x, this.y + other.y); + } + + public subtract(other: Vec2): Vec2 { + return new Vec2(this.x - other.x, this.y - other.y); + } + + public get list(): [number, number] { + return [this.x, this.y]; + } +} diff --git a/frontend/src/scripts/objects/game-object.ts b/frontend/src/scripts/objects/game-object.ts new file mode 100644 index 0000000..512e39f --- /dev/null +++ b/frontend/src/scripts/objects/game-object.ts @@ -0,0 +1,7 @@ +import { Typed } from '../transport/serializable'; +import { Vec2 } from '../math/vec2'; + +export class GameObject extends Typed { + public position = new Vec2(); + public boundingBoxSize = new Vec2(); +} diff --git a/frontend/src/scripts/objects/object-container.ts b/frontend/src/scripts/objects/object-container.ts new file mode 100644 index 0000000..31a3bc9 --- /dev/null +++ b/frontend/src/scripts/objects/object-container.ts @@ -0,0 +1,8 @@ +import { GameObject } from './game-object'; +import { Camera } from './types/camera'; + +export class ObjectContainer { + private objects: Array = []; + + constructor(public camera: Camera) {} +} diff --git a/frontend/src/scripts/objects/types/camera.ts b/frontend/src/scripts/objects/types/camera.ts new file mode 100644 index 0000000..bf612b2 --- /dev/null +++ b/frontend/src/scripts/objects/types/camera.ts @@ -0,0 +1,3 @@ +import { GameObject } from '../game-object'; + +export class Camera extends GameObject {} diff --git a/frontend/src/scripts/transport/serializable.ts b/frontend/src/scripts/transport/serializable.ts new file mode 100644 index 0000000..b1e03d8 --- /dev/null +++ b/frontend/src/scripts/transport/serializable.ts @@ -0,0 +1,9 @@ +export class Typed { + public get type(): string { + return this.constructor.name; + } + + public toJSON() { + return { type: this.type, ...this }; + } +} diff --git a/frontend/src/shaders/dist.frag b/frontend/src/shaders/dist.frag index 930ac7f..efc382b 100644 --- a/frontend/src/shaders/dist.frag +++ b/frontend/src/shaders/dist.frag @@ -41,6 +41,24 @@ float terrain(float x) { return result; } +vec2 random2(vec2 st){ + st = vec2( dot(st,vec2(127.1,311.7)), + dot(st,vec2(269.5,183.3)) ); + return -1.0 + 2.0*fract(sin(st)*43758.5453123); +} + +float noise(vec2 st) { + vec2 i = floor(st); + vec2 f = fract(st); + + vec2 u = f*f*(3.0-2.0*f); + + return mix( mix( dot( random2(i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ), + dot( random2(i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x), + mix( dot( random2(i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ), + dot( random2(i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y); +} + float lineDistance(in vec2 position, in Line line, out float h) { vec2 pa = position - line.a, ba = line.b - line.a; h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0); @@ -50,6 +68,7 @@ float lineDistance(in vec2 position, in Line line, out float h) { return length(delta) * side + terrain(length(ba * h)); } + Line endDummyLineFromLine(Line line) { return Line(line.b, line.b + rotate90deg(line.normal), line.normal, false); } diff --git a/frontend/src/styling/main.scss b/frontend/src/styles/main.scss similarity index 100% rename from frontend/src/styling/main.scss rename to frontend/src/styles/main.scss diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js index 2a159be..1724428 100644 --- a/frontend/webpack.config.js +++ b/frontend/webpack.config.js @@ -7,6 +7,7 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin'); const Sharp = require('responsive-loader/sharp'); const Sass = require('sass'); +const tsNameof = require('ts-nameof'); const isProduction = process.env.NODE_ENV === 'production'; @@ -73,7 +74,7 @@ module.exports = { { test: /\.(frag|vert)$/i, use: { - loader: 'raw-loader' + loader: 'raw-loader', }, }, { @@ -120,7 +121,12 @@ module.exports = { }, { test: /\.ts$/, - use: 'ts-loader', + use: { + loader: 'ts-loader', + options: { + getCustomTransformers: () => ({ before: [tsNameof] }), + }, + }, exclude: /node_modules/, }, ],