summaryrefslogtreecommitdiffstats
path: root/src/controller
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2018-12-08 12:39:18 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2018-12-08 12:39:18 +0100
commitb3950330e3351437f153c6c1debb3821d6e28864 (patch)
tree0b381b523045bd59cd679825a11976a45813fc24 /src/controller
parent439dcf391784ea3abb61473c74b9c27fcd9fdc2d (diff)
downloadrpgedit-b3950330e3351437f153c6c1debb3821d6e28864.tar
rpgedit-b3950330e3351437f153c6c1debb3821d6e28864.zip
Create Electron app
Diffstat (limited to 'src/controller')
-rw-r--r--src/controller/collision.ts65
-rw-r--r--src/controller/entitycontext.ts47
-rw-r--r--src/controller/gamecontext.ts174
3 files changed, 0 insertions, 286 deletions
diff --git a/src/controller/collision.ts b/src/controller/collision.ts
deleted file mode 100644
index a44ffa4..0000000
--- a/src/controller/collision.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { Collision } from '../model/data/collision';
-
-import { Circle } from '../math/circle';
-import { Collidable } from '../math/collision';
-import { LineSegment, Movement } from '../math/line';
-import { Point } from '../math/point';
-
-import { vec2 } from 'gl-matrix';
-
-export function mkCollision(collision: Collision[]): Collidable[] {
- const ret: Collidable[] = [];
-
- for (const c of collision) {
- switch (c.type) {
- case 'polygon':
- if (!c.vertices.length)
- continue;
-
- let prev = c.vertices[c.vertices.length - 1];
-
- for (const v of c.vertices) {
- ret.push(LineSegment.fromPoints(vec2.clone(prev), vec2.clone(v)));
- prev = v;
- }
-
- for (const v of c.vertices) {
- ret.push(new Point(vec2.clone(v)));
- prev = v;
- }
- break;
-
- case 'circle':
- ret.push(new Circle(vec2.clone(c.center), c.radius));
- break;
- }
- }
-
- return ret;
-}
-
-export interface CollidableGroup {
- getTranslation(): vec2|null;
- getCollidables(): Collidable[];
-}
-
-export function collide(collision: CollidableGroup, out: vec2, move: Movement, radius: number): boolean {
- const t = collision.getTranslation();
- if (t)
- move = move.translate(vec2.negate(vec2.create(), t));
-
- for (const c of collision.getCollidables()) {
- if (!c.collide(out, move, radius))
- continue;
-
- if (vec2.squaredDistance(move.src, out) >= vec2.squaredDistance(move.src, move.dest))
- continue;
-
- if (t)
- vec2.add(out, out, t);
-
- return true;
- }
-
- return false;
-}
diff --git a/src/controller/entitycontext.ts b/src/controller/entitycontext.ts
deleted file mode 100644
index 434bf9b..0000000
--- a/src/controller/entitycontext.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import { EntityView } from '../view/entity';
-import { Renderer } from '../view/renderer/renderer';
-
-import { Collidable } from '../math/collision';
-
-import { CollidableGroup, mkCollision } from './collision';
-
-import { vec2 } from 'gl-matrix';
-
-export class EntityContext implements CollidableGroup {
- public static async load(renderer: Renderer, name: string): Promise<EntityContext> {
- return new EntityContext(
- renderer,
- name,
- await EntityView.load(renderer, name),
- );
- }
-
- public readonly pos: vec2 = vec2.create();
-
- private readonly collision: Collidable[];
-
- private constructor(
- private readonly renderer: Renderer,
- private readonly name: string,
- private readonly view: EntityView,
- ) {
- this.collision = mkCollision(view.data.collision);
- }
-
- public render(time: number) {
- this.renderer.setTranslation(this.pos);
- this.view.renderByTime(time);
- }
-
- public getTranslation(): vec2 {
- return this.pos;
- }
-
- public getCollidables(): Collidable[] {
- return this.collision;
- }
-
- public interact() {
- alert(`You've interacted with ${this.name}!`);
- }
-}
diff --git a/src/controller/gamecontext.ts b/src/controller/gamecontext.ts
deleted file mode 100644
index 9a68e25..0000000
--- a/src/controller/gamecontext.ts
+++ /dev/null
@@ -1,174 +0,0 @@
-import { CollidableGroup, collide, mkCollision } from './collision';
-import { EntityContext } from './entitycontext';
-
-import { MapData } from '../model/data/map';
-
-import { ButtonCode, GameInputHandler } from '../view/input/gameinput';
-import { MapView } from '../view/map';
-import { Renderer } from '../view/renderer/renderer';
-
-import { Collidable } from '../math/collision';
-import { Movement } from '../math/line';
-import { getJSON, nextAnimationFrame } from '../util';
-
-import { vec2 } from 'gl-matrix';
-
-export class GameContext implements CollidableGroup {
- public static async load(renderer: Renderer): Promise<GameContext> {
- const map = this.loadMap(renderer, 'test');
- const loadPlayer = EntityContext.load(renderer, 'green_circle');
- const loadEntity = EntityContext.load(renderer, 'red_circle');
-
- const [mapView, mapCollision] = await map;
- const player = await loadPlayer;
- const entity = await loadEntity;
-
- vec2.set(player.pos, 7, 6);
- vec2.set(entity.pos, 4, 3);
-
- return new GameContext(
- renderer,
- mapView,
- player,
- [entity],
- mapCollision,
- );
- }
-
- private static async loadMap(renderer: Renderer, name: string): Promise<[MapView, Collidable[]]> {
- const map = new MapData(await getJSON(`resources/map/${name}.json`));
- return [await MapView.load(renderer, map), mkCollision(map.collision)];
- }
-
- private readonly initTime: number = performance.now();
- private time = 0;
-
- private readonly tick = 10; // ms per tick
- private readonly maxSpeed = 0.04; // movement per tick
- private readonly maxSkip = 20; // maximum ticks to process in a single render step
-
- private readonly input: GameInputHandler;
-
- private readonly playerDir: vec2 = vec2.fromValues(0, 1);
- private speed: number = 0;
-
- private readonly collisionRadius = 15 / 32;
- private readonly interactLength = 1 / 32;
-
- private constructor(
- private readonly renderer: Renderer,
- private readonly mapView: MapView,
- private readonly player: EntityContext,
- private readonly entities: EntityContext[],
- private readonly collision: Collidable[],
- ) {
- this.input = new GameInputHandler();
- this.input.addListener((input) => {
- switch (input.type) {
- case 'button':
- if (input.button === ButtonCode.Action)
- this.interact();
- break;
-
- case 'direction':
- if (vec2.sqrLen(input.direction) > 0) {
- vec2.copy(this.playerDir, input.direction);
- this.speed = this.maxSpeed;
- } else {
- this.speed = 0;
- }
- break;
- }
- });
-
- this.renderLoop();
- }
-
- public getTranslation(): null {
- return null;
- }
-
- public getCollidables(): Collidable[] {
- return this.collision;
- }
-
- private updateTime(time: number): number {
- const diff = Math.round(time / this.tick) - Math.round(this.time / this.tick);
- this.time = time;
-
- return diff;
- }
-
- private canInteract(c: CollidableGroup): boolean {
- const dest = vec2.scaleAndAdd(vec2.create(), this.player.pos, this.playerDir, this.interactLength);
- const move = new Movement(this.player.pos, dest);
-
- return collide(c, vec2.create(), move, this.collisionRadius);
- }
-
- private interact(): void {
- for (const e of this.entities) {
- if (!this.canInteract(e))
- continue;
-
- e.interact();
- break;
- }
- }
-
- private updateStepCollide(out: vec2, dest: vec2): boolean {
- const move = new Movement(this.player.pos, dest);
-
- for (const c of [this, ...this.entities]) {
- if (collide(c, out, move, this.collisionRadius)) {
- if (vec2.squaredDistance(move.src, out) >= vec2.squaredDistance(move.src, move.dest))
- continue;
-
- return true;
- }
- }
-
- return false;
- }
-
- private updateStep(): void {
- const dest = vec2.scaleAndAdd(vec2.create(), this.player.pos, this.playerDir, this.speed);
- const newDest = vec2.create();
-
- while (this.updateStepCollide(newDest, dest)) {
- if (vec2.equals(newDest, this.player.pos))
- return;
-
- vec2.copy(dest, newDest);
- }
-
- vec2.copy(this.player.pos, dest);
- }
-
- private update(time: number): void {
- const diff = Math.min(this.maxSkip, this.updateTime(time));
-
- if (!this.speed) {
- this.renderer.snapToGrid(this.player.pos, this.player.pos);
- return;
- }
-
- for (let i = 0; i < diff; i++)
- this.updateStep();
- }
-
- private render(): void {
- this.renderer.setCenter(this.player.pos);
- this.renderer.clear();
-
- for (const r of [this.mapView, ...this.entities, this.player])
- r.render(this.time);
- }
-
- private async renderLoop(): Promise<void> {
- while (true) {
- this.update(await nextAnimationFrame() - this.initTime);
- this.render();
- }
- }
-}