1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2006 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "Particles.h"
23 #include "Interface.h"
26 Color sparkcolors
[MAX_SPARK_COLOR
][MAX_SPARK_PHASE
];
29 void TranslateColor(const char *value
, Color
&color
)
34 //if not RGB then try to interpret it as a dword
35 if (strnicmp(value
,"RGB(",4)) {
36 r
= strtol(value
,NULL
,0);
38 color
.g
= (r
>>8)&0xff;
39 color
.b
= (r
>>16)&0xff;
40 color
.a
= (r
>>24)&0xff;
42 sscanf(value
+4,"%d,%d,%d)", &r
, &g
, &b
);
51 AutoTable
tab("sprklclr");
55 memset(sparkcolors
,0,sizeof(sparkcolors
));
56 for (i
=0;i
<MAX_SPARK_COLOR
;i
++) {
57 for (j
=0;j
<MAX_SPARK_PHASE
;j
++) {
58 sparkcolors
[i
][j
].a
=0xff;
61 i
= tab
->GetRowCount();
62 if (i
>MAX_SPARK_COLOR
) {
66 for (int j
=0;j
<MAX_SPARK_PHASE
;j
++) {
67 //not filling the first entry
68 const char *value
= tab
->QueryField(i
,j
);
69 TranslateColor(value
, sparkcolors
[i
+1][j
]);
74 Particles::Particles(int s
)
76 points
= (Element
*) malloc(s
*sizeof(Element
) );
77 memset(points
, -1, s
*sizeof(Element
) );
79 for (int i=0;i<MAX_SPARK_PHASE;i++) {
87 size
= last_insert
= s
;
93 spawn_type
= SP_SPAWN_NONE
;
96 Particles::~Particles()
102 for (int i=0;i<MAX_SPARK_PHASE;i++) {
109 void Particles::SetBitmap(unsigned int FragAnimID
)
115 fragments
= new CharAnimations(FragAnimID
, 0);
117 for (i=0;i<MAX_SPARK_PHASE;i++) {
121 AnimationFactory* af = ( AnimationFactory* )
122 gamedata->GetFactoryResource( BAM, IE_BAM_CLASS_ID );
128 for (i=0;i<MAX_SPARK_PHASE; i++) {
129 bitmap[i] = af->GetCycle( i );
135 bool Particles::AddNew(const Point
&point
)
142 st
= (last_insert
%15)<<16;
146 st
= core
->Roll(3,5,MAX_SPARK_PHASE
)<<4;
149 st
=(MAX_SPARK_PHASE
+ 2*pos
.h
)<<4;
153 st
=(MAX_SPARK_PHASE
+ pos
.h
)<<4;
158 if (points
[i
].state
== -1) {
159 points
[i
].state
= st
;
160 points
[i
].pos
= point
;
166 while (i
--!=last_insert
) {
167 if (points
[i
].state
== -1) {
168 points
[i
].state
= st
;
169 points
[i
].pos
= point
;
177 void Particles::Draw(const Region
&screen
)
179 int length
; //used only for raindrops
181 Video
*video
=core
->GetVideoDriver();
182 Region region
= video
->GetViewport();
189 if (points
[i
].state
== -1) {
192 int state
= points
[i
].state
>>4;
193 if (state
>=MAX_SPARK_PHASE
) {
194 length
= 6-abs(state
-MAX_SPARK_PHASE
-6);
197 state
=MAX_SPARK_PHASE
-state
;
200 Color clr
= sparkcolors
[color
][state
];
205 Sprite2D *frame = bitmap[state]->GetFrame(points[i].state&255);
206 video->BlitGameSprite(frame,
207 points[i].pos.x+screen.x,
208 points[i].pos.y+screen.y, 0, clr,
209 NULL, NULL, &screen);
213 //IE_ANI_CAST stance has a simple looping animation
214 Animation
** anims
= fragments
->GetAnimation( IE_ANI_CAST
, i
);
216 Animation
* anim
= anims
[0];
217 Sprite2D
* nextFrame
= anim
->GetFrame(anim
->GetCurrentFrame());
218 video
->BlitGameSprite( nextFrame
, points
[i
].pos
.x
- region
.x
, points
[i
].pos
.y
- region
.y
,
219 0, clr
, NULL
, fragments
->GetPartPalette(0), &screen
);
224 video
->DrawCircle (points
[i
].pos
.x
-region
.x
,
225 points
[i
].pos
.y
-region
.y
, 2, clr
, true);
229 video
->SetPixel (points
[i
].pos
.x
-region
.x
,
230 points
[i
].pos
.y
-region
.y
, clr
, true);
232 case SP_TYPE_LINE
: // this is more like a raindrop
234 video
->DrawLine (points
[i
].pos
.x
+region
.x
,
235 points
[i
].pos
.y
+region
.y
,
236 points
[i
].pos
.x
+region
.x
+(i
&1),
237 points
[i
].pos
.y
+region
.y
+length
, clr
, true);
244 void Particles::AddParticles(int count
)
256 p
.x
= core
->Roll(1,pos
.w
,0);
257 p
.y
= core
->Roll(1,pos
.h
/2,0);
261 p
.x
= core
->Roll(1,pos
.w
,0);
262 p
.y
= core
->Roll(1,pos
.h
,0);
265 p
.x
= core
->Roll(1,pos
.w
/2,pos
.w
/4);
266 p
.y
= core
->Roll(1,pos
.h
/2,0);
275 int Particles::Update()
281 if (phase
==P_EMPTY
) {
291 spawn_type
=SP_SPAWN_NONE
;
297 for(i
=0;i
<size
;i
++) {
298 if (points
[i
].state
==-1) {
302 if (!points
[i
].state
) {
309 points
[i
].pos
.y
+=3+((i
>>2)&3);
310 points
[i
].pos
.y
%=pos
.h
;
313 points
[i
].pos
.x
+=pos
.w
+(i
&1);
314 points
[i
].pos
.x
%=pos
.w
;
315 points
[i
].pos
.y
+=3+((i
>>2)&3);
316 points
[i
].pos
.y
%=pos
.h
;
319 if (points
[i
].state
<=MAX_SPARK_PHASE
<<4) {
322 points
[i
].pos
.x
+=core
->Roll(1,3,pos
.w
-2);
323 points
[i
].pos
.x
%=pos
.w
;
324 points
[i
].pos
.y
+=(i
&3)+1;
327 if (points
[i
].state
<=MAX_SPARK_PHASE
<<4) {
330 if (points
[i
].state
>(MAX_SPARK_PHASE
<<4)+pos
.h
) {
331 if ( (points
[i
].state
&7) == 7) {
332 points
[i
].pos
.x
+=(i
&3)-1;
336 if ( (points
[i
].state
&7) == 7) {
337 points
[i
].pos
.x
+=(i
&3)-1;