Use an absolute directory under /usr/share/games/ for game data
[kraptor.git] / src / enemigo.c
blob80e9ead9faed0888b350c21aab54b3de19b3d4e7
1 // --------------------------------------------------------
2 // enemigo.c
3 // --------------------------------------------------------
4 // Copyright (c) Kronoman
5 // En memoria de mi querido padre
6 // --------------------------------------------------------
7 // Este modulo contiene todo lo relacionado con los enemigos
8 // Tal como movimiento, disparos, etc...
9 // --------------------------------------------------------
10 #ifndef ENEMIGO_C
11 #define ENEMIGO_C
13 #include <stdio.h>
14 #include "allegro.h"
15 #include "pmask.h"
16 #include "azar.h"
17 #include "enemigo.h"
18 #include "kfbuffer.h"
19 #include "jugador.h" /* lo preciso para poder verificar
20 los disparos contra el jugador... jeje */
21 #include "sombras.h"
22 #include "combo.h"
23 #include "partic.h"
24 #include "global.h"
25 #include "sonido.h"
26 #include "bomba.h"
27 #include "ia.h"
28 #include "premio.h"
29 #include "error.h"
30 /* GLOBALES */
31 ARMA_ENE arma_ene[MAX_E_CLASS]; /* armamento enemigo */
32 ENEM_T enem_t[MAX_E_CLASS]; /* tipos de enemigos */
33 ENEMIGO *enemigo_1 = NULL; /* puntero al 1er enemigo activo */
34 DISP_ENE *disp_ene_1 = NULL; /* puntero al 1er disparo activo */
36 /* esta variable NO es necesaria, solo la uso para
37 ver cuantos enemigos hay en memoria, y de esa manera,
38 revisar la performance... */
39 int cant_enemigos_debug = 0;
41 /* Agrega un enemigo en x, y de tipo 'tipo' */
42 void agregar_enemigo(int x, int y, int tipo )
44 ENEMIGO *nueva = malloc(sizeof(ENEMIGO));
45 nueva->next = enemigo_1;
46 enemigo_1 = nueva;
48 if (nueva != NULL) /* si el malloc funciono, seteo los datos... */
50 nueva->x = itofix(x);
51 nueva->y = itofix(y);
52 nueva->vida = enem_t[tipo].vida; /* que corta es la vida de un piloto enemigo... */
53 nueva->ene_t = tipo; /* que somos? yankis gallinas o pilotos de verdad? */
54 // resetear la IA
55 nueva->bytecode_actual = -1; // aun no ejecute nada, por eso -1
56 nueva->bytecode_loop = 0; // empezar con la 1era instruccion
58 nueva->ia_node = enem_t[tipo].ia_node;
59 // debo comenzar la IA en un punto al azar?
60 if (enem_t[tipo].ia_azar != 0) nueva->bytecode_actual = rand_ex(-1, nueva->ia_node->size-1);
62 // animaciones, etc...
63 nueva->spr_actual = rand()%4;
64 nueva->spr_delay = 0;
68 /* Esta funcion altera la IA del enemigo
69 llamar en cada ciclo...
71 void IA_enemigo(ENEMIGO *ene)
74 // interpretar bytecodes de la IA
75 if (ene->ia_node == NULL) return; // no tiene IA, descerebrado...
76 if (ene->ia_node->size < 1) return; // IA vacia, que paso?
78 ene->bytecode_loop--; // ejecute 1 instruccion
81 if (ene->bytecode_loop < 0)
83 // proxima instruccion
84 ene->bytecode_actual ++;
85 if (ene->bytecode_actual > ene->ia_node->size - 1) ene->bytecode_actual = 0;
86 if (ene->bytecode_actual > ene->ia_node->size-1) return; // seguridad... :)
87 ene->bytecode_loop = ene->ia_node->code[ene->bytecode_actual].loop;
89 // copiar bytecode, solo campos importantes... el resto indeterminados... :)
90 ene->bytecode_exe.x1 = rand_ex(ene->ia_node->code[ene->bytecode_actual].x1, ene->ia_node->code[ene->bytecode_actual].x2);
91 ene->bytecode_exe.y1 = rand_ex(ene->ia_node->code[ene->bytecode_actual].y1, ene->ia_node->code[ene->bytecode_actual].y2);
96 if (ene->bytecode_actual > ene->ia_node->size-1) return; // seguridad... :)
98 // mover enemigo
99 ene->x = fixadd(ene->x, itofix(ene->bytecode_exe.x1));
100 ene->y = fixadd(ene->y, itofix(ene->bytecode_exe.y1));
103 /* debo disparar ? */
104 if (ene->ia_node->code[ene->bytecode_actual].weapon > -1)
106 // cambio de arma del enemigo
107 ene->arma_actual = ene->ia_node->code[ene->bytecode_actual].weapon;
108 // disparar
109 agregar_disparo_ene(ene);
117 Esta funcion actualiza los enemigos
118 Verifica colisiones con disparos de jugador y con el jugador mismo
119 Precisa saber el desplazamiento del fondo, 'fy' ya que
120 cuando el enemigo sale de pantalla, se elimina...
122 void mover_enemigos(int fy)
124 ENEMIGO **tmp_p = &enemigo_1;
125 DISP_JUG *tmpd = NULL;
126 ENEMIGO *tmp = NULL;
128 cant_enemigos_debug = 0; /* DEBUG: innecesario */
130 while (*tmp_p) {
132 cant_enemigos_debug++; /* DEBUG: innecesario */
134 tmp = *tmp_p;
135 /* hacer IA del enemigo */
136 IA_enemigo(tmp);
138 // animacion del enemigo
139 tmp->spr_delay--;
140 if (tmp->spr_delay < 0)
142 tmp->spr_delay = enem_t[tmp->ene_t].spr_delay; // reiniciar contador
143 tmp->spr_actual++; // cambiar sprite
144 if (tmp->spr_actual > 3) tmp->spr_actual = 0;
148 /* verificar colisiones... */
150 /* colision contra el jugador? */
151 if (check_pmask_collision(enem_t[tmp->ene_t].mask[tmp->spr_actual], jugador.mask,
152 fixtoi(tmp->x), fixtoi(tmp->y),
153 fixtoi(jugador.x), fixtoi(jugador.y) ) != 0)
155 /* DEBUG: choco al jugador!, falta sonido! */
157 pone_explo_pixel(&ptr_explo_arriba,
158 fixtoi(tmp->x)+rand()%enem_t[tmp->ene_t].spr[tmp->spr_actual]->w,
159 fixtoi(tmp->y)+rand()%enem_t[tmp->ene_t].spr[tmp->spr_actual]->h,
160 rand()%enem_t[tmp->ene_t].spr[tmp->spr_actual]->w+enem_t[tmp->ene_t].spr[tmp->spr_actual]->w/3,
161 rand()%30+20,
162 ftofix(0.01));
164 jugador.vida -= enem_t[tmp->ene_t].peso + rand()%5; /* restar energia al jugador */
165 tmp->vida -= rand()%5 + 5; /* restarme energia tambien */
168 /* loop:
169 recorrer disparos del jugador
170 DEBUG: esto es muy lento!! */
172 tmpd = disp_jug_1;
173 while (tmpd) {
174 /* chequear colision, solo si el disparo esta activo,
175 de la manera hecha siguiente, si el disparo esta muerto,
176 evito comprobar la mascara, que tarda mas...*/
178 if ( tmpd->vida > 0)
179 if (check_pmask_collision(enem_t[tmp->ene_t].mask[tmp->spr_actual], arma_tipo[tmpd->arma].mask,
180 fixtoi(tmp->x), fixtoi(tmp->y),
181 fixtoi(tmpd->x), fixtoi(tmpd->y) ) != 0 )
184 /* DEBUG: choco al disparo del jugador, restar energia, etc! */
185 poner_explosion_nave(fixtoi(tmpd->x),
186 fixtoi(tmpd->y),
187 rand()%20+20, rand()%10+5+arma_tipo[tmpd->arma].punch*2, 0);
189 /* DEBUG: sonido del arma
190 del jugador pegandole al enemigo */
191 tocar_sonido_paneado(fixtoi(tmpd->x),
192 arma_tipo[tmpd->arma].snd[1],
193 rand_ex(200,255),
194 rand_ex(900,1100));
197 /* Esta comparacion es para NO pagarle mas de una vez al jugador
198 por la muerte... */
199 if (tmp->vida > 0 )
202 tmp->vida -= arma_tipo[tmpd->arma].punch; /* restar energia al enemigo */
204 /* DEBUG: mato al enemigo */
205 if (tmp->vida <= 0)
207 int ttt;
208 for (ttt=0; ttt < rand()%3 + enem_t[tmp->ene_t].peso/2+1; ttt++)
210 pone_explo_pixel(&ptr_explo_arriba,
211 fixtoi(tmp->x)+rand()%enem_t[tmp->ene_t].spr[tmp->spr_actual]->w,
212 fixtoi(tmp->y)+rand()%enem_t[tmp->ene_t].spr[tmp->spr_actual]->h,
213 rand()%enem_t[tmp->ene_t].spr[tmp->spr_actual]->w+enem_t[tmp->ene_t].spr[tmp->spr_actual]->w/3,
214 rand()%30+20,
215 ftofix(0.01));
217 // Soltar premio, si lo hubiera... -DEBUG-
218 if ( (enem_t[tmp->ene_t].premio_idx > -1) && (rand()%100+1 < enem_t[tmp->ene_t].premio_prob ) )
219 agrega_premio(enem_t[tmp->ene_t].premio_idx, tmp->x, tmp->y);
221 // Pagar...
222 jugador.dinero += enem_t[tmp->ene_t].dinero;
224 } /* fin de no pagar 2 veces */
226 tmpd->vida = -1; /* eliminar disparo, la memoria
227 se libera en jugador.c */
228 } /* fin chequear colision */
230 tmpd = tmpd->next; /* siguiente */
232 } /* fin loop de verificar disparos */
234 /* Si esta activa la bomba especial, restar energia progresivamente */
235 if (bomba_esta_activa && tmp->vida > 0)
237 tmp->vida -= rand()%10+5;
238 if (tmp->vida < 1)
240 jugador.dinero += enem_t[tmp->ene_t].dinero; // pagar
241 tmp->vida = -1; // fuerzo que se 'combustione' completamente
245 /* Ir combustionando el enemigo cuando muere (energia <= 0) */
246 if (tmp->vida <= 0 )
248 tmp->vida -= rand()%10+10;
251 /* Explosiones peque~as */
252 if (rand()%150 < abs((tmp->vida * 100) / ENE_MUERTO) ) /* incremental al irse combustionando */
254 /* sonido */
255 if (rand()%10 < 5)
257 tocar_sonido_paneado(fixtoi(tmp->x),
258 explo_cache_snd[rand()%3],
259 rand_ex(128,255),
260 rand_ex(900, 1000));
263 pone_explo_pixel(&ptr_explo_arriba,
264 fixtoi(tmp->x)+rand()%enem_t[tmp->ene_t].spr[tmp->spr_actual]->w,
265 fixtoi(tmp->y)+rand()%enem_t[tmp->ene_t].spr[tmp->spr_actual]->h,
266 rand()%enem_t[tmp->ene_t].spr[tmp->spr_actual]->w+enem_t[tmp->ene_t].spr[tmp->spr_actual]->w/3,
267 rand()%30+10,
268 ftofix(0.01));
270 /* Descontrolar enemigo */
271 // tmp->dx = (rand()%100 < 50) ? ftofix(MAX_VEL_E_X * (-1.0)) : ftofix(MAX_VEL_E_X);
272 // tmp->dy = (rand()%100 < 50) ? ftofix(MAX_VEL_E_Y * (-1.0)) : ftofix(MAX_VEL_E_Y);
275 /* al aproximarse al final, recontra-explotar... */
276 if (tmp->vida < (ENE_MUERTO / 10)*9 && nivel_detalle > 4)
278 pone_explo_pixel(&ptr_explo_arriba,
279 fixtoi(tmp->x)+enem_t[tmp->ene_t].spr[tmp->spr_actual]->w/2,
280 fixtoi(tmp->y)+enem_t[tmp->ene_t].spr[tmp->spr_actual]->h/2,
281 enem_t[tmp->ene_t].spr[tmp->spr_actual]->w+rand()%10,
282 rand()%10+10,
283 ftofix(0.01));
285 /* PARTICULAS Y PEDAZOS DE NAVES AL MORIR... */
286 if (tmp->vida-10 <= ENE_MUERTO)
287 poner_explosion_nave(fixtoi(tmp->x)+enem_t[tmp->ene_t].spr[tmp->spr_actual]->w/2,
288 fixtoi(tmp->y)+enem_t[tmp->ene_t].spr[tmp->spr_actual]->h/2,
289 rand()%20+20,
290 rand()%10+5, -1);
292 } /* fin combustionar */
295 /* verificar limites de pantalla visible */
296 /* nota: la IA rebota en las X, queda cool. */
297 if (tmp->x < 0) { tmp->x = 0; tmp->bytecode_exe.x1 *= -1; }
299 if (fixtoi(tmp->x) > ANCHO_FB - enem_t[tmp->ene_t].spr[tmp->spr_actual]->w )
301 tmp->x = itofix(ANCHO_FB - enem_t[tmp->ene_t].spr[tmp->spr_actual]->w);
302 tmp->bytecode_exe.x1 *= -1;
305 if (fixtoi(tmp->y) < fy - (enem_t[tmp->ene_t].spr[tmp->spr_actual]->h*2)) tmp->y = itofix(fy - (enem_t[tmp->ene_t].spr[tmp->spr_actual]->h*2));
307 if (fixtoi(tmp->y) < fy )
309 tmp->y = itofix(fy+2); /* DEBUG: mejorar esto para que no 'salte' desde arriba de pantalla! */
310 tmp->bytecode_exe.y1 *= -1;
313 // es un BOSS, no pasar de 2/3 de pantalla?
314 if (enem_t[tmp->ene_t].ia_boss)
316 if (fixtoi(tmp->y)+enem_t[tmp->ene_t].spr[tmp->spr_actual]->h > (fy+ALTO_FB) / 3 * 2 )
318 tmp->y = itofix((fy+ALTO_FB) / 3 * 2 - enem_t[tmp->ene_t].spr[tmp->spr_actual]->h);
319 tmp->bytecode_exe.y1 *= -1;
322 else
323 { // desaparecer al salir por abajo
324 if (fixtoi(tmp->y) > fy + ALTO_FB*1.05) tmp->vida = ENE_MUERTO;
327 /* Verificacion para ir limpiando la lista de enemigos muertos */
328 if (tmp->vida <= ENE_MUERTO) {
329 /* murio, eliminar y pasar al siguiente!!! */
330 *tmp_p = tmp->next;
331 free(tmp);
332 } else {
333 tmp_p = &tmp->next; /* nadie murio, siguiente por favor! */
335 } /* fin loop recorrer enemigos */
339 Esta funcion dibuja los enemigos en
340 el bitmap, desplazado x,y,
341 dibuja tambien una sombra que se desplaza
342 en relacion al borde inferior del bitmap y el centro y del mismo
343 de manera de dar un look 3D (como el viejo Rapt*r :^P )
344 TIENE que estar seteado el colormap de transparencia
346 void dibujar_enemigos(BITMAP *bmp, int x, int y)
348 ENEMIGO *tmp = enemigo_1;
350 while (tmp) {
353 /* Colocar enemigo */
354 if (enem_t[tmp->ene_t].spr[tmp->spr_actual] != NULL)
356 /* colocar la sombra */
357 colocar_sombra(bmp, enem_t[tmp->ene_t].spr_shadow[tmp->spr_actual], fixtoi(tmp->x)-x, fixtoi(tmp->y)-y);
358 draw_sprite(bmp, enem_t[tmp->ene_t].spr[tmp->spr_actual], fixtoi(tmp->x)-x, fixtoi(tmp->y)-y);
360 else
362 char errstr[1024];
363 sprintf(errstr, "ERROR: dibujar_enemigos, hay un enemigo sin sprite (clase: %d, sprite: %d)!", tmp->ene_t, tmp->spr_actual);
364 levantar_error(errstr);
368 /* DEBUG: mostrar energia del enemigo */
369 // if (KRONO_QUIERE_DEBUG)
370 // {
371 // text_mode(0);
372 // textprintf(bmp, font, fixtoi(tmp->x)-x, fixtoi(tmp->y)-y, makecol(255,255,255), "%d" , tmp->vida);
373 // }
375 tmp = tmp->next;
380 /* Esta funcion se debe llamar cuando no se precise mas la lista
381 Libera la RAM usada y reinicia la lista
383 void liberar_lista_enemigos() {
384 ENEMIGO *tmp = enemigo_1;
385 enemigo_1 = NULL;
387 while (tmp) {
388 ENEMIGO *next = tmp->next;
389 free(tmp);
390 tmp = next;
394 /* ------- DISPAROS DE LOS ENEMIGOS A PARTIR DE AQUI -------- */
397 Esta funcion agrega un disparo a la lista de disparos
398 Automaticamente lo agrega usando el arma del enemigo, etc
399 Ademas, verifica el timer, y todo lo demas.
400 Pasarle el puntero al enemigo que dispara.
402 void agregar_disparo_ene(ENEMIGO *ene)
404 int c = 0, i = 0;
406 if (ene->arma_actual < 0) return; /* enemigo desarmado */
408 /* DEBUG:
409 EJECUTAR LOS SONIDOS DEL DISPARO */
410 tocar_sonido_paneado(fixtoi(ene->x),
411 arma_ene[ene->arma_actual].snd[0],
412 rand_ex(128, 200),
413 rand_ex(900, 1100));
416 switch (arma_ene[ene->arma_actual].t)
418 case 0:
419 case 1:
420 case 4:
421 c = 1;
422 break;
424 case 5:
425 c = 5;
426 break;
428 case 2:
429 c = 3;
430 break;
432 case 3:
433 c = 2;
434 break;
436 case 6:
437 c = 4;
438 break;
440 case 7:
441 c = rand_ex(20, 30);
442 break;
444 case 8:
445 c = 20;
446 break;
448 case 9:
449 c = rand_ex(20, 30);
450 break;
452 case 10:
453 c = rand_ex(5, 30);
454 break;
455 case 11:
456 c = rand_ex(4, 8);
457 break;
459 default:
460 /* DEBUG, que paso? */
461 c = -1; /* no agregar nada! */
462 break;
465 /* Si el tipo de disparo es doble, o triple, realizar el proceso varias veces */
466 for (i=0; i<c; i++)
468 DISP_ENE *nueva = malloc(sizeof(DISP_ENE));
469 nueva->next = disp_ene_1;
470 disp_ene_1 = nueva;
472 if (nueva != NULL) /* si el malloc funciono, seteo los datos... */
475 /* Para evitar problemas, lleno todos los valores con defaults primero... */
476 /* La 'y' es comun a todos los tipos de disparos */
477 nueva->x = fixadd(ene->x, itofix(enem_t[ene->ene_t].spr[ene->spr_actual]->w/2));
478 nueva->y = fixadd(ene->y, itofix(enem_t[ene->ene_t].spr[ene->spr_actual]->h/2));
479 nueva->dx = arma_ene[ene->arma_actual].vx;
480 nueva->dy = arma_ene[ene->arma_actual].vy;
481 nueva->arma = ene->arma_actual;
482 nueva->vida = arma_ene[nueva->arma].vida;
484 /* Dependiendo del tipo de disparo, setear su posicion */
485 switch (arma_ene[nueva->arma].t)
487 case 0: /* recto */
488 nueva->x = fixadd(ene->x, itofix(rand() % enem_t[ene->ene_t].spr[ene->spr_actual]->w));
489 break;
491 case 1: /* direccion al azar */
492 case 6:
493 case 7:
494 nueva->x = fixadd(ene->x, itofix(rand() % enem_t[ene->ene_t].spr[ene->spr_actual]->w));
495 nueva->dx = ftofix((float)rand_ex(-fixtof(arma_ene[ene->arma_actual].vx)*10.0, fixtof(arma_ene[ene->arma_actual].vx)*10.0) / 10.0);
496 if (rand()%100 < 10) nueva->dx = 0;
498 nueva->dy = fmul(arma_ene[ene->arma_actual].vy, itofix(rand_ex(1, 3)) );
499 break;
501 case 2: /* abanico triple */
502 nueva->x = fixadd(ene->x, itofix(rand() % enem_t[ene->ene_t].spr[ene->spr_actual]->w));
503 if (i == 0) nueva->dx = arma_ene[ene->arma_actual].vx;
504 if (i == 1) nueva->dx = 0;
505 if (i == 2) nueva->dx = fixmul(arma_ene[ene->arma_actual].vx, itofix(-1)) ;
506 nueva->dy = arma_ene[ene->arma_actual].vy;
507 break;
509 case 3: /* doble recto */
510 nueva->x = fixadd(ene->x, itofix(rand() % enem_t[ene->ene_t].spr[ene->spr_actual]->w));
511 nueva->dx = arma_ene[ene->arma_actual].vx;
512 nueva->dy = arma_ene[ene->arma_actual].vy;
513 break;
515 case 4: /* rastreador y en un 10% al azar */
516 case 5:
517 case 8:
518 nueva->x = fixadd(ene->x, itofix(rand()% enem_t[ene->ene_t].spr[ene->spr_actual]->w));
520 if (jugador.x < ene->x ) // rastrear
521 nueva->dx = ftofix((float)rand_ex(-150, 0)/10.0);
522 else
523 nueva->dx = ftofix((float)rand_ex(0, 150)/10.0);
525 nueva->dy = arma_ene[ene->arma_actual].vy;
527 if (rand()%100 < 15) // cada tanto, al azar
529 nueva->dx = ftofix((float)rand_ex(-150, 150) / 10.0);
530 nueva->dy = fmul(arma_ene[ene->arma_actual].vy, itofix(rand_ex(1, 3)) );
533 break;
535 case 9: // en todas direcciones
536 case 10:
537 case 11:
538 nueva->x = fixadd(ene->x, itofix(rand() % enem_t[ene->ene_t].spr[ene->spr_actual]->w));
540 if (rand()%100 < 50)
541 nueva->dx = ftofix((float)rand_ex(-fixtoi(arma_ene[ene->arma_actual].vx)*10, 0)/10.0);
542 else
543 nueva->dx = ftofix((float)rand_ex(fixtoi(arma_ene[ene->arma_actual].vx)*10, 0)/10.0);
545 if (rand()%100 < 50)
546 nueva->dy = ftofix((float)rand_ex(-fixtoi(arma_ene[ene->arma_actual].vy)*10, -fixtoi(arma_ene[ene->arma_actual].vy)*5 )/10.0);
547 else
548 nueva->dy = ftofix((float)rand_ex(fixtoi(arma_ene[ene->arma_actual].vy)*10, fixtoi(arma_ene[ene->arma_actual].vy)*5)/10.0);
549 break;
551 default: /* que paso? */
552 nueva->x = fixadd(ene->x, itofix(rand() % enem_t[ene->ene_t].spr[ene->spr_actual]->w));
553 nueva->dx = ftofix((float)rand_ex(-150, 150)/10.0);
554 nueva->dy = arma_ene[ene->arma_actual].vy;
555 break;
557 } // fin switch
558 } // fin != null
559 } // fin for
563 Esta funcion actualiza la logica de los disparos
564 y los comprueba contra el jugador
565 ademas de remover los que tienen vida < 0
566 Precisa saber el desplazamiento del mapa (fy)
567 si la bomba especial del jugador esta activa, elimina los disparos!
569 void mover_disparos_ene(int fy) {
570 DISP_ENE **tmp_p = &disp_ene_1;
571 int i1; /* auxiliar para agregar estelas a los disparos */
573 while (*tmp_p) {
575 DISP_ENE *tmp = *tmp_p;
577 /* aqui muevo */
578 tmp->x = fixadd(tmp->x, tmp->dx);
579 tmp->y = fixadd(tmp->y, tmp->dy);
580 (tmp->vida)--; /* DEBUG: esto es correcto?, teoricamente, si... */
582 if (bomba_esta_activa) tmp->vida = -1; // matar disparo si esta la bomba
584 /* verificar si disparo CHOCA CON jugador */
586 if (check_pmask_collision(arma_ene[tmp->arma].mask, jugador.mask,
587 fixtoi(tmp->x), fixtoi(tmp->y),
588 fixtoi(jugador.x), fixtoi(jugador.y) ) != 0)
591 /* choco al jugador! SONIDO de colision del arma */
592 tocar_sonido_paneado(fixtoi(tmp->x),
593 arma_ene[tmp->arma].snd[1],
594 rand_ex(200,255),
595 rand_ex(900,1100));
597 tmp->vida = -1;
599 jugador.vida -= arma_ene[tmp->arma].punch;
601 if (nivel_detalle > 0) poner_explosion_nave(fixtoi(tmp->x), fixtoi(tmp->y), rand()%20+20, rand()%10+5+arma_ene[tmp->arma].punch*2, 0);
603 else /* si no choco al jugador, agregar estela de particulas - DEBUG */
605 /* DEBUG: agregar estela en particulas, [eliminar en bajos detalles!]
606 esto podria ser una funcion aparte
607 porque es bastante complicada la sintaxis... */
608 if (nivel_detalle > 7)
609 for (i1=0;
610 i1 < rand_ex(arma_ene[tmp->arma].est_cant[0], arma_ene[tmp->arma].est_cant[1]);
611 i1++)
612 agrega_particula( fixadd(tmp->x, itofix(arma_ene[tmp->arma].spr->w/2)),
613 fixadd(tmp->y, itofix(rand()%arma_ene[tmp->arma].spr->h)),
614 ftofix(rand_ex(arma_ene[tmp->arma].est_dx[0], arma_ene[tmp->arma].est_dx[1])/100.0),
615 ftofix(rand_ex(arma_ene[tmp->arma].est_dy[0], arma_ene[tmp->arma].est_dy[1])/100.0),
616 rand_ex(arma_ene[tmp->arma].est_vida[0], arma_ene[tmp->arma].est_vida[1]),
617 makecol(rand_ex(arma_ene[tmp->arma].est_color[0][0], arma_ene[tmp->arma].est_color[0][1]),
618 rand_ex(arma_ene[tmp->arma].est_color[1][0], arma_ene[tmp->arma].est_color[1][1]),
619 rand_ex(arma_ene[tmp->arma].est_color[2][0], arma_ene[tmp->arma].est_color[2][1])),
620 rand_ex(arma_ene[tmp->arma].est_rad[0], arma_ene[tmp->arma].est_rad[1]),
621 rand_ex(arma_ene[tmp->arma].est_tipo[0], arma_ene[tmp->arma].est_tipo[1]),
622 arma_ene[tmp->arma].est_transp,0,
623 NULL );
626 if (fixtoi(tmp->y) > fy + ALTO_FB ) tmp->vida = -1; /* se fue por abajo... */
627 if (fixtoi(tmp->y) < fy ) tmp->vida = -1; /* se fue por arriba... */
629 /* Remocion de disparos muertos */
630 if (tmp->vida < 0) {
631 /* murio, eliminar!!! */
632 *tmp_p = tmp->next;
633 free(tmp);
634 } else {
635 tmp_p = &tmp->next; /* siguiente por favor! */
640 /* Dibuja los disparos, desplazados por x,y
641 sobre el bitmap bmp */
642 void dibujar_disp_ene(BITMAP *bmp, int x, int y) {
644 DISP_ENE *tmp = disp_ene_1;
646 while (tmp) {
647 draw_sprite(bmp, arma_ene[tmp->arma].spr, fixtoi(tmp->x)-x, fixtoi(tmp->y)-y);
649 /* DEBUG: mostrar energia */
650 // if (KRONO_QUIERE_DEBUG)
651 // {
652 // text_mode(0);
653 // textprintf(bmp, font, fixtoi(tmp->x)-x, fixtoi(tmp->y)-y, makecol(255,255,255), "%d" , tmp->vida);
654 // }
656 tmp = tmp->next; /* proximo... */
661 /* Esta funcion se debe llamar cuando no se precise mas la lista
662 Libera la RAM usada y reinicia la lista
664 void liberar_lista_disparos_ene() {
665 DISP_ENE *tmp = disp_ene_1;
666 disp_ene_1 = NULL;
668 while (tmp) {
669 DISP_ENE *next = tmp->next;
670 free(tmp);
671 tmp = next;
675 #endif