]> git.lizzy.rs Git - dragonblocks.git/blob - engine/spawned_entity.js
2f08e97896f98bbb202e4a273d3ba7e1a4102d97
[dragonblocks.git] / engine / spawned_entity.js
1 /*
2  * spawned_entity.js
3  * 
4  * Copyright 2020 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 dragonblocks.SpawnedEntity = class {
24         constructor(entity, x, y){
25                 dblib.copy(this, entity);
26                 if(entity instanceof dragonblocks.Entity){
27                         this.id = dragonblocks.getToken();
28                         this.jumping = this.movingRight = this.movingLeft = this.movingUp = this.movingDown = false;
29                         this.x = x;
30                         this.y = y;
31                         this.ax = 0;
32                         this.ay = 0;
33                         this.physicsResetX();
34                         this.physicsResetY();
35                         this.meta = this.meta || {};
36                         this.toEntity().oninit && this.toEntity().oninit(this);
37                 }
38                 this.physicsRecover();
39                 this.tmp = {};
40                 this.addGraphics();
41                 let self = this;
42                 this.tickInterval = setInterval(_ => {self.tick()}, 100);
43                 this.physicInterval = setInterval(_=>{self.physics()});
44                 this.toEntity().onspawn && this.toEntity().onspawn(this);
45                 addEventListener("focus", _ => { self.physicsRecover(); });
46                 addEventListener("blur", _ => { self.physicsRecover(); });
47                 dragonblocks.spawnedEntities.push(this);
48         }
49         toEntity(){
50                 return dragonblocks.entities[this.name];
51         }
52         despawn(){
53                 this.toEntity().ondespawn && this.toEntity().ondespawn(this);
54                 let id = this.id;
55                 dragonblocks.spawnedEntities = dragonblocks.spawnedEntities.filter(entity => {return entity.id != id});
56                 clearInterval(this.physicInterval);
57                 clearInterval(this.tickInterval);
58                 dblib.remove(document.getElementById("dragonblocks.entity[" + this.id + "]"));
59         }
60         physicsRecover(){
61                 this.tx0 = new Date().getTime() / 1000;
62                 this.ty0 = new Date().getTime() / 1000;
63                 this.x0 = this.x;
64                 this.y0 = this.y;
65         }
66         physicsCheckX(){
67                 if(this.x < 0)
68                         return false;
69                 if(this.x + this.width > dragonblocks.map.width)
70                         return false;
71                 return this.physicsCheckBoth();
72         }
73         physicsCheckY(){
74                 if(this.y < 0)
75                         return false;
76                 if(this.y + this.height > dragonblocks.map.height)
77                         return false;
78                 return this.physicsCheckBoth();
79         }
80         physicsCheckBoth(){
81                 for(let ix = Math.floor(this.x); ix <= Math.ceil(this.x + this.width - 0.01) - 1; ix++)
82                         for(let iy = Math.floor(this.y); iy <= Math.ceil(this.y + this.height - 0.01) - 1; iy++)
83                                 if(dragonblocks.getNode(ix, iy).mobstable)
84                                         return false;
85                 return true;
86         }
87         physicsResetX(){
88                 this.tx0 = new Date().getTime() / 1000;
89                 this.vx = 0;
90                 this.x0 = this.x;
91                 this.x = Math.round(this.x * 10) / 10;
92         }
93         physicsResetY(){
94                 this.ty0 = new Date().getTime() / 1000;
95                 this.vy = 0;
96                 this.y0 = this.y;
97                 this.y = Math.round(this.y * 10) / 10;
98         }
99         physics(){
100                 let t = new Date().getTime() / 1000;
101                 var oldX = this.x;
102                 var dtx = t - this.tx0;
103                 if(this.ax)
104                         this.x = this.ax * dtx * dtx + this.vx * dtx + this.x0;
105                 else if(this.vx)
106                         this.x = this.vx * dtx + this.x0;
107                 if(! this.physicsCheckX())
108                 {
109                         this.x = oldX;
110                         this.physicsResetX();
111                         this.toEntity().oncollide && this.toEntity().oncollide(this);
112                 }
113                 var oldY = this.y;
114                 var dty = t - this.ty0;
115                 if(this.ay)
116                         this.y = this.ay * dty * dty + this.vy * dty + this.y0;
117                 else if(this.vy)
118                         this.y = this.vy * dty + this.y0;
119                 if(! this.physicsCheckY())
120                 {
121                         this.y = oldY;
122                         this.physicsResetY();
123                         this.toEntity().oncollide && this.toEntity().oncollide(this);
124                 }
125                 this.y = Math.round(this.y * 50) / 50;
126                 this.updateGraphics();
127         }
128         touch(x, y){
129                 for(let ix = Math.floor(this.x); ix <= Math.ceil(this.x + this.width - 0.01) - 1; ix++)
130                         for(let iy = Math.floor(this.y); iy <= Math.ceil(this.y + this.height - 0.01) - 1; iy++)
131                                 if(iy == y && ix == x)
132                                         return true;
133         }
134         addGraphics(obj){
135                 var display = document.createElement("div");
136                 display.id = "dragonblocks.entity[" + this.id + "]";
137                 display.style.position = "absolute";
138                 display.style.width = this.width * dragonblocks.settings.map.scale + "px";
139                 display.style.height = this.height * dragonblocks.settings.map.scale + "px";
140                 display.style.zIndex = "0";
141                 let self = this;
142                 display.addEventListener("mouseover", event => {
143                         event.srcElement.style.boxShadow = "0 0 0 1px black inset";
144                 });
145                 display.addEventListener("mouseleave", event => {
146                         event.srcElement.style.boxShadow = "none";
147                 });
148                 display.addEventListener("mousedown", event => {
149                         switch(event.which){
150                                 case 1:
151                                         self.toEntity().onpunch && self.toEntity().onpunch(self);
152                                         break;
153                                 case 3:
154                                         self.toEntity().onclick && self.toEntity().onclick(self);
155                                         break;
156                         }
157                 });
158                 document.getElementById("dragonblocks.map").appendChild(display);
159                 this.updateTexture();
160                 this.updateGraphics();
161         }
162         async updateGraphics(){
163                 let display = document.getElementById("dragonblocks.entity[" + this.id + "]");
164                 if(! display)
165                         return;
166                 display.style.left = (this.x - dragonblocks.map.displayLeft) * dragonblocks.settings.map.scale + "px";
167                 display.style.top = (this.y - dragonblocks.map.displayTop) * dragonblocks.settings.map.scale + "px";
168         }
169         updateTexture(){
170                 let display = document.getElementById("dragonblocks.entity[" + this.id + "]");
171                 display.style.background = dragonblocks.getTexture(this.texture);
172                 display.style.backgroundSize = "cover";
173         }
174         teleport(x, y){
175                 this.physicsResetX();
176                 this.physicsResetY();
177                 this.x = x;
178                 this.y = y;
179         }
180         moveLeft(){
181                 if(this.vx == -this.horizontalSpeed)
182                         return;
183                 if(this.movingRight)
184                         this.movingRight = false;
185                 this.movingLeft = true;
186                 this.physicsResetX();
187                 this.vx = -this.horizontalSpeed;
188         }
189         moveRight(){
190                 if(this.vx == this.horizontalSpeed)
191                         return;
192                 if(this.movingLeft)
193                         this.movingLeft = false;
194                 this.movingRight = true;
195                 this.physicsResetX();
196                 this.vx = this.horizontalSpeed;
197         }
198         stop(){
199                 this.movingLeft = false;
200                 this.movingRight = false;
201                 this.physicsResetX();
202         }
203         moveDown(){
204                 if(this.vy == this.verticalSpeed)
205                         return;
206                 if(this.movingDown)
207                         this.movingDown = false;
208                 this.movingDown = true;
209                 this.physicsResetY();
210                 this.vy = this.verticalSpeed;
211         }
212         moveUp(){
213                 if(this.vy == -this.verticalSpeed)
214                         return;
215                 if(this.movingUp)
216                         this.movingUp = false;
217                 this.movingUp = true;
218                 this.physicsResetY();
219                 this.vy = -this.verticalSpeed;
220         }
221         stopFly(){
222                 this.movingUp = false;
223                 this.movingDown = false;
224                 this.physicsResetY();
225         }
226         jump(){
227                 if(this.vy == -this.verticalSpeed)
228                         return;
229                 this.jumping = true;
230                 this.vy = -this.verticalSpeed;
231         }
232         stopJump(){
233                 this.jumping = false;
234         }
235         jumpOnce(){
236                 this.vy = -this.verticalSpeed;
237         }
238         set gravity(value){
239                 this._gravity = value;
240                 if(this._gravity)
241                         this.ay = dragonblocks.settings.physics.gravity;
242                 else
243                         this.ay = 0;
244         }
245         get gravity(){
246                 return this._gravity;
247         }
248         tick(){
249                 if(this.movingLeft)
250                         this.moveLeft();
251                 if(this.movingRight)
252                         this.moveRight();
253                 if(this.movingUp)
254                         this.moveUp();
255                 if(this.movingDown)
256                         this.moveDown();
257                 if(this.jumping)
258                         this.jump();
259                 if(this.gravity)
260                         this.gravity = true;
261         }
262 }
263 dragonblocks.spawnedEntities = [];
264 dragonblocks.registerOnStarted(_ => {
265         if(dragonblocks.worldIsLoaded)
266                 for(let entity of dragonblocks.world.spawnedEntities)
267                         new dragonblocks.SpawnedEntity(entity);
268 });