summaryrefslogtreecommitdiffstats
path: root/src/control/MapContext.ts
blob: 1660ad49cfaff9ed88ab0bc8f8de36ae8ae8855a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
'use strict';


import Direction from '../model/Direction';
import Entity from '../model/Entity';
import EntityPosition from '../model/EntityPosition';
import MapData from '../model/MapData';
import Position from '../model/Position';
import Transition from '../model/Transition';

import InputHandler from '../view/InputHandler';
import MapView from '../view/MapView';


export default class MapContext {
        private view: MapView;

        private entities: EntityPosition[] = [];
        private playerEntity: EntityPosition;

        private collision: number[][];


        constructor(private map: MapData, private inputHandler: InputHandler) {
                this.collision = new Array(map.width);
                for (let i = 0; i < map.width; i++) {
                        this.collision[i] = new Array(map.height);

                        for (let j = 0; j < map.height; j++)
                                this.collision[i][j] = map.collision[j][i] == '0' ? 0 : 1;
                }

                this.playerEntity = new EntityPosition(
                        new Entity('square'),
                        new Position(8, 8),
                        Direction.East
                );

                this.addEntity(this.playerEntity);

                this.addEntity(new EntityPosition(
                        new Entity('square'),
                        new Position(10, 10),
                        Direction.East
                ));

                this.view = new MapView(
                        map,
                        this.entities,
                        this.playerEntity,
                        (time: number) => this.updateState(time)
                );

                inputHandler.addListener(() => {
                        if (this.updateState(performance.now()))
                                this.view.redraw();
                });
        }


        private inMap(p: Position): boolean {
                return p.x >= 0 && p.x < this.map.width && p.y >= 0 && p.y < this.map.height;
        }

        private incCollision(p: Position): void {
                if (this.inMap(p))
                        this.collision[p.x][p.y]++;
        }

        private decCollision(p: Position): void {
                if (this.inMap(p))
                        this.collision[p.x][p.y]--;
        }

        private collides(p: Position): boolean {
                return (!this.inMap(p)) || (this.collision[p.x][p.y] > 0);
        }

        private addEntity(entity: EntityPosition): void {
                this.entities.push(entity);

                this.incCollision(entity.position);
        }

        private addTransition(entity: EntityPosition, dest: Position, start: number, dur: number): void {
                entity.transition = new Transition(start, start+dur, entity.position, dest);

                this.incCollision(dest);
        }

        private finishTransition(entity: EntityPosition): void {
                this.decCollision(entity.position);

                entity.position = entity.transition.dest;
                entity.transition = null;

        }

        private updateState(time: number): boolean {
                var ret = false;

                while (true) {
                        let origTime = time;

                        if (this.playerEntity.transition && this.playerEntity.transition.end <= time) {
                                origTime = this.playerEntity.transition.end;
                                this.finishTransition(this.playerEntity);
                                ret = true;
                        }

                        if (this.playerEntity.transition)
                                return true;

                        let 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;

                        this.playerEntity.direction = dir;
                        ret = true;

                        let dest = this.playerEntity.position.translate(dir, 1);
                        if (this.collides(dest))
                                return true;

                        this.addTransition(this.playerEntity, dest, origTime, 250);
                }
        }
}