Start implementing input handling
This commit is contained in:
parent
c64ead08a3
commit
b7fec57c04
5 changed files with 94 additions and 19 deletions
|
@ -9,6 +9,7 @@ _ = lodash;
|
||||||
|
|
||||||
import MapContext from './control/MapContext';
|
import MapContext from './control/MapContext';
|
||||||
import MapData from './model/MapData';
|
import MapData from './model/MapData';
|
||||||
|
import InputHandler from './view/InputHandler';
|
||||||
|
|
||||||
|
|
||||||
var mapContext: MapContext;
|
var mapContext: MapContext;
|
||||||
|
@ -17,8 +18,9 @@ window.onload = () => {
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
xhr.onload = function() {
|
xhr.onload = function() {
|
||||||
let mapDef = new MapData(JSON.parse(this.responseText));
|
var mapDef = new MapData(JSON.parse(this.responseText));
|
||||||
mapContext = new MapContext(mapDef);
|
var inputHandler = new InputHandler();
|
||||||
|
mapContext = new MapContext(mapDef, inputHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
xhr.open('GET', 'resources/map/test.json', true);
|
xhr.open('GET', 'resources/map/test.json', true);
|
||||||
|
|
|
@ -7,6 +7,7 @@ import EntityPosition from '../model/EntityPosition';
|
||||||
import MapData from '../model/MapData';
|
import MapData from '../model/MapData';
|
||||||
import Position from '../model/Position';
|
import Position from '../model/Position';
|
||||||
|
|
||||||
|
import InputHandler from '../view/InputHandler';
|
||||||
import MapView from '../view/MapView';
|
import MapView from '../view/MapView';
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ export default class MapContext {
|
||||||
entities: {[key: string]: EntityPosition} = {};
|
entities: {[key: string]: EntityPosition} = {};
|
||||||
playerEntity: EntityPosition;
|
playerEntity: EntityPosition;
|
||||||
|
|
||||||
constructor(public map: MapData) {
|
constructor(private map: MapData, private inputHandler: InputHandler) {
|
||||||
this.playerEntity = new EntityPosition(
|
this.playerEntity = new EntityPosition(
|
||||||
new Entity('square'),
|
new Entity('square'),
|
||||||
new Position(8, 8),
|
new Position(8, 8),
|
||||||
|
@ -25,10 +26,36 @@ export default class MapContext {
|
||||||
|
|
||||||
this.addEntity(this.playerEntity);
|
this.addEntity(this.playerEntity);
|
||||||
|
|
||||||
this.view = new MapView(map, this.entities);
|
this.view = new MapView(map, this.entities, (time: number) => this.updateState(time));
|
||||||
|
|
||||||
|
inputHandler.addListener(() => {
|
||||||
|
if (this.updateState(performance.now()))
|
||||||
|
this.view.redraw();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addEntity(entity: EntityPosition) {
|
private addEntity(entity: EntityPosition) {
|
||||||
this.entities[entity.position.asString()] = entity;
|
this.entities[entity.position.asString()] = entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private updateState(time: number): boolean {
|
||||||
|
var ret = false;
|
||||||
|
var dir = this.playerEntity.direction;
|
||||||
|
|
||||||
|
if (this.inputHandler.keys[InputHandler.Up])
|
||||||
|
dir = Direction.North;
|
||||||
|
else if (this.inputHandler.keys[InputHandler.Right])
|
||||||
|
dir = Direction.East;
|
||||||
|
else if (this.inputHandler.keys[InputHandler.Down])
|
||||||
|
dir = Direction.South;
|
||||||
|
else if (this.inputHandler.keys[InputHandler.Left])
|
||||||
|
dir = Direction.West;
|
||||||
|
|
||||||
|
if (this.playerEntity.direction !== dir) {
|
||||||
|
this.playerEntity.direction = dir;
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ export enum Direction {
|
||||||
West
|
West
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export module Direction {
|
||||||
export function reverse(r: Direction): Direction { return (r+2) % 4; }
|
export function reverse(r: Direction): Direction { return (r+2) % 4; }
|
||||||
|
}
|
||||||
|
|
||||||
export default Direction;
|
export default Direction;
|
||||||
|
|
40
src/view/InputHandler.ts
Normal file
40
src/view/InputHandler.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
|
import Direction from '../model/Direction';
|
||||||
|
|
||||||
|
|
||||||
|
class InputHandler {
|
||||||
|
keys: {[key: number]: boolean} = {};
|
||||||
|
|
||||||
|
listeners: (() => void)[] = [];
|
||||||
|
|
||||||
|
private callListeners() {
|
||||||
|
this.listeners.forEach(l => l());
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
window.addEventListener('keydown', (ev) => {
|
||||||
|
this.keys[ev.keyCode] = true;
|
||||||
|
this.callListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('keyup', (ev) => {
|
||||||
|
delete this.keys[ev.keyCode];
|
||||||
|
this.callListeners();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addListener(l: () => void) {
|
||||||
|
this.listeners.push(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module InputHandler {
|
||||||
|
export const Left = 37;
|
||||||
|
export const Up = 38;
|
||||||
|
export const Right = 39;
|
||||||
|
export const Down = 40;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default InputHandler;
|
|
@ -40,15 +40,17 @@ function loadEntities(entities: EntityPosition[]): Promise<{[key: string]: HTMLI
|
||||||
|
|
||||||
|
|
||||||
export default class MapView {
|
export default class MapView {
|
||||||
redrawPending: boolean = false;
|
private redrawPending: boolean = false;
|
||||||
|
|
||||||
canvas: HTMLCanvasElement;
|
private canvas: HTMLCanvasElement;
|
||||||
ctx: CanvasRenderingContext2D;
|
private ctx: CanvasRenderingContext2D;
|
||||||
|
|
||||||
tiles: {[key: string]: HTMLImageElement};
|
private tiles: {[key: string]: HTMLImageElement};
|
||||||
entitySprites: {[key: string]: HTMLImageElement};
|
private entitySprites: {[key: string]: HTMLImageElement};
|
||||||
|
|
||||||
constructor(private map: MapData, private entities: {[key: string]: EntityPosition}) {
|
constructor(private map: MapData,
|
||||||
|
private entities: {[key: string]: EntityPosition},
|
||||||
|
private updateState: (time: number) => void) {
|
||||||
this.canvas = document.createElement('canvas');
|
this.canvas = document.createElement('canvas');
|
||||||
this.canvas.style.position = 'absolute';
|
this.canvas.style.position = 'absolute';
|
||||||
body.appendChild(this.canvas);
|
body.appendChild(this.canvas);
|
||||||
|
@ -71,11 +73,11 @@ export default class MapView {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getEntities(): EntityPosition[] {
|
private getEntities(): EntityPosition[] {
|
||||||
return _.valuesIn<EntityPosition>(this.entities);
|
return _.values<EntityPosition>(this.entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
setSize() {
|
private setSize() {
|
||||||
var e = document.documentElement;
|
var e = document.documentElement;
|
||||||
this.canvas.width = window.innerWidth || e.clientWidth || body.clientWidth;
|
this.canvas.width = window.innerWidth || e.clientWidth || body.clientWidth;
|
||||||
this.canvas.height = window.innerHeight || e.clientHeight || body.clientHeight;
|
this.canvas.height = window.innerHeight || e.clientHeight || body.clientHeight;
|
||||||
|
@ -83,14 +85,14 @@ export default class MapView {
|
||||||
this.redraw()
|
this.redraw()
|
||||||
}
|
}
|
||||||
|
|
||||||
drawTile(x: number, y: number, tile: HTMLImageElement) {
|
private drawTile(x: number, y: number, tile: HTMLImageElement) {
|
||||||
if (!tile)
|
if (!tile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.ctx.drawImage(tile, x, y);
|
this.ctx.drawImage(tile, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
drawEntity(e: EntityPosition) {
|
private drawEntity(e: EntityPosition) {
|
||||||
var sprite = this.entitySprites[e.entity.name];
|
var sprite = this.entitySprites[e.entity.name];
|
||||||
if (!sprite)
|
if (!sprite)
|
||||||
return;
|
return;
|
||||||
|
@ -104,7 +106,9 @@ export default class MapView {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
draw() {
|
private draw(time: number) {
|
||||||
|
this.updateState(time);
|
||||||
|
|
||||||
this.redrawPending = false;
|
this.redrawPending = false;
|
||||||
|
|
||||||
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||||
|
@ -137,6 +141,6 @@ export default class MapView {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.redrawPending = true;
|
this.redrawPending = true;
|
||||||
window.requestAnimationFrame(() => this.draw());
|
window.requestAnimationFrame((time: number) => this.draw(time));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue