]> git.lizzy.rs Git - dragonblocks.git/blob - engine/map_display.js
Implement per-map sky
[dragonblocks.git] / engine / map_display.js
1 /*
2  * map_display.js
3  *
4  * Copyright 2021 Elias Fleckenstein <eliasfleckenstein@web.de>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  * MA 02110-1301, USA.
20  *
21  *
22  */
23
24 dragonblocks.MapDisplay = class
25 {
26         constructor()
27         {
28                 this.map = null;
29                 this.anchor = null;
30
31                 this.scale = dragonblocks.settings.mapDisplay.scale;
32                 this.width = Math.ceil(innerWidth / this.scale);
33                 this.height = Math.ceil(innerHeight / this.scale);
34                 this.left = 0;
35                 this.top = 0;
36
37                 this.element = document.body.insertBefore(document.createElement("div"), document.body.firstChild);
38                 this.element.style.width = this.width * this.scale + "px";
39                 this.element.style.height = this.height * this.scale + "px";
40                 this.element.style.position = "fixed";
41                 this.element.style.top = "0px";
42                 this.element.style.left = "0px";
43                 this.element.style.visibility = "hidden";
44
45                 this.nodes = [];
46                 for (let x = 0; x < this.width; x++) {
47                         this.nodes[x] = [];
48                         for (let y = 0; y < this.height; y++) {
49                                 let node = this.nodes[x][y] = this.element.appendChild(document.createElement("div"));
50                                 node.style.position = "absolute";
51                                 node.style.top = y * this.scale + "px";
52                                 node.style.left = x * this.scale + "px";
53                                 node.style.width = this.scale + "px";
54                                 node.style.height = this.scale + "px";
55                         }
56                 }
57         }
58
59         setActive()
60         {
61                 let self = this;
62
63                 this.interval = setInterval(_ => {
64                         self.autoScroll();
65                 });
66
67                 this.element.style.visibility = "visible";
68         }
69
70         setInactive()
71         {
72                 if (this.interval) {
73                         clearInterval(this.interval);
74                         delete this.interval;
75                 }
76
77                 this.map = null;
78                 this.anchor = null;
79
80                 this.element.style.visibility = "hidden";
81         }
82
83         setMap(map)
84         {
85                 if (this.map)
86                         this.map.setInactive();
87
88                 this.map = map;
89                 this.map.setActive();
90
91                 this.setSky(this.map.sky);
92
93                 this.autoScroll() || this.update();
94         }
95
96         setAnchor(anchor)
97         {
98                 this.anchor = anchor;
99                 this.autoScroll();
100         }
101
102         setSky(sky)
103         {
104                 this.element.style.background = sky;
105         }
106
107         getActiveEntityContainer()
108         {
109                 return this.entityContainers[this.map];
110         }
111
112         isInitialized()
113         {
114                 return this.map && this.anchor;
115         }
116
117         withinBounds(x, y)
118         {
119                 return x < this.width && y < this.height && x >= 0 && y >= 0;
120         }
121
122         getNode(x, y)
123         {
124                 return this.withinBounds(x, y) && this.nodes[x][y];
125         }
126
127         updateNode(x, y)
128         {
129                 if (! this.isInitialized())
130                         return;
131
132                 let node = this.getNode(x - this.left, y - this.top);
133
134                 if (! node)
135                         return;
136
137                 let mapNodeDef = this.map.getNode(x, y).toNode();
138
139                 if (mapNodeDef) {
140                         node.style.background = dragonblocks.getTexture(mapNodeDef.texture);
141                         node.style.zIndex = mapNodeDef.zIndex || "1";
142                 } else {
143                         node.style.background = "black";
144                 }
145         }
146
147         autoScroll()
148         {
149                 if (! this.isInitialized())
150                         return;
151
152                 let oldLeft, oldTop;
153                 oldLeft = this.left;
154                 oldTop = this.top;
155
156                 if (this.map.width >= this.width)
157                         this.left = parseInt(Math.max(Math.min(this.left, this.map.width - this.width, this.anchor.x - 3), 0, this.anchor.x + this.anchor.width + 3 - this.width));
158                 else
159                         this.left = parseInt((this.width - this.map.width) / 2);
160
161                 if (this.map.width >= this.width)
162                         this.top = parseInt(Math.max(Math.min(this.top, this.map.height - this.height, this.anchor.y - 3), 0, this.anchor.y + this.anchor.height + 3 - this.height));
163                 else
164                         this.top = parseInt((this.height - this.map.height) / 2);
165
166                 let changed = oldLeft != this.left || oldTop != this.top;
167
168                 if (changed)
169                         this.update();
170
171                 return changed;
172         }
173
174         update()
175         {
176                 if (! this.isInitialized())
177                         return;
178
179                 this.map.entityContainer.style.left = -this.left * this.scale + "px";
180                 this.map.entityContainer.style.top = -this.top * this.scale + "px";
181
182                 for (let x = 0; x < this.width; x++)
183                         for(let y = 0; y < this.height; y++)
184                                 this.updateNode(x + this.left, y + this.top);
185         }
186 };
187
188 dragonblocks.mapDisplay = new dragonblocks.MapDisplay();
189
190 dragonblocks.registerOnQuit(_ => {
191         dragonblocks.mapDisplay.setInactive();
192 });
193
194 dragonblocks.registerOnStarted(_ => {
195         dragonblocks.mapDisplay.setAnchor(dragonblocks.player);
196         dragonblocks.mapDisplay.setMap(dragonblocks.player.map);
197
198         dragonblocks.mapDisplay.setActive();
199 });