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