WIP
This commit is contained in:
parent
24cc572e47
commit
345e183e34
30 changed files with 628 additions and 187 deletions
|
|
@ -1,33 +1,16 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { Command } from '../commands/command';
|
||||
import { CommandReceiver } from '../commands/command-receiver';
|
||||
import { IdentityManager } from '../identity/identity-manager';
|
||||
import { Objects } from './objects';
|
||||
import { Physics } from '../physics/physics';
|
||||
|
||||
export abstract class GameObject implements CommandReceiver {
|
||||
public readonly id = IdentityManager.generateId();
|
||||
|
||||
protected _position = vec2.create();
|
||||
public get position(): vec2 {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
protected _boundingBoxSize = vec2.create();
|
||||
public get boundingBoxSize(): vec2 {
|
||||
return this._boundingBoxSize;
|
||||
}
|
||||
|
||||
private commandExecutors: {
|
||||
[commandType: string]: (e: Command) => void;
|
||||
} = {};
|
||||
|
||||
// can only be called inside the constructor
|
||||
protected addCommandExecutor<T extends Command>(
|
||||
commandType: new () => T,
|
||||
handler: (command: T) => void
|
||||
) {
|
||||
this.commandExecutors[new commandType().type] = handler;
|
||||
}
|
||||
|
||||
public reactsToCommand(commandType: string): boolean {
|
||||
return this.commandExecutors.hasOwnProperty(commandType);
|
||||
}
|
||||
|
|
@ -39,4 +22,12 @@ export abstract class GameObject implements CommandReceiver {
|
|||
this.commandExecutors[commandType](command);
|
||||
}
|
||||
}
|
||||
|
||||
// can only be called inside the constructor
|
||||
protected addCommandExecutor<T extends Command>(
|
||||
commandType: new () => T,
|
||||
handler: (command: T) => void
|
||||
) {
|
||||
this.commandExecutors[new commandType().type] = handler;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { CommandReceiver } from '../commands/command-receiver';
|
|||
import { Id } from '../identity/identity';
|
||||
import { GameObject } from './game-object';
|
||||
|
||||
export class ObjectContainer implements CommandReceiver {
|
||||
export class Objects implements CommandReceiver {
|
||||
private objects: Map<Id, GameObject> = new Map();
|
||||
private objectsGroupedByAbilities: Map<string, Array<GameObject>> = new Map();
|
||||
|
||||
|
|
@ -5,14 +5,20 @@ import { GameObject } from '../game-object';
|
|||
import { Lamp } from './lamp';
|
||||
import { ZoomCommand } from '../../input/commands/zoom';
|
||||
import { MoveToCommand } from '../../physics/commands/move-to';
|
||||
import { BoundingBox } from '../../physics/containers/bounding-box';
|
||||
import { Physics } from '../../physics/physics';
|
||||
|
||||
export class Camera extends GameObject {
|
||||
private inViewArea = 1920 * 1080 * 5;
|
||||
private cursorPosition = vec2.create();
|
||||
private boundingBox: BoundingBox;
|
||||
|
||||
constructor(private light: Lamp) {
|
||||
constructor(physics: Physics, private light: Lamp) {
|
||||
super();
|
||||
|
||||
this.boundingBox = new BoundingBox(null);
|
||||
physics.addDynamicBoundingBox(this.boundingBox);
|
||||
|
||||
this.addCommandExecutor(BeforeRenderCommand, this.draw.bind(this));
|
||||
this.addCommandExecutor(MoveToCommand, this.moveTo.bind(this));
|
||||
this.addCommandExecutor(
|
||||
|
|
@ -22,20 +28,27 @@ export class Camera extends GameObject {
|
|||
this.addCommandExecutor(ZoomCommand, this.zoom.bind(this));
|
||||
}
|
||||
|
||||
public get viewAreaSize(): vec2 {
|
||||
return this.boundingBox.size;
|
||||
}
|
||||
|
||||
private draw(c: BeforeRenderCommand) {
|
||||
c.renderer.setCameraPosition(this.position);
|
||||
console.log('camera', this.boundingBox.topLeft);
|
||||
|
||||
c.renderer.setCameraPosition(this.boundingBox.topLeft);
|
||||
c.renderer.setCursorPosition(this.cursorPosition);
|
||||
this._boundingBoxSize = c.renderer.setInViewArea(this.inViewArea);
|
||||
this.boundingBox.size = c.renderer.setInViewArea(this.inViewArea);
|
||||
}
|
||||
|
||||
private moveTo(c: MoveToCommand) {
|
||||
this._position = c.position;
|
||||
console.log('camera', c.position);
|
||||
this.boundingBox.topLeft = c.position;
|
||||
this.light.sendCommand(
|
||||
new MoveToCommand(
|
||||
vec2.add(
|
||||
vec2.create(),
|
||||
c.position,
|
||||
vec2.scale(vec2.create(), this.boundingBoxSize, 0.5)
|
||||
vec2.scale(vec2.create(), this.boundingBox.size, 0.5)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,37 +1,80 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { GameObject } from '../game-object';
|
||||
import { Camera } from './camera';
|
||||
import { StepCommand } from '../../physics/commands/step';
|
||||
import { Circle } from '../../drawing/drawables/primitives/circle';
|
||||
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 { BoundingBox } from '../../physics/containers/bounding-box';
|
||||
import { Physics } from '../../physics/physics';
|
||||
import { GameObject } from '../game-object';
|
||||
import { Camera } from './camera';
|
||||
|
||||
export class Character extends GameObject {
|
||||
private keysDown: Set<string> = new Set();
|
||||
|
||||
private static speed = 0.5;
|
||||
private primitive: Circle;
|
||||
private static speed = 1.5;
|
||||
|
||||
constructor(private camera: Camera) {
|
||||
constructor(private physics: Physics, private camera: Camera) {
|
||||
super();
|
||||
|
||||
this.primitive = new Circle(this);
|
||||
this.primitive.radius = 20;
|
||||
|
||||
this.addCommandExecutor(StepCommand, this.stepHandler.bind(this));
|
||||
this.addCommandExecutor(TeleportToCommand, (c) =>
|
||||
this.setPosition(c.position)
|
||||
);
|
||||
this.addCommandExecutor(KeyDownCommand, (c) => this.keysDown.add(c.key));
|
||||
this.addCommandExecutor(KeyUpCommand, (c) => this.keysDown.delete(c.key));
|
||||
this.addCommandExecutor(SwipeCommand, (c) =>
|
||||
this.setPosition(
|
||||
this.checkAndSetPosition(
|
||||
vec2.add(
|
||||
vec2.create(),
|
||||
this.position,
|
||||
vec2.multiply(vec2.create(), c.delta, this.camera.boundingBoxSize)
|
||||
this.primitive.center,
|
||||
vec2.multiply(vec2.create(), c.delta, this.camera.viewAreaSize)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private checkAndSetPosition(value: vec2) {
|
||||
const size = this.camera.viewAreaSize;
|
||||
const realCenter = vec2.fromValues(
|
||||
value.x + size.x / 2,
|
||||
value.y + size.y / 2
|
||||
);
|
||||
|
||||
const targetBoundingBox = new BoundingBox(
|
||||
null,
|
||||
value.x + size.x / 2,
|
||||
value.x + size.x / 2 + 10,
|
||||
value.y + size.y / 2,
|
||||
value.y + size.y / 2 + 10
|
||||
);
|
||||
|
||||
console.log(
|
||||
this.physics
|
||||
.findIntersecting(targetBoundingBox)
|
||||
.map((b) => b.value.distance(realCenter))
|
||||
);
|
||||
if (
|
||||
this.physics
|
||||
.findIntersecting(targetBoundingBox)
|
||||
.map((b) => b.value.distance(realCenter))
|
||||
.find((d) => d < 0) !== undefined
|
||||
) {
|
||||
this.setPosition(value);
|
||||
}
|
||||
}
|
||||
|
||||
private setPosition(value: vec2) {
|
||||
this._position = value;
|
||||
this.camera.sendCommand(new MoveToCommand(this.position));
|
||||
console.log('character', value);
|
||||
|
||||
this.primitive.center = value;
|
||||
this.camera.sendCommand(new MoveToCommand(this.primitive.center));
|
||||
}
|
||||
|
||||
public stepHandler(c: StepCommand) {
|
||||
|
|
@ -44,16 +87,11 @@ export class Character extends GameObject {
|
|||
|
||||
const movementVector = vec2.fromValues(right - left, up - down);
|
||||
if (movementVector.length > 0) {
|
||||
this.setPosition(
|
||||
vec2.add(
|
||||
vec2.create(),
|
||||
this.position,
|
||||
vec2.scale(
|
||||
vec2.create(),
|
||||
vec2.normalize(movementVector, movementVector),
|
||||
Character.speed * deltaTime
|
||||
)
|
||||
)
|
||||
vec2.normalize(movementVector, movementVector);
|
||||
vec2.scale(movementVector, movementVector, Character.speed * deltaTime);
|
||||
|
||||
this.checkAndSetPosition(
|
||||
vec2.add(vec2.create(), this.primitive.center, movementVector)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(this, center, radius, color, lightness);
|
||||
|
||||
this.addCommandExecutor(RenderCommand, this.draw.bind(this));
|
||||
this.addCommandExecutor(MoveToCommand, this.moveTo.bind(this));
|
||||
|
|
|
|||
|
|
@ -1,16 +1,25 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { TunnelShape } from '../../drawing/drawables/primitives/tunnel-shape';
|
||||
import { GameObject } from '../game-object';
|
||||
import { RenderCommand } from '../../drawing/commands/render';
|
||||
import { Physics } from '../../physics/physics';
|
||||
import { TunnelShape } from '../../drawing/drawables/primitives/tunnel-shape';
|
||||
|
||||
export interface Line {}
|
||||
|
||||
export class Tunnel extends GameObject {
|
||||
private primitive: TunnelShape;
|
||||
|
||||
constructor(from: vec2, to: vec2, fromRadius: number, toRadius: number) {
|
||||
constructor(
|
||||
physics: Physics,
|
||||
public readonly from: vec2,
|
||||
to: vec2,
|
||||
fromRadius: number,
|
||||
toRadius: number
|
||||
) {
|
||||
super();
|
||||
this.primitive = new TunnelShape(from, to, fromRadius, toRadius);
|
||||
|
||||
this.primitive = new TunnelShape(this, from, to, fromRadius, toRadius);
|
||||
physics.addStaticBoundingBox(this.primitive.boundingBox);
|
||||
this.addCommandExecutor(RenderCommand, this.draw.bind(this));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
import { vec2, vec3 } from 'gl-matrix';
|
||||
import { ObjectContainer } from '../object-container';
|
||||
import { Objects } from '../objects';
|
||||
import { Camera } from '../types/camera';
|
||||
import { Character } from '../types/character';
|
||||
import { Lamp } from '../types/lamp';
|
||||
import { Physics } from '../../physics/physics';
|
||||
import { GameObject } from '../game-object';
|
||||
|
||||
export const createCharacter = (objects: ObjectContainer) => {
|
||||
export const createCharacter = (
|
||||
objects: Objects,
|
||||
physics: Physics
|
||||
): GameObject => {
|
||||
const light = new Lamp(
|
||||
vec2.create(),
|
||||
40,
|
||||
|
|
@ -12,8 +17,11 @@ export const createCharacter = (objects: ObjectContainer) => {
|
|||
2
|
||||
);
|
||||
|
||||
const camera = new Camera(light);
|
||||
const camera = new Camera(physics, light);
|
||||
const character = new Character(physics, camera);
|
||||
objects.addObject(light);
|
||||
objects.addObject(camera);
|
||||
objects.addObject(new Character(camera));
|
||||
objects.addObject(character);
|
||||
|
||||
return character;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,22 +1,35 @@
|
|||
import { vec2, vec3 } from 'gl-matrix';
|
||||
import { ObjectContainer } from '../object-container';
|
||||
import { Lamp } from '../types/lamp';
|
||||
import { Objects } from '../objects';
|
||||
import { Tunnel } from '../types/tunnel';
|
||||
import { Physics } from '../../physics/physics';
|
||||
import { GameObject } from '../game-object';
|
||||
|
||||
export const createDungeon = (objects: ObjectContainer) => {
|
||||
export const createDungeon = (objects: Objects, physics: Physics): Tunnel => {
|
||||
let previousRadius = 350;
|
||||
let previousEnd = vec2.create();
|
||||
|
||||
for (let i = 0; i < 500000; i += 500) {
|
||||
let first: Tunnel;
|
||||
|
||||
for (let i = 0; i < 1; i += 500) {
|
||||
const deltaHeight = (Math.random() - 0.5) * 2000;
|
||||
const height = previousEnd.y + deltaHeight;
|
||||
const currentEnd = vec2.fromValues(i, height);
|
||||
const currentToRadius = Math.random() * 300 + 150;
|
||||
|
||||
objects.addObject(
|
||||
new Tunnel(previousEnd, currentEnd, previousRadius, currentToRadius)
|
||||
const tunnel = new Tunnel(
|
||||
physics,
|
||||
previousEnd,
|
||||
currentEnd,
|
||||
previousRadius,
|
||||
currentToRadius
|
||||
);
|
||||
|
||||
if (!first) {
|
||||
first = tunnel;
|
||||
}
|
||||
|
||||
objects.addObject(tunnel);
|
||||
|
||||
/*if (deltaHeight > 0 && Math.random() > 0.8) {
|
||||
objects.addObject(
|
||||
new Lamp(
|
||||
|
|
@ -35,4 +48,6 @@ export const createDungeon = (objects: ObjectContainer) => {
|
|||
previousEnd = currentEnd;
|
||||
previousRadius = currentToRadius;
|
||||
}
|
||||
|
||||
return first;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue