-
-
Notifications
You must be signed in to change notification settings - Fork 644
/
Copy pathparticle.js
163 lines (133 loc) · 5.77 KB
/
particle.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
* MelonJS Game Engine
* Copyright (C) 2011 - 2014, Olivier BIOT
* http://www.melonjs.org
*
*/
(function () {
/**
* Single Particle Object.
* @class
* @extends me.Renderable
* @memberOf me
* @constructor
* @param {me.ParticleEmitter} particle emitter
*/
me.Particle = me.Renderable.extend(
/** @scope me.Particle.prototype */
{
/**
* @ignore
*/
init : function (emitter) {
// Call the super constructor
var point = emitter.getRandomPoint();
this._super(me.Renderable, "init", [point.x, point.y, emitter.image.width, emitter.image.height]);
// Particle will always update
this.alwaysUpdate = true;
// Particle will not act as a rednerable
// FIXME: This is probably not needed. It's a hack that tries to
// workaround performance issues within container.
this.isRenderable = false;
// Cache the image reference
this.image = emitter.image;
// Set the start particle Angle and Speed as defined in emitter
var angle = emitter.angle + ((emitter.angleVariation > 0) ? (-1).random(2) * emitter.angleVariation : 0);
var speed = emitter.speed + ((emitter.speedVariation > 0) ? (-1).random(2) * emitter.speedVariation : 0);
// Set the start particle Velocity
this.vel = new me.Vector2d(speed * Math.cos(angle), -speed * Math.sin(angle));
// Set the start particle Time of Life as defined in emitter
this.life = emitter.minLife.random(emitter.maxLife);
this.startLife = this.life;
// Set the start and end particle Scale as defined in emitter
// clamp the values as minimum and maximum scales range
this.startScale = emitter.minStartScale.randomFloat(
emitter.maxStartScale
).clamp(emitter.minStartScale, emitter.maxStartScale);
this.endScale = emitter.minEndScale.randomFloat(
emitter.maxEndScale
).clamp(emitter.minEndScale, emitter.maxEndScale);
// Set the particle Gravity and Wind (horizontal gravity) as defined in emitter
this.gravity = emitter.gravity;
this.wind = emitter.wind;
// Set if the particle update the rotation in accordance the trajectory
this.followTrajectory = emitter.followTrajectory;
// Set if the particle update only in Viewport
this.onlyInViewport = emitter.onlyInViewport;
// Set the particle Z Order
this.z = emitter.z;
// cache inverse of the expected delta time
this._deltaInv = me.sys.fps / 1000;
this.transform = new me.Matrix2d();
// Set the start particle rotation as defined in emitter
// if the particle not follow trajectory
if (!emitter.followTrajectory) {
this.angle = emitter.minRotation.randomFloat(emitter.maxRotation);
}
},
/**
* Update the Particle <br>
* This is automatically called by the game manager {@link me.game}
* @name update
* @memberOf me.Particle
* @function
* @ignore
* @param {Number} dt time since the last update in milliseconds
*/
update : function (dt) {
// move things forward independent of the current frame rate
var skew = dt * this._deltaInv;
// Decrease particle life
this.life = this.life > dt ? this.life - dt : 0;
// Calculate the particle Age Ratio
var ageRatio = this.life / this.startLife;
// Resize the particle as particle Age Ratio
var scale = this.startScale;
if (this.startScale > this.endScale) {
scale *= ageRatio;
scale = (scale < this.endScale) ? this.endScale : scale;
}
else if (this.startScale < this.endScale) {
scale /= ageRatio;
scale = (scale > this.endScale) ? this.endScale : scale;
}
// Set the particle opacity as Age Ratio
this.alpha = ageRatio;
// Adjust the particle velocity
this.vel.x += this.wind * skew;
this.vel.y += this.gravity * skew;
// If necessary update the rotation of particle in accordance the particle trajectory
var angle = this.followTrajectory ? Math.atan2(this.vel.y, this.vel.x) : this.angle;
// Update particle transform
this.transform.set(scale, 0, 0, scale, 0, 0).rotate(angle);
this.pos.x += this.vel.x * skew;
this.pos.y += this.vel.y * skew;
// Return true if the particle is not dead yet
return (this.inViewport || !this.onlyInViewport) && (this.life > 0);
},
draw : function (renderer) {
renderer.save();
// particle alpha value
renderer.setGlobalAlpha(renderer.globalAlpha() * this.alpha);
// translate to the defined anchor point and scale it
var transform = this.transform.val;
renderer.transform(
transform[0], transform[1],
transform[2], transform[3],
~~this.pos.x, ~~this.pos.y
);
var w = this.width, h = this.height;
renderer.drawImage(
this.image,
0, 0,
w, h,
-w / 2, -h / 2,
w, h
);
renderer.restore();
}
});
/*---------------------------------------------------------*/
// END END END
/*---------------------------------------------------------*/
})(window);