diff --git a/frontend/src/index.ts b/frontend/src/index.ts index ff2abea..ac666fe 100644 --- a/frontend/src/index.ts +++ b/frontend/src/index.ts @@ -1,11 +1,101 @@ -import { glMatrix } from 'gl-matrix'; +import { glMatrix, vec2 } from 'gl-matrix'; import { Game } from './scripts/game'; import { applyArrayPlugins } from './scripts/helper/array'; +import { Random } from './scripts/helper/random'; +import TunnelShape from './scripts/shapes/types/tunnel-shape'; import './styles/main.scss'; glMatrix.setMatrixArrayType(Array); applyArrayPlugins(); +const testSDF = () => { + Random.seed = 44; + + const objects: Array = [ + new TunnelShape(vec2.fromValues(20, 20), vec2.fromValues(40, 80), 10, 9), + new TunnelShape(vec2.fromValues(40, 80), vec2.fromValues(60, 20), 9, 15), + ]; + + const getPixelValue = (position: vec2) => { + /*const k = 0.15; + let res = Math.pow(2, -k * (vec2.distance(position, vec2.fromValues(20, 20)) - 20)); + res += Math.pow(2, -k * (vec2.distance(position, vec2.fromValues(40, 80)) - 30)); + res += Math.pow(2, -k * (vec2.distance(position, vec2.fromValues(60, 20)) - 20)); + res = -Math.log2(res) / k; + return -res; + + */ + let min = 1000; + for (const t of objects) { + min = Math.min(min, t.distance(position)); + } + if (min < 0) { + // min = Math.min(min, vec2.distance(position, vec2.fromValues(40, 80 - 31.62)) - 31.62); + } + return -min; + }; + + const width = 80; + const height = 100; + + const canvas = document.createElement('canvas'); + document.body.appendChild(canvas); + // set desired size of transparent image + canvas.width = width; + canvas.height = height; + + const ctx = canvas.getContext('2d'); + + const imageData = ctx.createImageData(width, height); + + const zeroes = []; + for (let x = 0; x < width; x++) { + console.log(x); + for (let y = 0; y < height; y++) { + const position = vec2.fromValues(x, y); + const redIndex = y * (width * 4) + x * 4; + const dist = getPixelValue(position); + if (Math.abs(dist) < 1) { + const blueIndex = y * (width * 4) + x * 4 + 2; + zeroes.push(position); + imageData.data[blueIndex] = 255; + } + imageData.data[redIndex + 3] = 255; + } + } + + ctx.putImageData(imageData, 0, 0); + + console.log(zeroes); + const errors = []; + for (let x = 0; x < width; x++) { + console.log('verify ', x); + + for (let y = 0; y < height; y++) { + const position = vec2.fromValues(x, y); + const dist = getPixelValue(position); + + const nearestDist = + zeroes.find((z) => Math.abs(vec2.distance(z, position) - dist) < 0.5)?.length > 0; + if (nearestDist) { + const greenIndex = y * (width * 4) + x * 4 + 1; + imageData.data[greenIndex] = 255; + } else if (dist >= 0) { + const redIndex = y * (width * 4) + x * 4; + errors.push(dist); + imageData.data[redIndex] = 255; + } + } + } + + console.log(errors); + + ctx.putImageData(imageData, 0, 0); +}; + +// testSDF(); +// extract as new image (data-uri) + /* const tree = new BoundingBoxTree([ new BoundingBox(300, 550, 150, 550, 'A'), @@ -24,6 +114,7 @@ console.log(tree.findIntersecting(new BoundingBox(960, 1050, 50, 190, 'G'))); */ try { + Random.seed = 42; new Game(); } catch (e) { console.error(e); diff --git a/frontend/src/scripts/drawing/drawables/drawable-blob.ts b/frontend/src/scripts/drawing/drawables/drawable-blob.ts index 31d3d0e..7c1b5b0 100644 --- a/frontend/src/scripts/drawing/drawables/drawable-blob.ts +++ b/frontend/src/scripts/drawing/drawables/drawable-blob.ts @@ -17,7 +17,6 @@ export class DrawableBlob extends Blob implements IDrawable { if (!Object.prototype.hasOwnProperty.call(uniforms, uniformName)) { uniforms[uniformName] = []; } - uniforms[uniformName].push({ headCenter: vec2.transformMat2d(vec2.create(), this.head.center, transform), torsoCenter: vec2.transformMat2d(vec2.create(), this.torso.center, transform), @@ -27,6 +26,10 @@ export class DrawableBlob extends Blob implements IDrawable { this.rightFoot.center, transform ), + headRadius: this.headRadius * scale, + torsoRadius: this.torsoRadius * scale, + footRadius: this.footRadius * scale, + k: this.k * scale, }); } } diff --git a/frontend/src/scripts/drawing/drawables/lights/circle-light.ts b/frontend/src/scripts/drawing/drawables/lights/circle-light.ts index 0f1ecf2..c5e0885 100644 --- a/frontend/src/scripts/drawing/drawables/lights/circle-light.ts +++ b/frontend/src/scripts/drawing/drawables/lights/circle-light.ts @@ -8,12 +8,13 @@ export class CircleLight implements ILight { uniformName: 'circleLights', countMacroName: 'circleLightCount', shaderCombinationSteps: settings.shaderCombinations.circleLightSteps, - empty: new CircleLight(vec2.fromValues(0, 0), 0, vec3.fromValues(0, 0, 0), 0), + empty: new CircleLight(vec2.fromValues(0, 0), 0, 0, vec3.fromValues(0, 0, 0), 0), }; constructor( public center: vec2, public radius: number, + public traceRadius: number, public color: vec3, public lightness: number ) {} @@ -32,6 +33,7 @@ export class CircleLight implements ILight { uniforms[uniformName].push({ center: vec2.transformMat2d(vec2.create(), this.center, transform), radius: this.radius * scale, + traceRadius: this.traceRadius * scale, value: this.value, }); } diff --git a/frontend/src/scripts/drawing/rendering/webgl2-renderer.ts b/frontend/src/scripts/drawing/rendering/webgl2-renderer.ts index 7f61d3a..ef9a3a9 100644 --- a/frontend/src/scripts/drawing/rendering/webgl2-renderer.ts +++ b/frontend/src/scripts/drawing/rendering/webgl2-renderer.ts @@ -23,7 +23,7 @@ export class WebGl2Renderer implements IRenderer { private stopwatch?: WebGlStopwatch; private upscaleTransform = mat2d.create(); - private linearDownscale = 1; + private linearUpscale = 1; private viewBoxBottomLeft = vec2.create(); private viewBoxSize = vec2.create(); @@ -95,10 +95,10 @@ export class WebGl2Renderer implements IRenderer { public finishFrame() { this.calculateMatrices(); - this.distancePass.render(this.uniforms, this.linearDownscale, this.upscaleTransform); + this.distancePass.render(this.uniforms, this.linearUpscale, this.upscaleTransform); this.lightingPass.render( this.uniforms, - this.linearDownscale, + this.linearUpscale, this.upscaleTransform, this.distanceFieldFrameBuffer.colorTexture ); @@ -161,7 +161,7 @@ export class WebGl2Renderer implements IRenderer { } public setViewArea(viewArea: BoundingBoxBase) { - const targetRange = 2 ** 7; + const targetRange = 2; this.viewBoxSize = viewArea.size; this.viewBoxBottomLeft = vec2.add( @@ -170,16 +170,16 @@ export class WebGl2Renderer implements IRenderer { vec2.fromValues(0, -viewArea.size.y) ); - this.linearDownscale = targetRange / Math.max(this.viewBoxSize.x, this.viewBoxSize.y); + this.linearUpscale = targetRange / Math.max(this.viewBoxSize.x, this.viewBoxSize.y); this.viewAreaScale = vec2.fromValues( - (this.viewBoxSize.x * this.linearDownscale) / 2, - (this.viewBoxSize.y * this.linearDownscale) / 2 + (this.viewBoxSize.x * this.linearUpscale) / 2, + (this.viewBoxSize.y * this.linearUpscale) / 2 ); mat2d.fromScaling( this.upscaleTransform, - vec2.fromValues(this.linearDownscale, this.linearDownscale) + vec2.fromValues(this.linearUpscale, this.linearUpscale) ); const translate = vec2.scale(vec2.create(), this.viewBoxBottomLeft, -1); diff --git a/frontend/src/scripts/drawing/settings.ts b/frontend/src/scripts/drawing/settings.ts index f9d7ef4..9ddc82d 100644 --- a/frontend/src/scripts/drawing/settings.ts +++ b/frontend/src/scripts/drawing/settings.ts @@ -8,24 +8,20 @@ export const settings = { [0.2, 0.1], [0.6, 0.1], [1, 1], - /* [1.25, 0.75], + [1.25, 0.75], [1.5, 1], [1.75, 1.25], - [1.75, 1.75], - [2, 2], */ + //[1.75, 1.75], + //[2, 2], ], startingTargetIndex: 2, scalingOptions: { additiveIncrease: 0.2, - multiplicativeDecrease: 1.15, + multiplicativeDecrease: 1.05, }, }, tileMultiplier: 8, - shaderMacros: { - headRadius: 0.05, - torsoRadius: 0.08, - footRadius: 0.02, - }, + shaderMacros: {}, shaderCombinations: { lineSteps: [0, 1, 2, 4, 8, 16, 128], blobSteps: [0, 1, 2, 8], diff --git a/frontend/src/scripts/drawing/shaders/cave-distance-fs.glsl b/frontend/src/scripts/drawing/shaders/cave-distance-fs.glsl index 174819d..eeef5f3 100644 --- a/frontend/src/scripts/drawing/shaders/cave-distance-fs.glsl +++ b/frontend/src/scripts/drawing/shaders/cave-distance-fs.glsl @@ -5,21 +5,23 @@ precision mediump float; #define LINE_COUNT {lineCount} #define BLOB_COUNT {blobCount} -uniform float maxMinDistance; +uniform float maxMinDistance; + +in vec2 position; + #if LINE_COUNT > 0 - uniform struct Line { + uniform struct { vec2 from; vec2 toFromDelta; float fromRadius; float toRadius; }[LINE_COUNT] lines; - void lineMinDistance(vec2 worldCoordinates, inout float minDistance) { - minDistance = maxMinDistance; - + void lineMinDistance(inout float minDistance, inout float color) { + float myMinDistance = 10.0; for (int i = 0; i < LINE_COUNT; i++) { - vec2 targetFromDelta = worldCoordinates - lines[i].from; + vec2 targetFromDelta = position - lines[i].from; vec2 toFromDelta = lines[i].toFromDelta; float h = clamp( @@ -27,61 +29,64 @@ uniform float maxMinDistance; 0.0, 1.0 ); - float lineDistance = ( - distance(targetFromDelta, toFromDelta * h) - - mix(lines[i].fromRadius, lines[i].toRadius, h) + float lineDistance = -mix( + lines[i].fromRadius, lines[i].toRadius, h + ) + distance( + targetFromDelta, toFromDelta * h ); - minDistance = min(minDistance, lineDistance); + color = mix(1.0, color, step(0.0, lineDistance)); + myMinDistance = min(myMinDistance, lineDistance); } - minDistance *= -1.0; + minDistance = -myMinDistance; } #endif #if BLOB_COUNT > 0 - #define headRadius {headRadius} - #define torsoRadius {torsoRadius} - #define footRadius {footRadius} - - uniform struct Blob { + uniform struct { vec2 headCenter; vec2 torsoCenter; vec2 leftFootCenter; vec2 rightFootCenter; + float headRadius; + float torsoRadius; + float footRadius; + float k; }[BLOB_COUNT] blobs; - float circleMinDistance(vec2 worldCoordinates, vec2 circleCenter, float radius) { - return distance(worldCoordinates, circleCenter) - radius; + float circleMinDistance(vec2 circleCenter, float radius) { + return distance(position, circleCenter) - radius; } - void blobMinDistance(vec2 worldCoordinates, inout float minDistance) { - float k = 1.0; - + void blobMinDistance(inout float minDistance, inout float color) { for (int i = 0; i < BLOB_COUNT; i++) { - float res = exp2(-k * circleMinDistance(worldCoordinates, blobs[i].headCenter, headRadius)); - res += exp2(-k * circleMinDistance(worldCoordinates, blobs[i].torsoCenter, torsoRadius)); - res += exp2(-k * circleMinDistance(worldCoordinates, blobs[i].leftFootCenter, footRadius)); - res += exp2(-k * circleMinDistance(worldCoordinates, blobs[i].rightFootCenter, footRadius)); + float res = exp2(-blobs[i].k * circleMinDistance(blobs[i].headCenter, blobs[i].headRadius)); + res += exp2(-blobs[i].k * circleMinDistance(blobs[i].torsoCenter, blobs[i].torsoRadius)); + res += exp2(-blobs[i].k * circleMinDistance(blobs[i].leftFootCenter, blobs[i].footRadius)); + res += exp2(-blobs[i].k * circleMinDistance(blobs[i].rightFootCenter, blobs[i].footRadius)); + res = -log2(res) / blobs[i].k; - minDistance = min(minDistance, -log2(res) / k); + color = mix(2.0, color, step(0.0, res)); + + minDistance = min(minDistance, res); } } #endif -in vec2 position; out vec2 fragmentColor; void main() { - float minDistance = -maxMinDistance; + float minDistance = -10.0; + float color = 0.0; #if LINE_COUNT > 0 - lineMinDistance(position, minDistance); + lineMinDistance(minDistance, color); #endif #if BLOB_COUNT > 0 - //blobMinDistance(position, minDistance); + blobMinDistance(minDistance, color); #endif - fragmentColor = vec2(minDistance, 0.0); + fragmentColor = vec2(minDistance, color); } diff --git a/frontend/src/scripts/drawing/shaders/lights-shading-fs.glsl b/frontend/src/scripts/drawing/shaders/lights-shading-fs.glsl index 709b536..0c9c218 100644 --- a/frontend/src/scripts/drawing/shaders/lights-shading-fs.glsl +++ b/frontend/src/scripts/drawing/shaders/lights-shading-fs.glsl @@ -3,17 +3,21 @@ precision mediump float; #define INFINITY 1000.0 -#define LIGHT_DROP 50.0 -#define AMBIENT_LIGHT vec3(0.15) +#define LIGHT_DROP 0.25 +#define AMBIENT_LIGHT vec3(0.3) #define CIRCLE_LIGHT_COUNT {circleLightCount} #define POINT_LIGHT_COUNT {pointLightCount} +#define SOFT_SHADOWS_ENABLED 1 +#define HARD_SHADOWS_QUALITY 1.5 +#define SOFT_SHADOWS_QUALITY 2.0 + uniform sampler2D distanceTexture; vec3[4] colors = vec3[4]( - vec3(0.5), - vec3(1.0, 0.0, 0.0), + vec3(0.2), + vec3(1.0, 1.0, 1.0), vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0) ); @@ -21,6 +25,7 @@ vec3[4] colors = vec3[4]( float getDistance(in vec2 target, out vec3 color) { vec4 values = texture(distanceTexture, target); color = colors[int(values[1])]; + return values[0]; } @@ -29,9 +34,10 @@ float getDistance(in vec2 target) { } #if CIRCLE_LIGHT_COUNT > 0 - uniform struct CircleLight { + uniform struct { vec2 center; float radius; + float traceRadius; vec3 value; }[CIRCLE_LIGHT_COUNT] circleLights; @@ -39,7 +45,7 @@ float getDistance(in vec2 target) { #endif #if POINT_LIGHT_COUNT > 0 - uniform struct PointLight { + uniform struct { vec2 center; float radius; vec3 value; @@ -61,13 +67,11 @@ void main() { #if CIRCLE_LIGHT_COUNT > 0 for (int i = 0; i < CIRCLE_LIGHT_COUNT; i++) { - float lightCenterDistance = distance( - circleLights[i].center, - position - ); + float lightCenterDistance = distance(circleLights[i].center, position); float lightDistance = lightCenterDistance - circleLights[i].radius; + float traceDistance = lightCenterDistance - circleLights[i].traceRadius; - if (lightDistance < 0.0) { + if (traceDistance < 0.0) { lighting = vec3(1.0, 1.0, 0.0); } @@ -75,21 +79,37 @@ void main() { lightDistance / LIGHT_DROP + 1.0, 2.0 ); - float q = INFINITY; - float rayLength = startingDistance; - vec2 direction = normalize(circleLightDirections[i]) / viewAreaScale / 2.0; - for (int j = 0; j < 48; j++) { - if (rayLength >= lightDistance) { - lighting += lightColorAtPosition * clamp( - q / circleLights[i].radius * lightCenterDistance, 0.0, 1.0 - ); - break; - } + #if SOFT_SHADOWS_ENABLED + float q = INFINITY; + float rayLength = startingDistance / SOFT_SHADOWS_QUALITY; + vec2 direction = normalize(circleLightDirections[i]) / viewAreaScale / 2.0; + for (int j = 0; j < 48 * int(ceil(SOFT_SHADOWS_QUALITY)); j++) { + if (rayLength >= traceDistance) { + lighting += lightColorAtPosition * clamp( + (q * 2.0) / circleLights[i].radius * lightCenterDistance, 0.0, 1.0 + ) * step(0.0, startingDistance); + break; + } - float minDistance = getDistance(uvCoordinates + direction * rayLength); - q = min(q, minDistance / rayLength); - rayLength += minDistance; - } + float minDistance = getDistance(uvCoordinates + direction * rayLength); + + q = min(q, minDistance / rayLength); + rayLength += minDistance / SOFT_SHADOWS_QUALITY; + } + #else + float rayLength = startingDistance / 2.0; + vec2 direction = normalize(circleLightDirections[i]) / viewAreaScale / 2.0; + for (int j = 0; j < 24 * int(ceil(HARD_SHADOWS_QUALITY)); j++) { + float minDistance = getDistance(uvCoordinates + direction * rayLength); + if (minDistance < 0.0) { + break; + } + rayLength += minDistance / HARD_SHADOWS_QUALITY; + } + if (rayLength >= traceDistance) { + lighting += lightColorAtPosition * step(0.0, startingDistance); + } + #endif } #endif @@ -123,9 +143,15 @@ void main() { }*/ #endif - fragmentColor = vec4(vec3(startingDistance / 100.0), 1.0); - fragmentColor = vec4( - colorAtPosition * lighting * step(0.0, startingDistance), - 1.0 - ); + + float d = startingDistance; + vec3 col = (d<0.0) ? vec3(0.6,0.8,1.0) : vec3(0.9,0.6,0.3); + col *= 1.0 - exp(-9.0*abs(d)); + col *= 1.0 + 0.2*cos(128.0*abs(d)); + col = mix( col, vec3(1.0), 1.0-smoothstep(0.0,0.015,abs(d)) ); + fragmentColor = vec4(col, 1.0); + fragmentColor = vec4(colorAtPosition * lighting, 1.0); + fragmentColor = vec4(mix(colorAtPosition * lighting, col, 0.2), 1.0); + + //fragmentColor = vec4(vec3(startingDistance), 1.0); } diff --git a/frontend/src/scripts/drawing/shaders/passthrough-shading-vs.glsl b/frontend/src/scripts/drawing/shaders/passthrough-shading-vs.glsl index 0c2c521..78ebdad 100644 --- a/frontend/src/scripts/drawing/shaders/passthrough-shading-vs.glsl +++ b/frontend/src/scripts/drawing/shaders/passthrough-shading-vs.glsl @@ -14,9 +14,10 @@ out vec2 uvCoordinates; uniform vec2 viewAreaScale; #if CIRCLE_LIGHT_COUNT > 0 - uniform struct CircleLight { + uniform struct { vec2 center; float radius; + float traceRadius; vec3 value; }[CIRCLE_LIGHT_COUNT] circleLights; @@ -24,7 +25,7 @@ uniform vec2 viewAreaScale; #endif #if POINT_LIGHT_COUNT > 0 - uniform struct PointLight { + uniform struct { vec2 center; float radius; vec3 value; diff --git a/frontend/src/scripts/game.ts b/frontend/src/scripts/game.ts index 20a26ed..43bf3ed 100644 --- a/frontend/src/scripts/game.ts +++ b/frontend/src/scripts/game.ts @@ -3,7 +3,6 @@ import { BeforeRenderCommand } from './drawing/commands/before-render'; import { RenderCommand } from './drawing/commands/render'; import { IRenderer } from './drawing/i-renderer'; import { WebGl2Renderer } from './drawing/rendering/webgl2-renderer'; -import { Random } from './helper/random'; import { timeIt } from './helper/timing'; import { IGame } from './i-game'; import { KeyboardListener } from './input/keyboard-listener'; @@ -23,27 +22,18 @@ import { BoundingBoxBase } from './shapes/bounding-box-base'; export class Game implements IGame { public readonly objects = new Objects(); - public readonly physics = new Physics(); - public readonly camera = new Camera(); - private previousTime?: DOMHighResTimeStamp = null; - private previousFpsValues: Array = []; - private infoText = new InfoText(); - private character: Character; - private renderer: IRenderer; constructor() { const canvas: HTMLCanvasElement = document.querySelector('canvas#main'); const overlay: HTMLElement = document.querySelector('#overlay'); - Random.seed = 42; - document.addEventListener('visibilitychange', this.handleVisibilityChange.bind(this)); new CommandBroadcaster( @@ -85,7 +75,9 @@ export class Game implements IGame { // this.physics.addDynamicBoundingBox(this.character.boundingBox); this.addObject(this.character); this.addObject(this.camera); - this.character.sendCommand(new TeleportToCommand(start.from)); + let pos: any = localStorage.getItem('character-position'); + pos = pos ? JSON.parse(pos) : start.from; + this.character.sendCommand(new TeleportToCommand(pos)); } private handleVisibilityChange() { @@ -124,6 +116,7 @@ export class Game implements IGame { this.infoText.sendCommand(new RenderCommand(this.renderer)); this.renderer.finishFrame(); + localStorage.setItem('character-position', JSON.stringify(this.character.position)); window.requestAnimationFrame(this.gameLoop.bind(this)); } diff --git a/frontend/src/scripts/objects/types/character.ts b/frontend/src/scripts/objects/types/character.ts index e87e508..4e9e508 100644 --- a/frontend/src/scripts/objects/types/character.ts +++ b/frontend/src/scripts/objects/types/character.ts @@ -1,28 +1,33 @@ import { vec2, vec3 } from 'gl-matrix'; import { RenderCommand } from '../../drawing/commands/render'; import { DrawableBlob } from '../../drawing/drawables/drawable-blob'; +import { CircleLight } from '../../drawing/drawables/lights/circle-light'; import { IGame } from '../../i-game'; import { KeyDownCommand } from '../../input/commands/key-down'; import { KeyUpCommand } from '../../input/commands/key-up'; import { SwipeCommand } from '../../input/commands/swipe'; -import { MoveToCommand } from '../../physics/commands/move-to'; import { StepCommand } from '../../physics/commands/step'; import { TeleportToCommand } from '../../physics/commands/teleport-to'; import { IShape } from '../../shapes/i-shape'; import { Blob } from '../../shapes/types/blob'; import { GameObject } from '../game-object'; -import { Lamp } from './lamp'; export class Character extends GameObject { private keysDown: Set = new Set(); - private light = new Lamp(vec2.create(), 40, vec3.fromValues(0.67, 0.0, 0.33), 2); + private light: CircleLight; private shape = new DrawableBlob(vec2.create()); - private static speed = 1.5; + private static speed = 4.5; constructor(private game: IGame) { super(); - game.addObject(this.light); + this.light = new CircleLight( + vec2.create(), + 40, + this.shape.boundingCircleRadius * 2, + vec3.fromValues(0.67, 0.0, 0.33), + 2 + ); this.addCommandExecutor(StepCommand, this.stepHandler.bind(this)); this.addCommandExecutor(RenderCommand, this.draw.bind(this)); @@ -40,7 +45,7 @@ export class Character extends GameObject { private draw(c: RenderCommand) { c.renderer.drawShape(this.shape); - this.light.sendCommand(c); + c.renderer.drawLight(this.light); } private tryMoving(delta: vec2, isFirstIteration = true) { @@ -102,15 +107,15 @@ export class Character extends GameObject { .filter((b) => b.shape) .map((b) => ({ shape: b.shape, - distance: b.shape.distance(shape.center) + shape.radius, + // TODO: fix this + distance: b.shape.distance(shape.center) + shape.radius - 20, })) .sort((e) => e.distance); } private setPosition(value: vec2) { this.shape.position = value; - vec2.add(value, value, vec2.fromValues(80, 0)); - this.light.sendCommand(new MoveToCommand(value)); + this.light.center = value; } public stepHandler(c: StepCommand) { diff --git a/frontend/src/scripts/objects/types/lamp.ts b/frontend/src/scripts/objects/types/lamp.ts index 80154d9..119f797 100644 --- a/frontend/src/scripts/objects/types/lamp.ts +++ b/frontend/src/scripts/objects/types/lamp.ts @@ -10,7 +10,7 @@ export class Lamp extends GameObject { constructor(center: vec2, radius: number, color: vec3, lightness: number) { super(); - this.light = new CircleLight(center, radius, color, lightness); + this.light = new CircleLight(center, radius, radius, color, lightness); this.addCommandExecutor(RenderCommand, this.draw.bind(this)); this.addCommandExecutor(MoveToCommand, this.moveTo.bind(this)); diff --git a/frontend/src/scripts/objects/world/create-dungeon.ts b/frontend/src/scripts/objects/world/create-dungeon.ts index 9b800e2..b1e36fc 100644 --- a/frontend/src/scripts/objects/world/create-dungeon.ts +++ b/frontend/src/scripts/objects/world/create-dungeon.ts @@ -1,8 +1,8 @@ import { vec2 } from 'gl-matrix'; +import { Random } from '../../helper/random'; import { Physics } from '../../physics/physics'; import { Objects } from '../objects'; import { Tunnel } from '../types/tunnel'; -import { Random } from '../../helper/random'; export const createDungeon = (objects: Objects, physics: Physics): Tunnel => { let previousRadius = 350; @@ -10,7 +10,7 @@ export const createDungeon = (objects: Objects, physics: Physics): Tunnel => { let first: Tunnel; - for (let i = 0; i < 50000; i += 500) { + for (let i = 0; i < 500000; i += 500) { const deltaHeight = (Random.getRandom() - 0.5) * 2000; const height = previousEnd.y + deltaHeight; const currentEnd = vec2.fromValues(i, height); diff --git a/frontend/src/scripts/shapes/types/blob.ts b/frontend/src/scripts/shapes/types/blob.ts index 78dbe1d..c625071 100644 --- a/frontend/src/scripts/shapes/types/blob.ts +++ b/frontend/src/scripts/shapes/types/blob.ts @@ -1,32 +1,42 @@ import { vec2 } from 'gl-matrix'; -import { settings } from '../../drawing/settings'; import { GameObject } from '../../objects/game-object'; import { BoundingBox } from '../bounding-box'; import { IShape } from '../i-shape'; import { Circle } from './circle'; export class Blob implements IShape { - private static readonly boundingCircleRadius = 19; - private static readonly headOffset = vec2.fromValues(0, 15); - private static readonly torsoOffset = vec2.fromValues(0, 0); - private static readonly leftFootOffset = vec2.fromValues(-5, -10); - private static readonly rightFootOffset = vec2.fromValues(5, -10); + public readonly boundingCircleRadius = 100; + + protected readonly headRadius = 40; + protected readonly torsoRadius = 60; + protected readonly footRadius = 30; + + protected readonly k = 1000000; + + private readonly headOffset = vec2.fromValues( + 0, + this.headRadius + this.torsoRadius / 2 + ); + private readonly torsoOffset = vec2.fromValues(0, 0); + private readonly leftFootOffset = vec2.fromValues(-20, -60); + private readonly rightFootOffset = vec2.fromValues(20, -60); + public readonly isInverted = false; - protected boundingCircle = new Circle(vec2.create(), Blob.boundingCircleRadius); - protected head = new Circle(vec2.create(), settings.shaderMacros.headRadius); - protected torso = new Circle(vec2.create(), settings.shaderMacros.torsoRadius); - protected leftFoot = new Circle(vec2.create(), settings.shaderMacros.footRadius); - protected rightFoot = new Circle(vec2.create(), settings.shaderMacros.footRadius); + protected boundingCircle = new Circle(vec2.create(), this.boundingCircleRadius); + protected head = new Circle(vec2.create(), this.headRadius); + protected torso = new Circle(vec2.create(), this.torsoRadius); + protected leftFoot = new Circle(vec2.create(), this.footRadius); + protected rightFoot = new Circle(vec2.create(), this.footRadius); public constructor(center: vec2, public readonly gameObject: GameObject = null) { this.position = center; } public set position(value: vec2) { vec2.copy(this.boundingCircle.center, value); - vec2.add(this.head.center, value, Blob.headOffset); - vec2.add(this.torso.center, value, Blob.torsoOffset); - vec2.add(this.leftFoot.center, value, Blob.leftFootOffset); - vec2.add(this.rightFoot.center, value, Blob.rightFootOffset); + vec2.add(this.head.center, value, this.headOffset); + vec2.add(this.torso.center, value, this.torsoOffset); + vec2.add(this.leftFoot.center, value, this.leftFootOffset); + vec2.add(this.rightFoot.center, value, this.rightFootOffset); } public get center(): vec2 { diff --git a/frontend/src/scripts/shapes/types/tunnel-shape.ts b/frontend/src/scripts/shapes/types/tunnel-shape.ts index d20db34..94a5bbd 100644 --- a/frontend/src/scripts/shapes/types/tunnel-shape.ts +++ b/frontend/src/scripts/shapes/types/tunnel-shape.ts @@ -1,10 +1,10 @@ import { vec2 } from 'gl-matrix'; -import { BoundingBox } from '../bounding-box'; import { clamp01 } from '../../helper/clamp'; import { mix } from '../../helper/mix'; -import { IShape } from '../i-shape'; import { rotate90Deg } from '../../helper/rotate-90-deg'; import { GameObject } from '../../objects/game-object'; +import { BoundingBox } from '../bounding-box'; +import { IShape } from '../i-shape'; export default class TunnelShape implements IShape { public readonly isInverted = true; diff --git a/frontend/src/styles/main.scss b/frontend/src/styles/main.scss index 3781003..db5f1ad 100644 --- a/frontend/src/styles/main.scss +++ b/frontend/src/styles/main.scss @@ -1,6 +1,6 @@ html, body, -canvas { +canvas#main { height: 100%; width: 100%; } @@ -19,8 +19,7 @@ body { right: 0; $outline-width: 0.5px; text-shadow: -$outline-width -$outline-width 0 #000, - $outline-width -$outline-width 0 #000, - -$outline-width $outline-width 0 #000, + $outline-width -$outline-width 0 #000, -$outline-width $outline-width 0 #000, $outline-width $outline-width 0 #000; color: white; white-space: pre;