Implement smooth transitions

This commit is contained in:
Matthias Schiffer 2016-01-07 11:22:59 +01:00
parent b7fec57c04
commit 584728a129
5 changed files with 101 additions and 18 deletions

View file

@ -6,6 +6,7 @@ import Entity from '../model/Entity';
import EntityPosition from '../model/EntityPosition'; 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 Transition from '../model/Transition';
import InputHandler from '../view/InputHandler'; import InputHandler from '../view/InputHandler';
import MapView from '../view/MapView'; import MapView from '../view/MapView';
@ -38,24 +39,47 @@ export default class MapContext {
this.entities[entity.position.asString()] = entity; this.entities[entity.position.asString()] = entity;
} }
private addTransition(entity: EntityPosition, dest: Position, start: number, dur: number) {
entity.transition = new Transition(start, start+dur, entity.position, dest);
}
private finishTransition(entity: EntityPosition) {
entity.position = entity.transition.dest;
entity.transition = null;
}
private updateState(time: number): boolean { private updateState(time: number): boolean {
var ret = false; var ret = false;
var dir = this.playerEntity.direction;
if (this.inputHandler.keys[InputHandler.Up]) while (true) {
dir = Direction.North; var origTime = time;
else if (this.inputHandler.keys[InputHandler.Right])
dir = Direction.East; if (this.playerEntity.transition && this.playerEntity.transition.end <= time) {
else if (this.inputHandler.keys[InputHandler.Down]) origTime = this.playerEntity.transition.end;
dir = Direction.South; this.finishTransition(this.playerEntity);
else if (this.inputHandler.keys[InputHandler.Left]) ret = true;
dir = Direction.West; }
if (this.playerEntity.transition)
return true;
var dir: Direction = null;
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 (dir === null)
return ret;
if (this.playerEntity.direction !== dir) {
this.playerEntity.direction = dir; this.playerEntity.direction = dir;
ret = true; this.addTransition(this.playerEntity, this.playerEntity.position.translate(dir, 1),
origTime, 250);
} }
return ret;
} }
} }

View file

@ -1,11 +1,14 @@
'use strict'; 'use strict';
import Direction from '../model/Direction'; import Direction from './Direction';
import Entity from './Entity'; import Entity from './Entity';
import Position from './Position'; import Position from './Position';
import Transition from './Transition';
export default class EntityPosition { export default class EntityPosition {
public transition: Transition = null;
constructor(public entity: Entity, public position: Position, public direction: Direction) {} constructor(public entity: Entity, public position: Position, public direction: Direction) {}
} }

View file

@ -1,9 +1,35 @@
'use strict'; 'use strict';
import Direction from './Direction';
export default class Position { export default class Position {
constructor(public x: number, public y: number) {} constructor(public x: number, public y: number) {}
translate(dir: Direction, amount: number): Position {
var p = new Position(this.x, this.y);
switch (dir) {
case Direction.North:
p.y -= amount;
break;
case Direction.East:
p.x += amount;
break;
case Direction.South:
p.y += amount;
break;
case Direction.West:
p.x -= amount;
}
return p;
}
asString(): string { asString(): string {
return `${this.x},${this.y}`; return `${this.x},${this.y}`;
} }

8
src/model/Transition.ts Normal file
View file

@ -0,0 +1,8 @@
'use strict';
import Position from './Position';
export default class Transition {
constructor(public start: number, public end: number, public orig: Position, public dest: Position) {}
};

View file

@ -92,18 +92,34 @@ export default class MapView {
this.ctx.drawImage(tile, x, y); this.ctx.drawImage(tile, x, y);
} }
private drawEntity(e: EntityPosition) { private drawEntity(e: EntityPosition, time: number): boolean {
var sprite = this.entitySprites[e.entity.name]; var sprite = this.entitySprites[e.entity.name];
if (!sprite) if (!sprite)
return; return false;
var x: number, y: number;
if (e.transition) {
var t = e.transition;
var d = (time - t.start) / (t.end-t.start);
x = (1-d) * t.orig.x + d * t.dest.x;
y = (1-d) * t.orig.y + d * t.dest.y;
}
else {
x = e.position.x;
y = e.position.y;
}
this.ctx.drawImage( this.ctx.drawImage(
sprite, sprite,
e.direction*tileSize, 0, e.direction*tileSize, 0,
tileSize, tileSize, tileSize, tileSize,
e.position.x*tileSize, e.position.y*tileSize, x*tileSize, y*tileSize,
tileSize, tileSize tileSize, tileSize
); );
return !!e.transition;
} }
private draw(time: number) { private draw(time: number) {
@ -131,9 +147,15 @@ export default class MapView {
}); });
}); });
var animate = false;
this.getEntities().forEach(e => { this.getEntities().forEach(e => {
this.drawEntity(e); if (this.drawEntity(e, time))
animate = true;
}); });
if (animate)
this.redraw();
} }
redraw() { redraw() {