1
- import timer from "./../system/timer.ts" ;
2
- import { randomFloat , clamp } from "./../math/math.ts" ;
3
- import Renderable from "./../renderable/renderable.js" ;
4
- import { vector2dPool } from "../math/vector2d.ts" ;
1
+ import timer from "../system/timer.ts" ;
2
+ import { randomFloat , clamp } from "../math/math.ts" ;
3
+ import Renderable from "../renderable/renderable.js" ;
4
+ import { Vector2d , vector2dPool } from "../math/vector2d.ts" ;
5
+ import { createPool } from "../pool.ts" ;
6
+ import ParticleEmitter from "./emitter.js" ;
7
+ import CanvasRenderer from "../video/canvas/canvas_renderer.js" ;
8
+ import WebGLRenderer from "../video/webgl/webgl_renderer.js" ;
9
+ import Container from "../renderable/container.js" ;
5
10
6
11
/**
7
12
* @import ParticleEmitter from "./emitter.js";
@@ -11,31 +16,44 @@ import { vector2dPool } from "../math/vector2d.ts";
11
16
* Single Particle Object.
12
17
*/
13
18
export default class Particle extends Renderable {
19
+ vel : Vector2d ;
20
+ image : any ;
21
+ life : number ;
22
+ startLife : number ;
23
+ startScale : number ;
24
+ endScale : number ;
25
+ gravity : number ;
26
+ wind : number ;
27
+ followTrajectory : boolean ;
28
+ onlyInViewport : boolean ;
29
+ _deltaInv : number ;
30
+ _angle : number ;
31
+ alive : boolean ;
32
+
14
33
/**
15
- * @param { ParticleEmitter } emitter - the particle emitter
34
+ * @param emitter - the particle emitter
16
35
*/
17
- constructor ( emitter ) {
36
+ constructor ( emitter : ParticleEmitter ) {
18
37
// Call the super constructor
19
38
super (
20
39
emitter . getRandomPointX ( ) ,
21
40
emitter . getRandomPointY ( ) ,
22
41
emitter . settings . image . width ,
23
42
emitter . settings . image . height ,
24
43
) ;
44
+ // particle velocity
45
+ this . vel = vector2dPool . get ( ) ;
25
46
this . onResetEvent ( emitter , true ) ;
26
47
}
27
48
28
49
/**
29
50
* @ignore
30
51
*/
31
- onResetEvent ( emitter , newInstance = false ) {
32
- if ( newInstance === false ) {
52
+ onResetEvent ( emitter : ParticleEmitter , newInstance : boolean = false ) {
53
+ if ( ! newInstance ) {
33
54
this . pos . set ( emitter . getRandomPointX ( ) , emitter . getRandomPointY ( ) ) ;
34
55
this . resize ( emitter . settings . image . width , emitter . settings . image . height ) ;
35
56
this . currentTransform . identity ( ) ;
36
- } else {
37
- // particle velocity
38
- this . vel = vector2dPool . get ( ) ;
39
57
}
40
58
41
59
this . image = emitter . settings . image ;
@@ -44,12 +62,10 @@ export default class Particle extends Renderable {
44
62
this . alwaysUpdate = true ;
45
63
46
64
if ( typeof emitter . settings . tint === "string" ) {
47
- this . tint . parseCSS ( emitter . settings . tint ) ;
65
+ this . tint . parseCSS ( emitter . settings . tint as any ) ;
48
66
}
49
67
50
- if ( emitter . settings . textureAdditive === true ) {
51
- this . blendMode = "additive" ;
52
- }
68
+ this . blendMode = emitter . settings . textureAdditive ? "additive" : "normal" ;
53
69
54
70
if ( emitter . settings . blendMode !== "normal" ) {
55
71
this . blendMode = emitter . settings . blendMode ;
@@ -106,28 +122,34 @@ export default class Particle extends Renderable {
106
122
// Set the start particle rotation as defined in emitter
107
123
// if the particle not follow trajectory
108
124
if ( ! emitter . settings . followTrajectory ) {
109
- this . angle = randomFloat (
125
+ this . _angle = randomFloat (
110
126
emitter . settings . minRotation ,
111
127
emitter . settings . maxRotation ,
112
128
) ;
113
129
}
130
+
131
+ this . alive = true ;
114
132
}
115
133
116
134
/**
117
135
* Update the Particle <br>
118
136
* This is automatically called by the game manager {@link game}
119
137
* @ignore
120
- * @param { number } dt - time since the last update in milliseconds
138
+ * @param dt - time since the last update in milliseconds
121
139
*/
122
- update ( dt ) {
140
+ override update ( dt : number ) {
123
141
// move things forward independent of the current frame rate
124
142
const skew = dt * this . _deltaInv ;
125
143
126
144
// Decrease particle life
127
145
this . life = this . life > dt ? this . life - dt : 0 ;
128
146
129
- if ( this . life <= 0 ) {
130
- this . ancestor . removeChild ( this ) ;
147
+ if ( this . alive && this . life <= 0 ) {
148
+ const parent = this . ancestor as Container ;
149
+ // use true for keepalive since we recycle the instance directly here after
150
+ parent . removeChild ( this , true ) ;
151
+ particlePool . release ( this ) ;
152
+ this . alive = false ;
131
153
return false ;
132
154
}
133
155
@@ -154,7 +176,7 @@ export default class Particle extends Renderable {
154
176
// If necessary update the rotation of particle in accordance the particle trajectory
155
177
const angle = this . followTrajectory
156
178
? Math . atan2 ( this . vel . y , this . vel . x )
157
- : this . angle ;
179
+ : this . _angle ;
158
180
159
181
this . pos . x += this . vel . x * skew ;
160
182
this . pos . y += this . vel . y * skew ;
@@ -173,9 +195,22 @@ export default class Particle extends Renderable {
173
195
/**
174
196
* @ignore
175
197
*/
176
- draw ( renderer ) {
198
+ override draw ( renderer : CanvasRenderer | WebGLRenderer ) {
177
199
const w = this . width ;
178
200
const h = this . height ;
179
201
renderer . drawImage ( this . image , 0 , 0 , w , h , - w / 2 , - h / 2 , w , h ) ;
180
202
}
181
203
}
204
+
205
+ export const particlePool = createPool < Particle , [ emitter : ParticleEmitter ] > (
206
+ ( emitter ) => {
207
+ const instance = new Particle ( emitter ) ;
208
+
209
+ return {
210
+ instance,
211
+ reset ( emitter ) {
212
+ instance . onResetEvent ( emitter , false ) ;
213
+ } ,
214
+ } ;
215
+ } ,
216
+ ) ;
0 commit comments