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 "game.h"
36 #include "init.h"
37 #include "player.h"
38 #include "mymath.h"
39 #include "tilemap.h"
40 #include "enemy.h"
41 #include "particle.h"
42 #include "bonus.h"
43 #include "helpers.h"
44 #include "effects.h"
45 #include "special_power.h"
46 #include "trap.h"
47 #include "soundmusic.h"
48 #include "levels.h"
49 
50 
51 // Enemy list
52 list<ENEMY> enemylist;
53 
54 // Enemy animations
55 GLuint enemy_anim[3];
56 static int anim_frames[4] = { 0, 1, 0, 2 };
57 
58 
59 // Texture from player.cpp
60 extern GLuint sprite_shadow;
61 
62 // From bonus.cpp
63 extern int killed_5_diamonds;
64 
65 
66 // The counter for the continuous enemy creation
67 int enemy_creation_counter;
68 
69 // Amount of time between two enemy creation periods
70 const int enemy_creation_interval = 90;
71 
72 // Enemy burning time
73 int enemy_burn_time = 420;
74 
75 
76 // Load the enemies
load_enemies()77 void load_enemies() {
78 
79 	// Load the red enemy animations
80 	enemy_anim[0] = load_png("enemy1.png", true, false, false);
81 	enemy_anim[1] = load_png("enemy2.png", true, false, false);
82 	enemy_anim[2] = load_png("enemy3.png", true, false, false);
83 
84 }
85 
86 
87 // Helper function which checks if the players are right next to
88 // a location or in the same region
is_player_close(int x,int y)89 bool is_player_close(int x, int y) {
90 
91 	// Check distance to the players
92 	int dx = x - (int)p1.get_real_x();
93 	int dy = y - (int)p1.get_real_y();
94 	if(dx*dx + dy*dy <= 49)		// 49 == 7*7
95 		return true;
96 
97 	if(two_players) {
98 		dx = x - (int)p2.get_real_x();
99 		dy = y - (int)p2.get_real_y();
100 		if(dx*dx + dy*dy <= 49)	// 49 == 7*7
101 			return true;
102 	}
103 
104 
105 	// Determine the regions (4x4)
106 	int p1reg = 0, p2reg = 0;
107 	if(p1.x < 7 && p1.y <= 7)
108 		p1reg = 1;
109 	else if(p1.x < 7 && p1.y > 7)
110 		p1reg = 3;
111 	else if(p1.x >= 7 && p1.y <= 7)
112 		p1reg = 2;
113 	else
114 		p1reg = 4;
115 
116 
117 	if(two_players) {
118 		if(p2.x < 7 && p2.y <= 7)
119 			p2reg = 1;
120 		else if(p2.x < 7 && p2.y > 7)
121 			p2reg = 3;
122 		else if(p2.x >= 7 && p2.y <= 7)
123 			p2reg = 2;
124 		else
125 			p2reg = 4;
126 	}
127 
128 	int ereg;
129 	if(x < 7 && y <= 7)
130 		ereg = 1;
131 	else if(x < 7 && y > 7)
132 		ereg = 3;
133 	else if(x >= 7 && y <= 7)
134 		ereg = 2;
135 	else
136 		ereg = 4;
137 
138 	// Check the region
139 	if(p1reg == ereg)
140 		return true;
141 	if(two_players && p2reg == ereg)
142 		return true;
143 
144 	return false;
145 }
146 
147 
148 // Helper function which adds an new enemy while checking
149 // for bad places
new_enemy(int & ex,int & ey)150 bool new_enemy(int &ex, int &ey) {
151 	// Add a new enemy
152 	ENEMY e;
153 	e.clear();
154 
155 	// Check for bad places
156 	int x = RAND(0, MAP_W-1);
157 	int y = RAND(0, MAP_H-1);
158 	int counter = 0;
159 	while((!can_teleport(x, y) || is_player_close(x,y)) && counter < 10000) {
160 		x = RAND(0, MAP_W-1);
161 		y = RAND(0, MAP_H-1);
162 		counter++;
163 	}
164 
165 	if(counter >= 10000)
166 		return false;
167 
168 	e.x = x;
169 	e.y = y;
170 	ex = x;
171 	ey = y;
172 	e.tx = e.x;
173 	e.ty = e.y;
174 	e.type = RAND(0,2);
175 	e.alive = true;
176 	enemylist.push_back(e);
177 	return true;
178 }
179 
180 
181 // Move the enemies
move_enemies()182 void move_enemies() {
183 	// Create new enemies if there's less than enemy_amount of them
184 	// (but don't create enemies until all the diamonds from Killed-5 have
185 	//  been collected)
186 	int num_enemies = enemylist.size();
187 	if(num_enemies < ENEMY_AMOUNT && !killed_5_diamonds && !level_pause) {
188 		enemy_creation_counter--;
189 		if(enemy_creation_counter < 0) {
190 			bool created = false;
191 			// Add enemies to maintain the certain enemy amount
192 			for(int i=0; i < (ENEMY_AMOUNT - num_enemies); i++) {
193 				// Add a new enemy
194 				int ex, ey;
195 				if(new_enemy(ex, ey)) {
196 					// Create the teleport effect
197 					create_teleport_effect(ex, ey);
198 					created = true;
199 				}
200 			}
201 
202 			// Play the appear sound
203 			if(created) {
204 				play_sound(SND_APPEAR, false);
205 				enemy_creation_counter = enemy_creation_interval;
206 			}
207 		}
208 
209 	}
210 
211 	// Move the active enemies
212 	if(enemylist.size() == 0)
213 		return;
214 
215 	list<ENEMY>::iterator i;
216 	for(i = enemylist.begin(); i != enemylist.end(); ++i) {
217 		(*i).move();
218 		// Remove the dead enemies
219 		if((*i).alive == false) {
220 			i = enemylist.erase(i);
221 		}
222 	}
223 
224 }
225 
226 
227 // Draw the enemies
draw_enemies()228 void draw_enemies() {
229 	if(enemylist.size() == 0)
230 		return;
231 
232 	list<ENEMY>::iterator i;
233 	for(i = enemylist.begin(); i != enemylist.end(); ++i) {
234 		(*i).draw();
235 	}
236 }
237 
238 
239 // Clear the enemy list
clear_enemies()240 void clear_enemies() {
241 	enemylist.clear();
242 	enemy_creation_counter = 30;
243 }
244 
245 
246 // Helper function which computes the right direction
get_dir(int dx,int dy)247 int get_dir(int dx, int dy) {
248 	if(dx == 0 && dy == -1)
249 		return DIR_N;
250 	else if(dx == 1 && dy == 0)
251 		return DIR_E;
252 	else if(dx == 0 && dy == 1)
253 		return DIR_S;
254 	else
255 		return DIR_W;
256 }
257 
258 
259 // Look for a player and chase him
look_player()260 void ENEMY::look_player() {
261 	// Movement deltas for each direction
262 	const int dx[4] = {  0, 1, 0, -1 };
263 	const int dy[4] = { -1, 0, 1,  0 };
264 
265 	// Sweep in a straigth line and check for the player presence
266 	for(int pos=1; pos < MAP_W; pos++) {
267 		int xx, yy;
268 		xx = x + dx[dir] * pos;
269 		yy = y + dy[dir] * pos;
270 
271 		// Check for solid tile
272 		if(map_solid(xx, yy))
273 			break;
274 
275 		// Check for the players
276 		if((int)p1.get_real_x() == xx && (int)p1.get_real_y() == yy && p1.alive && !p1.jumping && !(using_special_power == 1 && which_special_power == BLUE_POWER_TELEPORT)) {
277 			// Begin the chase
278 			chase = 1;			// 1 for player one
279 			speed += 0.03f;
280 			break;
281 		}
282 		else if(two_players && (int)p2.get_real_x() == xx && (int)p2.get_real_y() == yy && p2.alive && !p2.jumping && !(using_special_power == 2 && which_special_power == BLUE_POWER_TELEPORT)) {
283 			// Begin the chase
284 			chase = 2;			// 2 for player two
285 			speed += 0.03f;
286 			break;
287 		}
288 	}
289 
290 }
291 
292 
293 // Lightning special power instance from special_power.cpp
294 extern SP_LIGHTNING sp_lightning;
295 
296 
297 // Move the enemy
move()298 void ENEMY::move() {
299 	// Advance the animation
300 	if(!chase && !burning)
301 		anim += 0.10f;
302 	else
303 		anim += 0.20f;
304 	if((int)anim > 3 || kicked)
305 		anim = 0.0f;
306 
307 	// Advance the dying animation if we're actually dying
308 	if(dying) {
309 		die_anim -= 0.03f;
310 
311 		// Create the blue "burning down" effect
312 		float px = get_real_x();
313 		float py = get_real_y();
314 		for(int f=0; f < RAND(2,10); f++) {
315 			float rnd = RANDF(-0.3f, 0.3f);
316 			VECT pos(px, 2*size - 0.05f - (2.5f*size*(1-die_anim)), py);
317 			pos.x += rnd;
318 			pos.z -= rnd;
319 			if(pos.y < 0.0f)
320 				pos.y = 0.0f;
321 			if(turning)
322 				pos.y += (turning_raise * 0.85f);
323 			VECT dir = 0.0f;
324 			float c1[4] = { 0.1f, 0.7f, 1, 1 };
325 			float c2[4] = { 0.1f, 0.7f, 1, 0 };
326 			add_particle(pos, dir, RAND(20,35), 0.1f, 0.4f, c1, c2, part_star);
327 		}
328 
329 		if(die_anim < 0.0f) {
330 			die_anim = 0.0f;
331 			alive = false;
332 		}
333 
334 		return;
335 	}
336 
337 
338 	// Create some particle fire from the burning enemies
339 	if(burning) {
340 		VECT ppos(get_real_x(), 0.5f, get_real_y());
341 		create_fire(ppos);
342 	}
343 
344 	// Advance the turning animation
345 	if(turning) {
346 		// Raise up
347 		if(turning == 1) {
348 			turning_raise += 0.035f;
349 			if(turning_raise >= 1.0f) {
350 				turning_raise = 1.0f;
351 				turning++;
352 			}
353 		}
354 		// Turn
355 		else if(turning == 2) {
356 			turning_counter++;
357 			if(turning_counter == 5) {
358 				dir = nextdir;
359 				nextdir = dir + 1;
360 				if(nextdir > DIR_W)
361 					nextdir = DIR_N;
362 			}
363 			else if(turning_counter == 10) {
364 				dir = nextdir;
365 				turning++;
366 			}
367 		}
368 		// Go down
369 		else if(turning == 3) {
370 			turning_raise -= 0.035f;
371 			if(turning_raise <= 0.0f) {
372 				turning_raise = 0.0f;
373 				turning = 0;
374 			}
375 		}
376 
377 		// Check the collision between the player #1
378 		if(p1.alive && !p1.jumping) {
379 			float dx = get_real_x() - p1.get_real_x();
380 			float dy = get_real_y() - p1.get_real_y();
381 			if(dx*dx + dy*dy <= 0.9f) {
382 				// Collision happened!
383 
384 				// Kill the player and die
385 				p1.die();
386 				die();
387 			}
388 		}
389 
390 		// Check the collision between the player #2
391 		if(alive && two_players && p2.alive && !p2.jumping) {
392 			float dx = get_real_x() - p2.get_real_x();
393 			float dy = get_real_y() - p2.get_real_y();
394 			if(dx*dx + dy*dy <= 0.9f) {
395 				// Collision happened!
396 
397 				// Kill the player and die
398 				p2.die();
399 				die();
400 			}
401 		}
402 
403 		return;
404 	}
405 
406 
407 	// If there is the lightning special power in progress, don't move the enemies which are
408 	// suffering from the lightning strikes
409 	if(special_power_pause && which_special_power == BLUE_POWER_LIGHTNING) {
410 		// Check if we're a target
411 		for(int f=0; f<ENEMY_AMOUNT; f++) {
412 			if(sp_lightning.targets[f] == this) {
413 				anim += 0.30f;
414 				if((int)anim > 3)
415 					anim = 0.0f;
416 				return;
417 			}
418 		}
419 	}
420 
421 	// Don't move if the level is finished
422 	if(level_pause)
423 		return;
424 
425 
426 	// Check the traps
427 	if(traplist.size() > 0) {
428 		list<TRAP>::iterator t;
429 		for(t = traplist.begin(); t != traplist.end(); ++t) {
430 			if(x == (*t).x && y == (*t).y) {
431 				die();
432 				return;
433 			}
434 		}
435 	}
436 
437 
438 	// Handle the burning, that is run around aimlessly
439 	if(burning) {
440 		if(!kicked) {
441 			// Reduce the burning time
442 			burn_time--;
443 			if(burn_time == 0) {
444 				die();
445 				return;
446 			}
447 
448 			// Choose a random direction
449 			if(RAND(0,100) > 50 && offset == 0.0f) {
450 				if(RAND(0,100) > 50)
451 					dir++;
452 				else
453 					dir--;
454 				if(dir > DIR_W)
455 					dir = DIR_N;
456 				else if(dir < DIR_N)
457 					dir = DIR_W;
458 			}
459 
460 			// Move one step
461 			if(tx == x && ty == y) {
462 				offset = 0.0f;
463 
464 				// Don't stop until there's a wall.
465 				switch(dir) {
466 					default:
467 					case DIR_N: tx = x; ty = y - 1; break;
468 					case DIR_E: tx = x + 1; ty = y; break;
469 					case DIR_S: tx = x; ty = y + 1; break;
470 					case DIR_W: tx = x - 1; ty = y; break;
471 				}
472 
473 				// Check if the target is passable?
474 				if(map_solid(tx, ty)) {
475 					// Stop and choose a new dir
476 					tx = x;
477 					ty = y;
478 
479 					dir += RAND(-1,1);
480 					if(dir < DIR_N)
481 						dir = DIR_W;
482 					else if(dir > DIR_W)
483 						dir = DIR_N;
484 					return;
485 				}
486 
487 			}
488 
489 			// Move towards the target tile
490 			if(offset < 1.0f && (tx != x || ty != y)) {
491 				offset += speed;
492 
493 				// Check the collision between the player #1
494 				if(p1.alive && !p1.jumping && !(using_special_power == 1 && which_special_power == BLUE_POWER_TELEPORT)) {
495 					float dx = get_real_x() - p1.get_real_x();
496 					float dy = get_real_y() - p1.get_real_y();
497 					if(dx*dx + dy*dy <= 0.9f) {
498 						// Collision happened!
499 
500 						// Turn around and run
501 						tx = x;
502 						ty = y;
503 						offset = 0.0f;
504 						dir += 2;
505 						if(dir > DIR_W)
506 							dir -= 4;
507 					}
508 				}
509 
510 				// Check the collision between the player #2
511 				if(two_players && p2.alive && !p2.jumping && !(using_special_power == 2 && which_special_power == BLUE_POWER_TELEPORT)) {
512 					float dx = get_real_x() - p2.get_real_x();
513 					float dy = get_real_y() - p2.get_real_y();
514 					if(dx*dx + dy*dy <= 0.9f) {
515 						// Collision happened!
516 
517 						// Turn around and run
518 						tx = x;
519 						ty = y;
520 						offset = 0.0f;
521 						dir += 2;
522 						if(dir > DIR_W)
523 							dir -= 4;
524 					}
525 				}
526 
527 				// Check the collision between the potato men
528 				if(potatoman.collide_with(this) && !kicked) {
529 					// Potatoman "kicked" us
530 					potatoman.kick(this);
531 				}
532 
533 
534 				// If we're reached the target tile, move again
535 				if(offset >= 1.0f) {
536 					x = tx;
537 					y = ty;
538 					offset = 0.0f;
539 				}
540 			}
541 		}
542 
543 		// Check collisions with other enemies and spread the fire
544 		bool burnt_somebody = false;
545 		list<ENEMY>::iterator e;
546 		for(e = enemylist.begin(); e != enemylist.end(); ++e) {
547 			if(this != &(*e) && !(*e).burning) {
548 				// Check the distance
549 				float dx = get_real_x() - (*e).get_real_x();
550 				float dy = get_real_y() - (*e).get_real_y();
551 				if(dx*dx + dy*dy <= 0.9f) {
552 					// Burn the other enemy
553 					(*e).burning = true;
554 					(*e).burn_time = enemy_burn_time;
555 					(*e).speed += 0.06f;
556 					burnt_somebody = true;
557 				}
558 			}
559 		}
560 
561 		// Play the burning sound
562 		if(burnt_somebody)
563 			play_sound(SND_WILDFIRE, false);
564 
565 		if(!kicked)
566 			return;
567 	}
568 
569 
570 	// Not burning below here
571 
572 	// Choose a random destination
573 	if(path_pos == -1) {
574 		// Choose a valid target
575 		int dx = RAND(0, MAP_W-1);
576 		int dy = RAND(0, MAP_H-1);
577 		while(map_solid(dx, dy) || dx == x || dy == y) {
578 			dx = RAND(0, MAP_W-1);
579 			dy = RAND(0, MAP_H-1);
580 		}
581 
582 		// Calculate the path
583 		if(pf.find_path(x, y, dx, dy) == PATH_FAILED) {
584 			// Well, tough luck. We'll just wait and try again later.
585 			return;
586 		}
587 
588 		// Now we've got a nice path for us!
589 		path_pos = 0;
590 		offset = 0.0f;
591 		tx = pf.path[0].x;
592 		ty = pf.path[0].y;
593 		dir = get_dir(tx - x, ty - y);
594 		look_player();
595 	}
596 
597 	// Move one step
598 	if(tx == x && ty == y && path_pos > -1) {
599 		offset = 0.0f;
600 
601 		// Follow the path if we're not chasing
602 		if(chase == 0 && !kicked) {
603 			path_pos++;
604 			tx = pf.path[path_pos].x;
605 			ty = pf.path[path_pos].y;
606 			dir = get_dir(tx - x, ty - y);
607 			look_player();
608 		}
609 		else if(chase && !kicked) {
610 			// We are chasing. Don't stop until there's a wall.
611 			switch(dir) {
612 				default:
613 				case DIR_N: tx = x; ty = y - 1; break;
614 				case DIR_E: tx = x + 1; ty = y; break;
615 				case DIR_S: tx = x; ty = y + 1; break;
616 				case DIR_W: tx = x - 1; ty = y; break;
617 			}
618 
619 			// Check if the target is passable?
620 			if(map_solid(tx, ty)) {
621 				// Stop and choose a new path
622 				tx = x;
623 				ty = y;
624 
625 				path_pos = -1;
626 				chase = 0;
627 				speed -= 0.03f;
628 			}
629 		}
630 		else if(kicked) {
631 			// Potatoman has kicked us. "Fly" straight until we hit a wall.
632 			switch(dir) {
633 				default:
634 				case DIR_N: tx = x; ty = y - 1; break;
635 				case DIR_E: tx = x + 1; ty = y; break;
636 				case DIR_S: tx = x; ty = y + 1; break;
637 				case DIR_W: tx = x - 1; ty = y; break;
638 			}
639 
640 			// Check for the wall
641 			if(map_solid(tx, ty)) {
642 				die();
643 				return;
644 			}
645 		}
646 	}
647 
648 	// Move towards the target tile
649 	if(offset < 1.0f && (tx != x || ty != y) && path_pos > -1) {
650 		offset += speed;
651 
652 		// Check the collision between the player #1
653 		if(p1.alive && !p1.jumping && !(using_special_power == 1 && which_special_power == BLUE_POWER_TELEPORT)) {
654 			float dx = get_real_x() - p1.get_real_x();
655 			float dy = get_real_y() - p1.get_real_y();
656 			if(dx*dx + dy*dy <= 0.9f) {
657 				// Collision happened!
658 
659 				// Kill the player and die
660 				p1.die();
661 				die();
662 			}
663 		}
664 
665 		// Check the collision between the player #2
666 		if(alive && two_players && p2.alive && !p2.jumping && !(using_special_power == 2 && which_special_power == BLUE_POWER_TELEPORT)) {
667 			float dx = get_real_x() - p2.get_real_x();
668 			float dy = get_real_y() - p2.get_real_y();
669 			if(dx*dx + dy*dy <= 0.9f) {
670 				// Collision happened!
671 
672 				// Kill the player and die
673 				p2.die();
674 				die();
675 			}
676 		}
677 
678 
679 		// Check the collision between the potato men
680 		if(potatoman.collide_with(this) && !kicked) {
681 			// Potatoman "kicked" us
682 			potatoman.kick(this);
683 		}
684 
685 
686 		// If we're reached the target tile, move again
687 		if(offset >= 1.0f) {
688 			x = tx;
689 			y = ty;
690 			offset = 0.0f;
691 
692 			// If this is the final destination, stay put and choose a new path
693 			// on the next cycle
694 			if(x == pf.dx && y == pf.dy && !chase && !kicked)
695 				path_pos = -1;
696 		}
697 	}
698 
699 }
700 
701 
702 // Kill the enemy
die()703 void ENEMY::die() {
704 	if(dying)
705 		return;		// Hey, don't you die twice, man! ;)
706 	dying = true;
707 	kill_count++;
708 	die_anim = 1.0f;
709 
710 	// Create a bonus
711 	add_bonus((int)get_real_x(), (int)get_real_y(), type);
712 
713 	// Play the sound
714 	static int last_sound = -1;
715 	int sound = last_sound;
716 	while(sound == last_sound)
717 		sound = RAND(SND_DIE1, SND_DIE6);
718 	play_sound(sound, false);
719 	last_sound = sound;
720 }
721 
722 
723 // Get current x with offset
get_real_x()724 float ENEMY::get_real_x() {
725 	// Calculate the offset
726 	float offx = 0;
727 	if(dir == DIR_E)
728 		offx = offset;
729 	else if(dir == DIR_W)
730 		offx = -offset;
731 
732 	return (float)x + offx + 0.5f;
733 }
734 
735 
736 // Get current y with offset
get_real_y()737 float ENEMY::get_real_y() {
738 	// Calculate the offset
739 	float offy = 0;
740 	if(dir == DIR_N)
741 		offy = -offset;
742 	else if(dir == DIR_S)
743 		offy = offset;
744 
745 	return (float)y + offy + 0.5f;
746 }
747 
748 
749 // Draw the enemy
draw()750 void ENEMY::draw() {
751 	// Calculate the offset
752 	float offx = 0, offz = 0;
753 	switch(dir) {
754 		default:
755 		case DIR_N: offz = -offset; break;
756 		case DIR_E: offx = offset; break;
757 		case DIR_S: offz = offset; break;
758 		case DIR_W: offx = -offset; break;
759 	}
760 
761 	// Translate to the position
762 	glPushMatrix();
763 	glTranslatef(x + offx + 0.5f, size - 0.20f, y + offz + 0.5f);
764 
765 	// Draw the shadow
766 	glDepthMask(GL_FALSE);
767 	glColor3f(1,1,1);
768 	BIND_TEXTURE(sprite_shadow);
769 	float sh = -(size - 0.21f);
770 	glBegin(GL_TRIANGLE_STRIP);
771 		glTexCoord2f(1,1); glVertex3f( 0.6f, sh, -0.6f);
772 		glTexCoord2f(0,1); glVertex3f(-0.6f, sh, -0.6f);
773 		glTexCoord2f(1,0); glVertex3f( 0.6f, sh,  0.6f);
774 		glTexCoord2f(0,0); glVertex3f(-0.6f, sh,  0.6f);
775 	glEnd();
776 	glDepthMask(GL_TRUE);
777 
778 	// Raise up if we're turning
779 	if(turning)
780 		glTranslatef(0, turning_raise * 0.85f, 0);
781 
782 
783 	// Negate the camera rotation
784 	glMultMatrixf(cam_neg_matrix);
785 //	glRotatef(45.0f, 0,1,0);
786 //	glRotatef(-30.0f, 1,0,0);
787 
788 	// Draw the sprite
789 	if(burning)
790 		glColor3f(.5f,.5f,.5f);
791 
792 	// Compute the texture coords according the animation frame and direction
793 	BIND_TEXTURE(enemy_anim[type]);
794 	int f = anim_frames[(int)anim];
795 	float textx = 0.25f * f;
796 	float texty = 0.25f * (3-dir);
797 
798 	if(!dying) {
799 		glBegin(GL_TRIANGLE_STRIP);
800 			glTexCoord2f(textx + 0.25f, texty + 0.25f); glVertex3f( size,  size,  size);
801 			glTexCoord2f(textx, texty + 0.25f); glVertex3f(-size,  size,  size);
802 			glTexCoord2f(textx + 0.25f, texty); glVertex3f( size, -size, -size);
803 			glTexCoord2f(textx, texty); glVertex3f(-size, -size, -size);
804 		glEnd();
805 	}
806 	else {
807 		// Draw the dying animation
808 		float z = size - (2*size*(1-die_anim));
809 		glBegin(GL_TRIANGLE_STRIP);
810 			glTexCoord2f(textx + 0.25f, texty + (die_anim*0.25f)); glVertex3f( size,  z,  z);
811 			glTexCoord2f(textx, texty + (die_anim*0.25f)); glVertex3f(-size,  z,  z);
812 			glTexCoord2f(textx + 0.25f, texty); glVertex3f( size, -size, -size);
813 			glTexCoord2f(textx, texty); glVertex3f(-size, -size, -size);
814 		glEnd();
815 
816 	}
817 
818 	glPopMatrix();
819 }
820 
821 
822 // Clear the enemy
clear()823 void ENEMY::clear() {
824 	x = y = 0;
825 	tx = ty = 0;
826 	offset = 0.0f;
827 	speed = 0.05f;
828 	dir = RAND(DIR_N, DIR_W);
829 	nextdir = dir;
830 	size = 0.85f;
831 	anim = 0.0f;
832 	type = 0;
833 	alive = false;
834 	dying = false;
835 	die_anim = 1.0f;
836 	path_pos = -1;
837 	chase = 0;
838 	burning = false;
839 	burn_time = 0;
840 	turning = 0;
841 	turning_counter = 0;
842 	turning_raise = 0.0f;
843 	kicked = false;
844 }
845 
846 
847