1 /*************************************************************************
2
3 "I Have No Tomatoes"
4 Copyright (c) 2004, Mika Halttunen
5
6 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
9
10 Permission is granted to anyone to use this software for any purpose,
11 including commercial applications, and to alter it and redistribute
12 it freely, subject to the following restrictions:
13
14 1. The origin of this software must not be misrepresented; you must
15 not claim that you wrote the original software. If you use this
16 software in a product, an acknowledgment in the product documentation
17 would be appreciated but is not required.
18
19 2. Altered source versions must be plainly marked as such, and must
20 not be misrepresented as being the original software.
21
22 3. This notice may not be removed or altered from any source
23 distribution.
24
25
26 Mika Halttunen <lsoft@mbnet.fi>
27
28 *************************************************************************/
29
30 #include <stdio.h>
31 #include "SDL.h"
32 #include "SDL_opengl.h"
33 #include "SDL_image.h"
34 #include "texture.h"
35 #include "init.h"
36 #include "mymath.h"
37 #include "tilemap.h"
38 #include "particle.h"
39
40 // Particle display list
41 GLuint part_dlist;
42
43
44 // Particle sprites
45 GLuint part_spark;
46 GLuint part_explo;
47 GLuint part_star;
48 GLuint part_glow;
49 GLuint part_smoke;
50 GLuint part_fire;
51 GLuint part_flower;
52
53
54 // Gravity
55 const float gravity = -0.002f;
56
57 // "Negate camera rotation" matrix (rotates 45 degrees around Y axis and -30 degrees around X axis)
58 const float cam_neg_matrix[16] = { 0.707107f, 0, -0.707107f, 0, -0.353553f, 0.866025f, -0.353553f, 0, 0.612372f, 0.5f, 0.612372f, 0, 0, 0, 0, 1 };
59
60
61 // Particle lists (one for regular, one for alpha blended parts)
62 list<PARTICLE> partlist;
63 list<PARTICLE> alphapartlist;
64
65
66
67 // Load particles
load_particles()68 void load_particles() {
69 part_spark = load_jpg("spark.jpg", false, false, true);
70 part_explo = load_jpg("explo.jpg", false, false, true);
71 part_star = load_jpg("star.jpg", false, false, true);
72 part_glow = load_jpg("glow.jpg", false, false, true);
73 part_smoke = load_png("smoke.png", true, false, true);
74 part_fire = load_jpg("fire.jpg", false, false, true);
75 part_flower = load_png("flower.png", true, false, true);
76
77
78 // Build the display list
79 part_dlist = glGenLists(1);
80 glNewList(part_dlist, GL_COMPILE);
81 glBegin(GL_TRIANGLE_STRIP);
82 glTexCoord2f(1,1); glVertex3f( 1, 1, 1);
83 glTexCoord2f(0,1); glVertex3f(-1, 1, 1);
84 glTexCoord2f(1,0); glVertex3f( 1, -1, -1);
85 glTexCoord2f(0,0); glVertex3f(-1, -1, -1);
86 glEnd();
87 glEndList();
88 }
89
90
91 // Free the particle list
kill_particles()92 void kill_particles() {
93 glDeleteLists(part_dlist, 1);
94 }
95
96
97 // Add particle
add_particle(VECT pos,VECT dir,int maxlife,float size1,float size2,float color1[4],float color2[4],GLuint tex,bool alpha)98 void add_particle(VECT pos, VECT dir, int maxlife, float size1, float size2, float color1[4], float color2[4], GLuint tex, bool alpha) {
99 PARTICLE p;
100 p.clear();
101 p.pos = pos;
102 p.dir = dir;
103 p.size = size1;
104 p.delta_size = (size2 - size1) / (float)maxlife;
105 p.life = 0;
106 p.maxlife = maxlife;
107 p.alive = true;
108 p.tex = tex;
109
110 for(int f=0; f<4; f++) {
111 p.color[f] = color1[f];
112 p.delta_color[f] = (color2[f] - color1[f]) / (float)maxlife;
113 }
114
115 // Regular particle or alpha blended particle?
116 if(alpha)
117 alphapartlist.push_back(p);
118 else
119 partlist.push_back(p);
120 }
121
122
123 // Move the particles
move_particles()124 void move_particles() {
125 // Move the regular particles
126 if(partlist.size() != 0) {
127 list<PARTICLE>::iterator i;
128 for(i = partlist.begin(); i != partlist.end(); ++i) {
129 (*i).move();
130 // Remove the dead particles
131 if((*i).alive == false) {
132 i = partlist.erase(i);
133 }
134 }
135 }
136
137 // Move the alpha blended particles
138 if(alphapartlist.size() != 0) {
139 list<PARTICLE>::iterator i;
140 for(i = alphapartlist.begin(); i != alphapartlist.end(); ++i) {
141 (*i).move();
142 // Remove the dead particles
143 if((*i).alive == false) {
144 i = alphapartlist.erase(i);
145 }
146 }
147 }
148
149 }
150
151
152 // Draw the particles
draw_particles()153 void draw_particles() {
154 // Draw the regular particles
155 if(partlist.size() != 0) {
156 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
157 glDepthMask(GL_FALSE);
158
159 list<PARTICLE>::iterator i;
160 for(i = partlist.begin(); i != partlist.end(); ++i)
161 (*i).draw();
162
163 glDepthMask(GL_TRUE);
164 }
165
166 // Draw the alpha blended particles
167 if(alphapartlist.size() != 0) {
168 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
169 glDepthMask(GL_FALSE);
170
171 list<PARTICLE>::iterator i;
172 for(i = alphapartlist.begin(); i != alphapartlist.end(); ++i)
173 (*i).draw();
174
175 glDepthMask(GL_TRUE);
176 }
177 }
178
179
180 // Clear the particles
clear_particles()181 void clear_particles() {
182 partlist.clear();
183 alphapartlist.clear();
184 }
185
186
187 // Draw the particle
draw()188 void PARTICLE::draw() {
189 // Translate to the position
190 glPushMatrix();
191 glTranslatef(pos.x, pos.y, pos.z);
192
193
194 // Negate the camera rotation
195 glMultMatrixf(cam_neg_matrix);
196 // glRotatef(45.0f, 0,1,0);
197 // glRotatef(-30.0f, 1,0,0);
198
199 glRotatef(rot, 0,0,1);
200
201 // Draw the sprite
202 BIND_TEXTURE(tex);
203 glColor4fv(color);
204 glScalef(size, size, size);
205 glCallList(part_dlist);
206 /* glBegin(GL_TRIANGLE_STRIP);
207 glTexCoord2f(1,1); glVertex3f( size, size, size);
208 glTexCoord2f(0,1); glVertex3f(-size, size, size);
209 glTexCoord2f(1,0); glVertex3f( size, -size, -size);
210 glTexCoord2f(0,0); glVertex3f(-size, -size, -size);
211 glEnd();
212 */
213 glPopMatrix();
214 }
215
216
217 // Move the particle
move()218 void PARTICLE::move() {
219 // Advance the life
220 life++;
221 if(life >= maxlife) {
222 alive = false;
223 return;
224 }
225
226 // Model some gravity and move
227 dir.y += gravity;
228 pos += dir;
229
230 // Bounce from the floor
231 if(pos.y < 0.0f) {
232 pos.y = 0.0f;
233 dir.y = -dir.y;
234 }
235
236
237 // Modify the size
238 size += delta_size;
239
240 // Modify the color
241 color[0] += delta_color[0];
242 color[1] += delta_color[1];
243 color[2] += delta_color[2];
244 color[3] += delta_color[3];
245
246 // Rotate
247 //rot = add_angle(rot, 2.0f);
248 rot += 2.0f;
249 //if(rot > 360.0f)
250 // rot -= 360.0f;
251
252 }
253
254
255 // Clear the particle
clear()256 void PARTICLE::clear() {
257 pos = 0.0f;
258 dir = 0.0f;
259 rot = RANDF(0,359);
260 size = 1.0f;
261 delta_size = 0.0f;
262
263 color[0] = color[1] = color[2] = color[3] = 1.0f;
264 delta_color[0] = delta_color[1] = delta_color[2] = delta_color[3] = 0.0f;
265
266 tex = 0;
267 life = maxlife = 0;
268 alive = false;
269 }
270
271
272