@@ -53,8 +53,6 @@ class Entity extends EventEmitter {
53
53
static object_name :string = 'oUnknownEntity' ;
54
54
type : string ;
55
55
object_name : string ;
56
- // type = Entity.type;
57
- // object_name = Entity.object_name;
58
56
59
57
is_solid = false ;
60
58
is_static = false ;
@@ -63,12 +61,14 @@ class Entity extends EventEmitter {
63
61
pos :Point ; // keep in mind that the coordinates are always set to a whole number (to achieve pixel-perfect collisions)
64
62
spd :Point ; // speed in pixels per second, can be fractional
65
63
angle :number = 0 ;
64
+ origin :Point = { x : 0 , y : 0 } ; // origin from 0 (top/left) to 1 (bottom/right)
66
65
67
66
prev_pos :Point ;
68
67
serialized :SerializedEntity ; // save the last serialized version of this entity (to compare changes)
69
68
70
69
base_size :Point = { x : 64 , y : 64 } ;
71
70
scale :Point = { x : 1 , y : 1 } ;
71
+ flip :Point = { x : 0 , y : 0 } ;
72
72
73
73
74
74
// the custom variables that need sending with the entitiy
@@ -84,6 +84,7 @@ class Entity extends EventEmitter {
84
84
85
85
collider :Collider = null ; // a polygon or a circle
86
86
collider_type :ColliderType | string = 'box' ;
87
+ collider_origin :Point = { x : 0 , y : 0 } ;
87
88
collider_radius :number = this . width / 2 ; // only relevant when collider_type is 'circle'
88
89
collider_vertices :Point [ ] = [ ] ; // if this is not overridden, a default rectangle collider will be used
89
90
@@ -112,7 +113,7 @@ class Entity extends EventEmitter {
112
113
if ( typeof value === 'string' ) {
113
114
this . _state = this . states [ value ] ;
114
115
}
115
- // it's a number
116
+ // state is a number
116
117
// (-1 means keep the old state)
117
118
else if ( value != - 1 ) {
118
119
this . _state = value ;
@@ -133,14 +134,13 @@ class Entity extends EventEmitter {
133
134
this . id = crypto . randomUUID ( ) ;
134
135
this . room = room ;
135
136
this . pos = { x, y } ;
136
- this . spd = { x : 0 , y : 0 } ;
137
+ this . spd = { x : 0 , y : 0 } ;
137
138
this . prev_pos = { x, y } ;
138
139
139
140
this . type = this . constructor [ 'type' ] ;
140
141
this . object_name = this . constructor [ 'object_name' ] ;
141
142
142
143
this . createCollider ( ) ;
143
- this . collider . entity = this ;
144
144
145
145
this . tree . insert ( this . collider ) ;
146
146
}
@@ -194,12 +194,15 @@ class Entity extends EventEmitter {
194
194
}
195
195
196
196
public createCollider ( x = this . x , y = this . y ) {
197
- let pos = { x : x , y : y } ;
197
+ let pos = {
198
+ x : x + this . width * ( this . collider_origin . x - this . origin . x ) ,
199
+ y : y + this . height * ( this . collider_origin . y - this . origin . y )
200
+ } ;
198
201
199
202
// create the collider
200
203
switch ( this . collider_type ) {
201
204
case 'box' :
202
- this . collider = new BoxCollider ( pos , this . width - .01 , this . height - .01 ) ;
205
+ this . collider = new BoxCollider ( pos , this . base_size . x - .01 , this . base_size . y - .01 ) ;
203
206
break ;
204
207
case 'circle' :
205
208
this . collider = new CircleCollider ( pos , this . collider_radius ) ;
@@ -212,6 +215,10 @@ class Entity extends EventEmitter {
212
215
throw 'Unknown collider type: ' + this . collider_type ;
213
216
}
214
217
218
+ this . collider . setScale ( this . xscale , this . yscale ) ;
219
+ this . collider . setAngle ( this . angle ) ;
220
+ // this.tree.updateBody(this.collider);
221
+
215
222
this . collider . entity = this ;
216
223
}
217
224
@@ -224,46 +231,72 @@ class Entity extends EventEmitter {
224
231
this . tree . insert ( this . collider ) ;
225
232
}
226
233
227
- protected updateCollider ( x = this . x , y = this . y ) {
228
- if ( this . size . x != this . prev_size . x || this . size . y != this . prev_size . y ) {
229
- this . regenerateCollider ( x , y ) ;
234
+ protected updateCollider ( x = this . x , y = this . y , collider = this . collider ) {
235
+ let pos = {
236
+ x : x + this . width * ( this . collider_origin . x - this . origin . x ) ,
237
+ y : y + this . height * ( this . collider_origin . y - this . origin . y )
238
+ } ;
239
+
240
+ if ( collider === this . collider ) {
241
+ collider . setScale ( this . xscale , this . yscale ) ;
242
+ collider . setAngle ( this . angle ) ;
243
+ collider . setPosition ( pos . x , pos . y ) ;
244
+ }
245
+ else {
246
+ collider . setPosition ( x , y ) ;
230
247
}
231
248
232
- this . collider . setAngle ( this . angle ) ;
233
- this . collider . setPosition ( x , y ) ;
234
- this . tree . updateBody ( this . collider ) ;
249
+ this . tree . updateBody ( collider ) ;
235
250
}
236
251
237
- public checkCollision ( x : number = this . x , y : number = this . y , e :Entity ) :boolean {
238
- this . updateCollider ( x , y ) ;
239
- return this . tree . checkCollision ( this . collider , e . collider ) ;
252
+ public checkCollision ( x : number = this . x , y : number = this . y , e :Entity , collider = this . collider ) :boolean {
253
+ this . updateCollider ( x , y , collider ) ;
254
+
255
+ let result = this . tree . checkCollision ( collider , e . collider ) ;
256
+
257
+ // move back the collider
258
+ if ( collider === this . collider )
259
+ this . updateCollider ( this . x , this . y ) ;
260
+
261
+ return result ;
240
262
}
241
263
242
- public placeMeeting ( x :number = this . x , y :number = this . y , type :EntityType | string = 'solid' ) :boolean {
243
- this . updateCollider ( x , y ) ;
264
+ public placeMeeting ( x :number = this . x , y :number = this . y , type :EntityType | string = 'solid' , collider = this . collider ) :boolean {
265
+ this . updateCollider ( x , y , collider ) ;
244
266
245
267
this . prev_size = { x : this . size . x , y : this . size . y }
246
268
247
- return this . tree . checkOne ( this . collider , ( res ) => {
269
+ let result = this . tree . checkOne ( this . collider , ( res ) => {
248
270
let e = res . b . entity ;
249
- return e . matchesType ( type ) ;
271
+ return e && e . matchesType ( type ) ;
250
272
} ) ;
273
+
274
+ // move back the collider
275
+ if ( collider === this . collider )
276
+ this . updateCollider ( this . x , this . y ) ;
277
+
278
+ return result ;
251
279
}
252
280
253
- public placeMeetingAll < T = Entity > ( x :number = this . x , y :number = this . y , type :EntityType | string = 'solid' ) :T [ ] {
254
- this . updateCollider ( x , y ) ;
281
+ public placeMeetingAll < T = Entity > ( x :number = this . x , y :number = this . y , type :EntityType | string = 'solid' , collider = this . collider ) :T [ ] {
282
+ this . updateCollider ( x , y , collider ) ;
255
283
256
284
let entities = [ ] ;
257
- this . tree . checkOne ( this . collider , ( res ) => {
285
+ this . tree . checkOne ( collider , ( res ) => {
258
286
let e = res . b . entity ;
259
- if ( e . matchesType ( type ) )
287
+ if ( e && e . matchesType ( type ) )
260
288
entities . push ( e ) ;
261
289
} ) ;
290
+
291
+ // move back the collider
292
+ if ( collider === this . collider )
293
+ this . updateCollider ( this . x , this . y ) ;
294
+
262
295
return entities ;
263
296
}
264
297
265
298
isOutsideRoom ( x = this . x , y = this . y ) :boolean {
266
- let bbox = this . bbox ; // this is an optimization btw
299
+ let bbox = this . bbox ; // don't call the getter every time
267
300
268
301
return bbox . left - this . x + x > this . room . width
269
302
|| bbox . right - this . x + x < 0
@@ -301,8 +334,11 @@ class Entity extends EventEmitter {
301
334
302
335
// removes the entity from the room (and triggers the 'remove' event)
303
336
public remove ( ) {
304
- this . emit ( 'remove' ) ;
305
337
let idx = this . room . entities . indexOf ( this ) ;
338
+ if ( idx === - 1 ) { // already removed
339
+ return ;
340
+ }
341
+ this . emit ( 'remove' ) ;
306
342
this . room . entities . splice ( idx , 1 ) ;
307
343
this . tree . remove ( this . collider ) ;
308
344
}
@@ -343,11 +379,14 @@ class Entity extends EventEmitter {
343
379
let x :number = this . x , y :number = this . y ;
344
380
let w :number = this . width , h :number = this . height ;
345
381
382
+ let ox = this . origin . x ;
383
+ let oy = this . origin . y ;
384
+
346
385
return {
347
- left : x ,
348
- top : y ,
349
- right : x + w ,
350
- bottom : y + h
386
+ left : x - w * ox ,
387
+ top : y - h * oy ,
388
+ right : x + w * ( 1 - ox ) ,
389
+ bottom : y + h * ( 1 - oy )
351
390
}
352
391
}
353
392
0 commit comments