Use an absolute directory under /usr/share/games/ for game data
[kraptor.git] / src / jugador.c
bloba2a83485f9dc49c7bd2cfb45ba86392e2fad5bc1
1 // --------------------------------------------------------
2 // jugador.c
3 // --------------------------------------------------------
4 // Copyright (c) Kronoman
5 // En memoria de mi querido padre
6 // --------------------------------------------------------
7 // Este modulo contiene todo lo relacionado con el jugador
8 // Tal como movimiento, disparos, etc...
9 // --------------------------------------------------------
10 #ifndef JUGADOR_C
11 #define JUGADOR_C
13 #include <stdio.h>
14 #include <allegro.h>
15 #include "pmask.h"
16 #include "azar.h"
17 #include "jugador.h"
18 #include "kfbuffer.h"
19 #include "sombras.h"
20 #include "mapa.h"
21 #include "combo.h"
22 #include "error.h"
23 #include "global.h"
24 #include "partic.h"
25 #include "sonido.h"
26 #include "bomba.h"
28 /* GLOBALES, son exportadas para usarlas en otros modulos... */
29 ARMA_JUG arma_tipo[MAX_ARM_CLASS]; /* tipos de armas */
30 JUGADOR jugador; /* jugador */
31 DISP_JUG *disp_jug_1 = NULL; /* puntero al 1er disparo del jugador */
32 TECLADO_JUG teclado_jug; /* teclado del jugador */
34 /* ----------- RUTINAS DEL JUGADOR ----------------- */
36 /* Esta funcion dibuja el tablero del jugador
37 La barra de energia va al costado, parada (como R...) */
38 void dibujar_tablero(BITMAP *bmp)
40 char tablero_txt[2048]; // buffer texto del tablero
41 int y = 0;
43 /* vaciar la parte vacia.. :P */
44 rectfill(bmp,
45 bmp->w - 38, bmp->h - 2,
46 bmp->w - 2 , 2,
47 makecol(16,0,0) );
49 y = bmp->h - (jugador.vida * (bmp->h-2) / MAX_ENERGIA);
51 // Barra de energia
52 if (jugador.vida > 0)
53 rectfill(bmp,
54 bmp->w - 38, bmp->h - 2,
55 bmp->w - 2 , y,
56 makecol(128,0,0) );
59 // Colocar el % de energia que queda
60 if (nivel_detalle > 3)
62 text_mode(-1);
63 textprintf_centre(bmp, hud_font, bmp->w - 20, (y < bmp->h -text_height(hud_font)) ? y : bmp->h - text_height(hud_font), makecol(255,255,255), "%d%%", (jugador.vida > 0) ? jugador.vida * 100 / MAX_ENERGIA : 0);
66 // Borde rojo
67 rect(bmp,
68 bmp->w - 38, bmp->h - 2,
69 bmp->w - 2 , 2,
70 makecol(255,0,0) );
72 // si el nivel de detalle es muy bajo, chau...
73 if (nivel_detalle < 1) return;
76 // Dinero y cantidad de balas
77 sprintf(tablero_txt,"[$%09d][%s:%04d][B:%d]", jugador.dinero, arma_tipo[jugador.arma_actual].desc_short,jugador.arma[jugador.arma_actual], jugador.bombas);
79 text_mode(-1);
82 // dependiendo del nivel de detalle, usa transparencia, o lo rebordea, o nada
83 if (nivel_detalle < 9)
85 textprintf(bmp, hud_font, 4, 4,makecol(0,0,0), "%s", tablero_txt);
87 else
89 drawing_mode(DRAW_MODE_TRANS, NULL, 0,0); // DEBUG, LENTO!
90 rectfill(bmp, 0,0, text_length(hud_font, tablero_txt)+6, text_height(hud_font)+2, makecol(32,32,32));
91 solid_mode();
94 textprintf(bmp, hud_font, 2, 2,makecol(255,255,255), "%s", tablero_txt);
97 /* Esta funcion setea el teclado a default */
98 void set_teclado_default()
100 teclado_jug.arr = KEY_UP;
101 teclado_jug.abj = KEY_DOWN;
102 teclado_jug.izq = KEY_LEFT;
103 teclado_jug.der = KEY_RIGHT;
104 teclado_jug.sht = KEY_Z;
105 teclado_jug.wpn = KEY_X;
106 teclado_jug.bmb = KEY_C;
110 Esto resetea totalmente el jugador.
111 Ideal para COMENZAR UN NUEVO JUEGO.
113 void reset_total_jugador()
115 int i;
116 reset_parcial_jugador();
117 jugador.dinero = jugador.init_money;
118 jugador.bombas = jugador.init_bombas;
120 jugador.vida = MAX_ENERGIA; /* 100 % de energia */
122 /* no tiene ningun arma, excepto la 0 */
123 for(i = 0; i < MAX_ARM_CLASS; i++)
124 jugador.arma[i] = 0;
126 jugador.arma_actual = 0; /* arma 0 seleccionada */
127 jugador.arma[0] = 1; /* tiene el arma 0 */
131 Esto resetea el jugador parcialmente, util para cuando se pasa de nivel
132 Setea la posicion al inicio del nivel, saca la aceleracion, y recarga el timer del arma
134 void reset_parcial_jugador()
136 jugador.x = itofix((W_FONDO - jugador.spr[1]->w) / 2);
137 jugador.y = itofix(H_FONDO - jugador.spr[1]->h - 5);
138 jugador.dx = jugador.dy = 0;
139 jugador.lastshoot = 0;
140 // Darle suficientes balas del arma 0, que es inifinita
141 jugador.arma[0] = 9999;
143 /* TRUCO / CHEAT - DEBUG - MODO 'DIOS' */
144 if (cheat_god_mode) jugador.dinero += 15000; // darle plata $$$
147 /* Esta funcion cambia a la proxima arma disponible */
148 void jugador_proxima_arma()
150 /* recorre el array de armas desde la actual hasta dar un loop, y
151 coloca la proxima 1era arma que aparezca */
152 int i, i2;
153 i2 = jugador.arma_actual;
155 for(i = 0; i < MAX_ARM_CLASS; i++)
157 i2++;
158 if (i2 > MAX_ARM_CLASS-1) i2 = 0;
159 if ( jugador.arma[i2] > 0 && jugador.arma_actual != i2)
161 jugador.arma_actual = i2;
162 break;
168 Esta funcion debe ser llamada en la actualizacion logica
169 para leer el teclado y actuar en consecuencia
171 void interpreta_teclado()
174 /* esta mascara de bits es el dummy driver, que el teclado, mouse o joystick modifican */
175 int tk_driver = 0;
177 #define ARR 1
178 #define ABJ 2
179 #define IZQ 4
180 #define DER 8
181 #define SHT 16
182 #define WPN 32
183 #define BMB 64
185 /* driver del mouse */
186 if (quiere_usar_mouse)
188 int mickeyx = 0; int mickeyy = 0;
190 if (mouse_needs_poll()) poll_mouse(); // debug, necesario ?
191 get_mouse_mickeys(&mickeyx, &mickeyy);
193 if (mickeyx < -32 + mouse_velocidad) tk_driver |= IZQ;
194 if (mickeyx > 32 - mouse_velocidad) tk_driver |= DER;
196 if (mickeyy < -32 + mouse_velocidad) tk_driver |= ARR;
197 if (mickeyy > 32 - mouse_velocidad) tk_driver |= ABJ;
199 if (mouse_b & 1) tk_driver |= SHT;
200 if (mouse_b & 2) tk_driver |= WPN;
201 if (mouse_b & 4) tk_driver |= BMB;
204 /* driver de joystick */
205 if (quiere_usar_joystick)
207 poll_joystick(); // absolutamente NECESARIO
209 // uso modo digital del joystick
210 if (joy[numero_de_joystick].stick[0].axis[0].d1) tk_driver |= IZQ;
211 if (joy[numero_de_joystick].stick[0].axis[0].d2) tk_driver |= DER;
213 if (joy[numero_de_joystick].stick[0].axis[1].d1) tk_driver |= ARR;
214 if (joy[numero_de_joystick].stick[0].axis[1].d2) tk_driver |= ABJ;
216 // botones - DEBUG: permitir configurar
217 // solo tomo los 3 primeros botones _existentes_
218 if (joy[numero_de_joystick].num_buttons > 0)
219 if (joy[numero_de_joystick].button[0].b) tk_driver |= SHT;
221 if (joy[numero_de_joystick].num_buttons > 1)
222 if (joy[numero_de_joystick].button[1].b)
224 joy[numero_de_joystick].button[1].b = 0; // hack horrible!
225 tk_driver |= WPN;
228 if (joy[numero_de_joystick].num_buttons > 2)
230 if (joy[numero_de_joystick].button[2].b) tk_driver |= BMB;
232 else if (joy[numero_de_joystick].num_buttons > 1) /* emular 3er boton, con los dos primeros apretados */
234 if ((joy[numero_de_joystick].button[0].b) && (joy[numero_de_joystick].button[1].b)) tk_driver |= BMB;
238 /* driver de teclado, siempre funciona */
239 if (keyboard_needs_poll()) poll_keyboard();
241 if (key[teclado_jug.der] ) tk_driver |= DER;
242 if (key[teclado_jug.izq] ) tk_driver |= IZQ;
243 if (key[teclado_jug.abj] ) tk_driver |= ABJ;
244 if (key[teclado_jug.arr] ) tk_driver |= ARR;
246 if (key[teclado_jug.wpn] )
248 tk_driver |= WPN;
249 key[teclado_jug.wpn] = FALSE; /* hack horrible! */
251 if (key[teclado_jug.sht] ) tk_driver |= SHT;
252 if (key[teclado_jug.bmb] ) tk_driver |= BMB;
256 /* Notar que el movimiento izq-der es instantaneo (imito a R??t?r) */
257 if (tk_driver & DER) // derecha
259 if (jugador.dx < 0)
260 jugador.dx = 0;
261 else
262 jugador.dx = fixadd(jugador.dx, ftofix(VEL_X_J));
266 if (tk_driver & IZQ) // izquierda
268 if (jugador.dx > 0)
269 jugador.dx = 0;
270 else
271 jugador.dx = fixsub(jugador.dx, ftofix(VEL_X_J));
275 if (tk_driver & ARR)
277 if (jugador.dy > 0)
278 jugador.dy = 0;
279 else
280 jugador.dy = fixsub(jugador.dy, ftofix(VEL_Y_J));
284 if (tk_driver & ABJ)
286 if (jugador.dy < 0)
287 jugador.dy = 0;
288 else
289 jugador.dy = fixadd(jugador.dy, ftofix(VEL_Y_J));
293 if (tk_driver & SHT) agregar_disparo_jug(); /* disparar */
295 if (tk_driver & WPN) /* proxima arma... */
297 jugador_proxima_arma();
301 Agregado 16/12/2003
302 esto soluciona un 'bug' en el cual, si se presiona LEFT/RIGHT, se aprieta UP/DOWN y se suelta,
303 la cosa sigue moviendo loca, no se porque
305 descripcion del problema reportado por Ysaneya
306 For example, say your ship is at the bottom center of the screen. You press the up and left arrows at the same time, to make it go into the up-left direction. Your ship starts moving, fine.
307 Now, while the ship is moving, you release the up arrow, keeping the left arrow pressed. Your ship should logically move to the left, and slowly stop moving up, right ?
308 Well no, it continues the exact same movement in the up-left direction. That's why it's unplayable. Can't avoid any bullets.
311 if (jugador.vida > 1)
313 if (!(tk_driver & DER) && !(tk_driver & IZQ)) jugador.dx = 0;
314 if (!(tk_driver & ARR) && !(tk_driver & ABJ)) jugador.dy = 0;
317 if (tk_driver & BMB) // lanzar bomba especial
319 if (jugador.bombas > 0 && !bomba_esta_activa)
321 jugador.bombas --;
322 bomba_esta_activa = TRUE;
323 bomba_detonacion = 7; // tiempo de destruccion masiva... :)
324 detonar_totalmente_el_piso(scroll_mapa);
326 // sonido!
327 if (bomba_sonido != NULL) tocar_sonido(bomba_sonido, 255, 128, 1000);
334 /* Esta funcion mueve el jugador, y no permite que se salga de pantalla, etc
335 Precisa saber el desplazamiento 'y' del mapa
336 Ademas, verifica la vida que le queda al jugador,hecha humo, lo explota y lo mata... :P
338 void mover_jugador(int fy) {
340 /* TRUCO / CHEAT - DEBUG - MODO 'DIOS' */
341 if (cheat_god_mode) jugador.vida = MAX_ENERGIA;
343 if (jugador.dx > ftofix(MAX_VEL_J_X) ) jugador.dx = ftofix(MAX_VEL_J_X);
344 if (jugador.dy > ftofix(MAX_VEL_J_Y) ) jugador.dy = ftofix(MAX_VEL_J_Y);
346 if (jugador.dx < ftofix(MAX_VEL_J_X * (-1.0)) ) jugador.dx = ftofix(MAX_VEL_J_X * (-1.0));
347 if (jugador.dy < ftofix(MAX_VEL_J_Y * (-1.0)) ) jugador.dy = ftofix(MAX_VEL_J_Y * (-1.0));
349 jugador.x = fixadd (jugador.x, jugador.dx);
350 jugador.y = fixadd (jugador.y, jugador.dy);
352 if (jugador.dx > 0) {
353 jugador.dx = fixsub(jugador.dx, ftofix(FRC_X_J));
354 if (jugador.dx < 0) jugador.dx = 0;
357 if (jugador.dx < 0) {
358 jugador.dx = fixadd(jugador.dx, ftofix(FRC_X_J));
359 if (jugador.dx > 0) jugador.dx = 0;
362 if (jugador.dy > 0) {
363 jugador.dy = fixsub(jugador.dy, ftofix(FRC_Y_J));
364 if (jugador.dy < 0) jugador.dy = 0;
367 if (jugador.dy < 0) {
368 jugador.dy = fixadd(jugador.dy, ftofix(FRC_Y_J));
369 if (jugador.dy > 0) jugador.dy = 0;
372 if (jugador.y < 0) jugador.y = 0;
374 if (jugador.x < 0) jugador.x = 0;
376 if (fixtoi(jugador.x) > ANCHO_FB - jugador.spr[1]->w ) jugador.x = itofix(ANCHO_FB - jugador.spr[1]->w);
378 if (fixtoi(jugador.y) < fy ) jugador.y = itofix(fy);
379 if (fixtoi(jugador.y) > fy + ALTO_FB - jugador.spr[1]->h ) jugador.y = itofix(fy + ALTO_FB - jugador.spr[1]->h);
381 jugador.lastshoot--; /* ir recargando arma */
382 if (jugador.lastshoot < 0) jugador.lastshoot = 0;
385 /* Energia del jugador... exploto? combustionar al maldito!
386 y hacerle perder el control! */
387 if (jugador.vida < 1)
389 jugador.vida -= rand()%3+1; /* combustiono la nave */
391 if (rand()%100 < abs((jugador.vida * 100) / JUG_MUERTO) ) /* incremental al irse combustionando */
393 /* agregar explosiones peque~as... */
394 pone_explo_pixel(&ptr_explo_arriba,
395 fixtoi(jugador.x)+rand()%jugador.spr[1]->w,
396 fixtoi(jugador.y)+rand()%jugador.spr[1]->h,
397 rand()%jugador.spr[1]->w + jugador.spr[1]->w/3,
398 rand()%30+10,
399 ftofix(0.01));
400 /* descontrolar la nave */
401 if (rand()%100 < 25)
403 jugador.dx = (rand()%100 < 50) ? ftofix(MAX_VEL_J_X * (-1.0)) : ftofix(MAX_VEL_J_X);
404 jugador.dy = (rand()%100 < 50) ? ftofix(MAX_VEL_J_Y * (-1.0)) : ftofix(MAX_VEL_J_Y);
408 /* al aproximarse al final, recontra-explotar con pedazos y todo... */
409 if (jugador.vida < (JUG_MUERTO / 4) )
410 poner_explosion_nave(fixtoi(jugador.x)+jugador.spr[1]->w/2, fixtoi(jugador.y)+jugador.spr[1]->h/2, rand()%20+20, rand()%40+40, (rand()%100 < 25) ? -1 : 0);
412 if (jugador.vida <= JUG_MUERTO) /* ahora si murio... */
414 /* accionar en consecuencia... */
415 salir_del_juego = TRUE;
418 else
420 /* Si aun esta vivo, y la energia del jugador es < 20 %, hechar humo y chispas, proporcional al jugador */
421 if ((jugador.vida * 100 / MAX_ENERGIA < 30) && (nivel_detalle > 8) )
423 if (rand()%((jugador.vida * 100 / MAX_ENERGIA)+1)< 15) // a medida que se quema, larga mas humo, notar el +1 impide division por 0
425 int col, it;
426 col = rand()%32+16;
427 // humo
428 for (it=0; it < rand()%3+1; it++)
429 agrega_particula( fixadd(jugador.x, itofix(jugador.spr[1]->w/2 + rand_ex(10,-10))), fixadd(jugador.y, itofix(jugador.spr[1]->h + rand_ex(0, -5))),
430 fixmul(jugador.dx, ftofix( (float)rand_ex(0, -25)/100.0 ) ), ftofix((float)rand_ex(25, 70)/10.0),
431 rand_ex(5,15),
432 makecol(col,col,col), rand_ex(3,5), 1,
433 -1, ftofix((float)rand_ex(5, 15)/10.0),
434 NULL);
435 // chispa
436 for (it=0; it < rand()%3+1; it++)
437 agrega_particula( fixadd(jugador.x, itofix(jugador.spr[1]->w/2 + rand_ex(10,-10))), fixadd(jugador.y, itofix(jugador.spr[1]->h + rand_ex(0, -5))),
438 ftofix( (float)rand_ex(25, -25)/10.0 ),
439 ftofix((float)rand_ex(10, 30)/10.0),
440 rand_ex(3,10),
441 makecol(255,rand()%255,0),
442 rand_ex(1,2),
444 0, 0,NULL);
453 Esta funcion dibuja la nave del jugador en
454 el bitmap, desplazado x,y,
455 dibuja tambien una sombra que se desplaza
456 en relacion al borde inferior del bitmap y el centro y del mismo
457 de manera de dar un look 3D (como el viejo Rapt*r :^P )
458 TIENE que estar seteado el colormap de transparencia
460 void dibujar_nave_jugador(BITMAP *bmp, int x, int y)
462 int idx = 0;
463 /* Ver que sprite dibujar, si se esta inclinando izq-med-der */
464 if (jugador.dx > ftofix(-4.5) && jugador.dx < ftofix(4.5)) /* medio.. */
466 idx = 1;
468 else
470 if (jugador.dx < 0) /* izq */
471 idx = 0;
472 else
473 idx = 2;
475 /* colocar la sombra */
476 colocar_sombra(bmp, jugador.spr[idx+3], fixtoi(jugador.x)-x, fixtoi(jugador.y)-y);
478 /* FALTA dibujar estela del motor - DEBUG */
480 /* Colocar jugador */
481 draw_sprite(bmp, jugador.spr[idx], fixtoi(jugador.x)-x, fixtoi(jugador.y)-y);
484 /* ----------- RUTINAS DE LA LISTA DE DISPAROS ----------------- */
487 Esta funcion agrega un disparo a la lista de disparos
488 Automaticamente lo agrega usando el arma del jugador, etc
489 Ademas, verifica el timer, y todo lo demas.
491 void agregar_disparo_jug()
493 int c = 0, i = 0; // auxiliares
495 if (jugador.arma_actual < 0) return; /* jugador desarmado? shit! */
497 if (jugador.lastshoot > 0 ) return; /* NO es tiempo de poder disparar todavia */
499 if (jugador.vida < 0) return; /* esta muerto... no tenes armas! chau salame... */
501 // Verificar cantidad de balas, a menos que sea el arma 'infinita' (0)
502 if (jugador.arma[jugador.arma_actual] < 1 && jugador.arma_actual != 0)
504 // poner el arma siguiente disponible
505 jugador_proxima_arma();
506 return;
508 else
510 // Descontar balas
511 if (jugador.arma_actual != 0) jugador.arma[jugador.arma_actual]--;
512 if (jugador.arma[jugador.arma_actual] < 0) jugador.arma[jugador.arma_actual] = 0;
515 jugador.lastshoot = arma_tipo[jugador.arma_actual].firerate;
517 /* EJECUTAR LOS SONIDOS DEL DISPARO EN GLORIOSO STEREO */
518 tocar_sonido_paneado(fixtoi(jugador.x),
519 arma_tipo[jugador.arma_actual].snd[0],
520 rand_ex(240, 255),
521 rand_ex(900, 1100));
523 switch (arma_tipo[jugador.arma_actual].t)
525 case 1:
526 case 0:
527 c = 1;
528 break;
530 case 2:
531 case 5:
532 c = 3;
533 break;
535 case 3:
536 case 4:
537 c = 2;
538 break;
540 case 6: // flak... invento especial... :P
541 c = 8;
542 break;
544 default:
545 /* DEBUG: arma desconocida, no agregar nada.. */
546 c = -1;
547 break;
550 /* ir agregando disparos */
551 for (i=0; i<c; i++) /* Si el tipo de disparo es doble, o triple, realizar el proceso varias veces */
553 DISP_JUG *nueva = malloc(sizeof(DISP_JUG));
554 nueva->next = disp_jug_1;
555 disp_jug_1 = nueva;
557 if (nueva != NULL) /* si el malloc funciono, seteo los datos... */
559 nueva->arma = jugador.arma_actual;
560 nueva->vida = arma_tipo[jugador.arma_actual].vida;
562 // valores default de coordenadas, genericos para todos los disparos
563 nueva->y = fixadd(jugador.y, itofix(jugador.spr[1]->h - arma_tipo[jugador.arma_actual].spr->h)); // la y sale del fondo de la nave
564 nueva->x = fixadd(jugador.x, itofix(jugador.spr[1]->w/2 - arma_tipo[jugador.arma_actual].spr->w / 2)); // la x sale del centro de la nave
566 nueva->dx = arma_tipo[jugador.arma_actual].vx;
567 nueva->dy = arma_tipo[jugador.arma_actual].vy;
569 /* Dependiendo del tipo de disparo, setear su posicion */
570 switch (arma_tipo[jugador.arma_actual].t)
572 case 0: /* recto */
573 nueva->dx = arma_tipo[jugador.arma_actual].vx;
574 nueva->dy = arma_tipo[jugador.arma_actual].vy;
575 break;
577 case 1: /* direccion al azar */
578 if (arma_tipo[jugador.arma_actual].vx == 0) arma_tipo[jugador.arma_actual].vx = itofix(5);
580 nueva->dx = ftofix((float)rand_ex(-fixtoi(arma_tipo[jugador.arma_actual].vx)*10, fixtoi(arma_tipo[jugador.arma_actual].vx)*10)/10.0);
581 nueva->dy = arma_tipo[jugador.arma_actual].vy;
582 break;
584 case 2: /* abanico triple */
585 /* verificacion de seguridad */
586 if (arma_tipo[jugador.arma_actual].vx == 0) arma_tipo[jugador.arma_actual].vx = itofix(5);
588 if (i == 0) nueva->dx = arma_tipo[jugador.arma_actual].vx;
589 if (i == 1) nueva->dx = 0;
590 if (i == 2) nueva->dx = fixmul(itofix(-1), arma_tipo[jugador.arma_actual].vx);
591 nueva->dy = arma_tipo[jugador.arma_actual].vy;
592 break;
594 case 3: /* doble recto, vx controla la apertura del disparo (debe ser >= 0) */
596 if (i == 0)
598 nueva->x = fixadd(jugador.x, itofix(jugador.spr[1]->w - arma_tipo[jugador.arma_actual].spr->w/2));
599 nueva->dx = arma_tipo[jugador.arma_actual].vx;
601 else
603 nueva->x = fixsub(jugador.x, itofix(arma_tipo[jugador.arma_actual].spr->w/2));
604 nueva->dx = fixmul(itofix(-1),arma_tipo[jugador.arma_actual].vx);
607 nueva->dy = arma_tipo[jugador.arma_actual].vy;
608 break;
610 case 4: /* 1 del centro, 1 al azar por disparo */
611 if (i == 0)
613 nueva->dx = arma_tipo[jugador.arma_actual].vx;
614 nueva->dy = arma_tipo[jugador.arma_actual].vy;
616 else
618 nueva->dx = ftofix((float)rand_ex(-50, 50)/10.0);
619 nueva->dy = arma_tipo[jugador.arma_actual].vy;
621 break;
623 case 5: // 1 del centro, 1 de la izq, 1 de la derecha (tipo misile pod, incluye una variacion del 10% al azar en la velocidad en y, para efecto misile pod)
624 // el disparo 0 sale del centro, por default
625 if (i == 1) nueva->x = fixadd(jugador.x, itofix(jugador.spr[1]->w - arma_tipo[jugador.arma_actual].spr->w/2));
626 if (i == 2) nueva->x = fixsub(jugador.x, itofix(arma_tipo[jugador.arma_actual].spr->w/2));
627 nueva->dy = fixmul(nueva->dy, ftofix( (float)(100 + rand_ex(-10, 10))/100.0 ) );
628 break;
629 case 6: // ca~on de flak
630 if (i == 0) nueva->x = fixadd(jugador.x, itofix(jugador.spr[1]->w - arma_tipo[jugador.arma_actual].spr->w/2));
631 if (i == 1) nueva->x = fixsub(jugador.x, itofix(arma_tipo[jugador.arma_actual].spr->w/2));
633 if (i > 1)
634 nueva->dx = ftofix((float)rand_ex(-fixtoi(arma_tipo[jugador.arma_actual].vx)*10, fixtoi(arma_tipo[jugador.arma_actual].vx)*10)/10.0);
635 else
636 nueva->dx = 0;
638 break;
640 default: /* ARMA desconocida - DEBUG */
641 nueva->dx = 0;
642 nueva->dy = itofix(-15);
643 break;
645 } /* fin switch */
647 /* Al terminar de setear el disparo, agrego una explosion, indicando
648 que de alli salio el disparo... */
649 /* DEBUG, con el dibujo de la explosion se ve horrible! habria que
650 dibujar algo mejor... tipo una flama larga o algo */
652 // pone_explo_pixel(&ptr_explo_arriba,
653 // fixtoi(nueva->x),
654 // fixtoi(nueva->y),
655 // rand()%15+10,
656 // rand()%5+5,
657 // ftofix(0.01));
659 } /* fin != NULL */
660 } /* fin for */
664 Esta funcion actualiza la logica de los disparos
665 ademas de remover los que tienen vida < 0
666 y colocar particulas donde se mueven (si tiene un proyector de particulas ON)
667 Precisa saber el desplazamiento del mapa (fy)
669 void mover_disparos_jug(int fy) {
670 DISP_JUG **tmp_p = &disp_jug_1;
671 int i1; /* auxiliar para el for de la particula */
674 while (*tmp_p) {
675 DISP_JUG *tmp = *tmp_p;
677 /* aqui muevo */
678 tmp->x = fixadd(tmp->x, tmp->dx);
679 tmp->y = fixadd(tmp->y, tmp->dy);
680 (tmp->vida)--;
682 /* DEBUG: agregar estela en particulas,
683 esto podria ser una funcion aparte porque es bastante complicada la sintaxis... */
684 if (nivel_detalle > 5)
685 for (i1=0;
686 i1 < rand_ex(arma_tipo[tmp->arma].est_cant[0], arma_tipo[tmp->arma].est_cant[1]);
687 i1++)
688 agrega_particula( fixadd(tmp->x, itofix(arma_tipo[tmp->arma].spr->w/2)),
689 fixadd(tmp->y, itofix(arma_tipo[tmp->arma].spr->h)),
690 ftofix(rand_ex(arma_tipo[tmp->arma].est_dx[0], arma_tipo[tmp->arma].est_dx[1])/100.0),
691 ftofix(rand_ex(arma_tipo[tmp->arma].est_dy[0], arma_tipo[tmp->arma].est_dy[1])/100.0),
692 rand_ex(arma_tipo[tmp->arma].est_vida[0], arma_tipo[tmp->arma].est_vida[1]),
693 makecol(rand_ex(arma_tipo[tmp->arma].est_color[0][0], arma_tipo[tmp->arma].est_color[0][1]),
694 rand_ex(arma_tipo[tmp->arma].est_color[1][0], arma_tipo[tmp->arma].est_color[1][1]),
695 rand_ex(arma_tipo[tmp->arma].est_color[2][0], arma_tipo[tmp->arma].est_color[2][1])),
696 rand_ex(arma_tipo[tmp->arma].est_rad[0],arma_tipo[tmp->arma].est_rad[1]),
697 rand_ex(arma_tipo[tmp->arma].est_tipo[0], arma_tipo[tmp->arma].est_tipo[1]),
698 arma_tipo[tmp->arma].est_transp,0,
699 NULL );
702 /* LA VERIFICACION SI CHOCA EL DISPARO CONTRA LOS ENEMIGOS SE HACE EN enemigo.c!!! */
704 /* Verificar si rompio el fondo y quemarlo!!!! */
705 /* Si explota, el disparo se elimina gradualmente */
706 if (explotar_fondo((fixtoi(tmp->x)+arma_tipo[tmp->arma].spr->w/2)/W_GR,
707 (fixtoi(tmp->y)+arma_tipo[tmp->arma].spr->h/2)/H_GR,
708 arma_tipo[tmp->arma].punch*1.5))
710 tmp->vida /= 2;
713 if (fixtoi(tmp->y) < fy - ALTO_FB/4 ) tmp->vida = -1; /* el disparo se fue por arriba */
714 if (fixtoi(tmp->y) > fy + ALTO_FB*2 ) tmp->vida = -1; /* el disparo se fue por abajo */
716 /* Remocion de disparos muertos */
717 if (tmp->vida < 0) {
718 /* murio, eliminar!!! */
719 *tmp_p = tmp->next;
720 free(tmp);
722 else
724 tmp_p = &tmp->next; /* siguiente por favor! */
729 /* Dibuja los disparos, desplazados por x,y
730 sobre el bitmap bmp */
731 void dibujar_disp_jug(BITMAP *bmp, int x, int y) {
733 DISP_JUG *tmp = disp_jug_1;
735 while (tmp)
737 draw_sprite(bmp, arma_tipo[tmp->arma].spr, fixtoi(tmp->x)-x, fixtoi(tmp->y)-y);
739 // if (KRONO_QUIERE_DEBUG)
740 // {
741 // text_mode(0);
742 // textprintf(bmp, font, fixtoi(tmp->x)-x, fixtoi(tmp->y)-y, makecol(255,255,255), "%d" , tmp->vida);
743 // }
745 tmp = tmp->next; /* proximo... */
750 /* Esta funcion se debe llamar cuando no se precise mas la lista
751 Libera la RAM usada y reinicia la lista
753 void liberar_lista_disparos_jug() {
754 DISP_JUG *tmp = disp_jug_1;
755 disp_jug_1 = NULL;
757 while (tmp) {
758 DISP_JUG *next = tmp->next;
759 free(tmp);
760 tmp = next;
764 #endif