4 * Copyright 2020 Elias Fleckenstein <eliasfleckenstein@web.de>
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.
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.
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,
24 dragonblocks.SpawnedEntity = class
26 constructor(def, map, x, y)
28 dblib.copy(this, def);
31 if (def instanceof dragonblocks.Entity) {
32 this.jumping = this.movingRight = this.movingLeft = this.movingUp = this.movingDown = false;
39 this.meta = this.meta || {};
40 this.toEntity().oninit && this.toEntity().oninit(this);
43 this.restorePhysics();
48 this.tickInterval = setInterval(_ => {
52 this.physicInterval = setInterval(_=>{
56 let entityDef = this.toEntity();
57 entityDef.onspawn && entityDef.onspawn(this);
59 addEventListener("focus", _ => {
60 self.restorePhysics();
63 addEventListener("blur", _ => {
64 self.restorePhysics();
67 map.entities.push(this);
72 return dragonblocks.entities[this.name];
78 this.map.entities = this.map.entities.filter(entity => {
79 return entity != self;
86 map.entities.push(this);
89 this.tmp.display = map.entityContainer.appendChild(this.tmp.display);
96 let entityDef = this.toEntity();
97 entityDef.ondespawn && entityDef.ondespawn(this);
101 clearInterval(this.physicInterval);
102 clearInterval(this.tickInterval);
104 this.tmp.display && this.tmp.display.remove();
109 this.tx0 = new Date().getTime() / 1000;
110 this.ty0 = new Date().getTime() / 1000;
120 if (this.x + this.width > this.map.width)
123 return this.collision();
131 if (this.y + this.height > this.map.height)
134 return this.collision();
139 for (let ix = Math.floor(this.x); ix <= Math.ceil(this.x + this.width - 0.01) - 1; ix++)
140 for (let iy = Math.floor(this.y); iy <= Math.ceil(this.y + this.height - 0.01) - 1; iy++)
141 if (this.map.getNode(ix, iy).mobstable)
148 this.tx0 = new Date().getTime() / 1000;
151 this.x = Math.round(this.x * 10) / 10;
156 this.ty0 = new Date().getTime() / 1000;
159 this.y = Math.round(this.y * 10) / 10;
164 let t = new Date().getTime() / 1000;
167 let dtx = t - this.tx0;
170 this.x = this.ax * dtx * dtx + this.vx * dtx + this.x0;
172 this.x = this.vx * dtx + this.x0;
174 if (! this.collisionX()) {
176 this.physicsResetX();
177 this.toEntity().oncollide && this.toEntity().oncollide(this);
181 let dty = t - this.ty0;
184 this.y = this.ay * dty * dty + this.vy * dty + this.y0;
186 this.y = this.vy * dty + this.y0;
188 if (! this.collisionY()) {
190 this.physicsResetY();
191 this.toEntity().oncollide && this.toEntity().oncollide(this);
194 this.y = Math.round(this.y * 50) / 50;
196 this.updateGraphics();
203 for (let ix = Math.floor(this.x); ix <= Math.ceil(this.x + this.width - 0.01) - 1; ix++)
204 for (let iy = Math.floor(this.y); iy <= Math.ceil(this.y + this.height - 0.01) - 1; iy++)
205 if (iy == y && ix == x)
211 this.tmp.display = this.map.entityContainer.appendChild(document.createElement("div"));
212 this.tmp.display.style.position = "absolute";
213 this.tmp.display.style.width = this.width * dragonblocks.settings.mapDisplay.scale + "px";
214 this.tmp.display.style.height = this.height * dragonblocks.settings.mapDisplay.scale + "px";
215 this.tmp.display.style.zIndex = "0";
217 this.tmp.display.addEventListener("mouseover", event => {
218 event.srcElement.style.boxShadow = "0 0 0 1px black inset";
221 this.tmp.display.addEventListener("mouseleave", event => {
222 event.srcElement.style.boxShadow = "none";
227 this.tmp.display.addEventListener("mousedown", event => {
228 let entityDef = self.toEntity();
230 switch (event.which) {
232 entityDef.onpunch && entityDef.onpunch(self);
236 entityDef.onclick && entityDef.onclick(self);
241 this.updateTexture();
242 this.updateGraphics();
245 async updateGraphics()
247 if (! this.tmp.display)
250 this.tmp.display.style.left = this.x * dragonblocks.settings.mapDisplay.scale + "px";
251 this.tmp.display.style.top = this.y * dragonblocks.settings.mapDisplay.scale + "px";
256 this.tmp.display.style.background = dragonblocks.getTexture(this.texture);
261 this.physicsResetX();
262 this.physicsResetY();
269 if (this.vx == -this.horizontalSpeed)
272 if (this.movingRight)
273 this.movingRight = false;
275 this.movingLeft = true;
276 this.physicsResetX();
277 this.vx = -this.horizontalSpeed;
282 if (this.vx == this.horizontalSpeed)
286 this.movingLeft = false;
288 this.movingRight = true;
289 this.physicsResetX();
290 this.vx = this.horizontalSpeed;
295 this.movingLeft = false;
296 this.movingRight = false;
297 this.physicsResetX();
302 if (this.vy == this.verticalSpeed)
306 this.movingDown = false;
308 this.movingDown = true;
309 this.physicsResetY();
310 this.vy = this.verticalSpeed;
315 if (this.vy == -this.verticalSpeed)
319 this.movingUp = false;
321 this.movingUp = true;
322 this.physicsResetY();
323 this.vy = -this.verticalSpeed;
328 this.movingUp = false;
329 this.movingDown = false;
330 this.physicsResetY();
335 for (let x = Math.floor(this.x); x <= Math.ceil(this.x + this.width - 0.01) - 1; x++) {
336 let entityY = this.y + this.height;
337 let y = Math.ceil(entityY);
339 if (y - entityY <= 0.01) {
340 let node = this.map.getNode(x, y);
342 if (! node || node.mobstable)
350 if (! this.canJump())
354 this.vy = -this.verticalSpeed;
359 this.jumping = false;
364 this.vy = -this.verticalSpeed;
369 this._gravity = value;
372 this.ay = dragonblocks.settings.physics.gravity;
379 return this._gravity;
386 if (this.movingRight)