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"
27 Color sparkcolors
[MAX_SPARK_COLOR
][MAX_SPARK_PHASE
];
30 #define SPARK_COUNT 13
32 static int spark_color_indices
[SPARK_COUNT
]={12,5,0,6,1,8,2,7,9,3,4,10,11};
34 void TranslateColor(const char *value
, Color
&color
)
39 //if not RGB then try to interpret it as a dword
40 if (strnicmp(value
,"RGB(",4)) {
41 r
= strtol(value
,NULL
,0);
43 color
.g
= (r
>>8)&0xff;
44 color
.b
= (r
>>16)&0xff;
45 color
.a
= (r
>>24)&0xff;
47 sscanf(value
+4,"%d,%d,%d)", &r
, &g
, &b
);
56 AutoTable
tab("sprklclr");
60 memset(sparkcolors
,0,sizeof(sparkcolors
));
61 for (i
=0;i
<MAX_SPARK_COLOR
;i
++) {
62 for (j
=0;j
<MAX_SPARK_PHASE
;j
++) {
63 sparkcolors
[i
][j
].a
=0xff;
66 i
= tab
->GetRowCount();
67 if (i
>MAX_SPARK_COLOR
) {
71 for (int j
=0;j
<MAX_SPARK_PHASE
;j
++) {
75 idx
= spark_color_indices
[i
];
79 const char *value
= tab
->QueryField(idx
,j
);
80 TranslateColor(value
, sparkcolors
[i
][j
]);
86 Particles::Particles(int s
)
88 points
= (Element
*) malloc(s
*sizeof(Element
) );
89 memset(points
, -1, s
*sizeof(Element
) );
91 for (int i=0;i<MAX_SPARK_PHASE;i++) {
99 size
= last_insert
= s
;
103 type
= SP_TYPE_POINT
;
105 spawn_type
= SP_SPAWN_NONE
;
109 Particles::~Particles()
115 for (int i=0;i<MAX_SPARK_PHASE;i++) {
122 void Particles::SetBitmap(unsigned int FragAnimID
)
128 fragments
= new CharAnimations(FragAnimID
, 0);
130 for (i=0;i<MAX_SPARK_PHASE;i++) {
134 AnimationFactory* af = ( AnimationFactory* )
135 gamedata->GetFactoryResource( BAM, IE_BAM_CLASS_ID );
141 for (i=0;i<MAX_SPARK_PHASE; i++) {
142 bitmap[i] = af->GetCycle( i );
148 bool Particles::AddNew(const Point
&point
)
155 st
= pos
.h
+last_insert
%15;
159 st
= core
->Roll(3,5,MAX_SPARK_PHASE
)<<4;
162 st
=(MAX_SPARK_PHASE
+ 2*pos
.h
);
166 st
=(MAX_SPARK_PHASE
+ pos
.h
)<<4;
171 if (points
[i
].state
== -1) {
172 points
[i
].state
= st
;
173 points
[i
].pos
= point
;
179 while (i
--!=last_insert
) {
180 if (points
[i
].state
== -1) {
181 points
[i
].state
= st
;
182 points
[i
].pos
= point
;
190 void Particles::Draw(const Region
&screen
)
192 int length
; //used only for raindrops
194 Video
*video
=core
->GetVideoDriver();
195 Region region
= video
->GetViewport();
202 if (points
[i
].state
== -1) {
210 state
= points
[i
].state
>>4;
213 state
= points
[i
].state
;
217 if (state
>=MAX_SPARK_PHASE
) {
218 length
= 6-abs(state
-MAX_SPARK_PHASE
-6);
221 state
=MAX_SPARK_PHASE
-state
-1;
224 Color clr
= sparkcolors
[color
][state
];
229 Sprite2D *frame = bitmap[state]->GetFrame(points[i].state&255);
230 video->BlitGameSprite(frame,
231 points[i].pos.x+screen.x,
232 points[i].pos.y+screen.y, 0, clr,
233 NULL, NULL, &screen);
237 //IE_ANI_CAST stance has a simple looping animation
238 Animation
** anims
= fragments
->GetAnimation( IE_ANI_CAST
, i
);
240 Animation
* anim
= anims
[0];
241 Sprite2D
* nextFrame
= anim
->GetFrame(anim
->GetCurrentFrame());
242 video
->BlitGameSprite( nextFrame
, points
[i
].pos
.x
- region
.x
, points
[i
].pos
.y
- region
.y
,
243 0, clr
, NULL
, fragments
->GetPartPalette(0), &screen
);
248 video
->DrawCircle (points
[i
].pos
.x
-region
.x
,
249 points
[i
].pos
.y
-region
.y
, 2, clr
, true);
253 video
->SetPixel (points
[i
].pos
.x
-region
.x
,
254 points
[i
].pos
.y
-region
.y
, clr
, true);
256 // this is more like a raindrop
259 video
->DrawLine (points
[i
].pos
.x
+region
.x
,
260 points
[i
].pos
.y
+region
.y
,
261 points
[i
].pos
.x
+region
.x
+(i
&1),
262 points
[i
].pos
.y
+region
.y
+length
, clr
, true);
269 void Particles::AddParticles(int count
)
276 p
.x
= pos
.w
/2+core
->Roll(1,pos
.w
/2,pos
.w
/4);
277 p
.y
= pos
.h
/2+(last_insert
&7);
281 p
.x
= core
->Roll(1,pos
.w
,0);
282 p
.y
= core
->Roll(1,pos
.h
/2,0);
286 p
.x
= core
->Roll(1,pos
.w
,0);
287 p
.y
= core
->Roll(1,pos
.h
,0);
290 p
.x
= core
->Roll(1,pos
.w
/2,pos
.w
/4);
291 p
.y
= core
->Roll(1,pos
.h
/2,0);
300 int Particles::Update()
306 if (phase
==P_EMPTY
) {
311 if (timetolive
<core
->GetGame()->GameTime
) {
312 spawn_type
= SP_SPAWN_NONE
;
323 spawn_type
=SP_SPAWN_NONE
;
329 for(i
=0;i
<size
;i
++) {
330 if (points
[i
].state
==-1) {
334 if (!points
[i
].state
) {
341 points
[i
].pos
.y
+=3+((i
>>2)&3);
342 points
[i
].pos
.y
%=pos
.h
;
345 points
[i
].pos
.x
+=pos
.w
+(i
&1);
346 points
[i
].pos
.x
%=pos
.w
;
347 points
[i
].pos
.y
+=3+((i
>>2)&3);
348 points
[i
].pos
.y
%=pos
.h
;
351 if (points
[i
].state
<=MAX_SPARK_PHASE
<<4) {
354 points
[i
].pos
.x
+=core
->Roll(1,3,pos
.w
-2);
355 points
[i
].pos
.x
%=pos
.w
;
356 points
[i
].pos
.y
+=(i
&3)+1;
362 if (points
[i
].state
<=MAX_SPARK_PHASE
) {
365 if (points
[i
].state
<(MAX_SPARK_PHASE
+pos
.h
)) {
366 if ( (points
[i
].state
&7) == 7) {
367 points
[i
].pos
.x
+=(i
&3)-1;
371 if ( (points
[i
].state
&7) == 7) {
372 points
[i
].pos
.x
+=(i
&3)-1;