Work on various issues
This commit is contained in:
parent
b7afa274f2
commit
a6efbc02b9
15 changed files with 257 additions and 126 deletions
|
|
@ -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<TunnelShape> = [
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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],
|
||||
|
|
|
|||
|
|
@ -7,19 +7,21 @@ precision mediump float;
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
|
||||
#if SOFT_SHADOWS_ENABLED
|
||||
float q = INFINITY;
|
||||
float rayLength = startingDistance;
|
||||
float rayLength = startingDistance / SOFT_SHADOWS_QUALITY;
|
||||
vec2 direction = normalize(circleLightDirections[i]) / viewAreaScale / 2.0;
|
||||
for (int j = 0; j < 48; j++) {
|
||||
if (rayLength >= lightDistance) {
|
||||
for (int j = 0; j < 48 * int(ceil(SOFT_SHADOWS_QUALITY)); j++) {
|
||||
if (rayLength >= traceDistance) {
|
||||
lighting += lightColorAtPosition * clamp(
|
||||
q / circleLights[i].radius * lightCenterDistance, 0.0, 1.0
|
||||
);
|
||||
(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;
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<number> = [];
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<string> = 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) {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue