source: libcaca/trunk/src/weapons.c @ 143

Last change on this file since 143 was 143, checked in by Sam Hocevar, 18 years ago
  • src/weapons.c data/weapon_fragbomb: + Drew the fragbomb sprite. + Use the fragbomb in src/weapons.c.
  • Property svn:keywords set to Id
File size: 14.7 KB
Line 
1/*
2 *   ttyvaders     Textmode shoot'em up
3 *   Copyright (c) 2002 Sam Hocevar <sam@zoy.org>
4 *                 All Rights Reserved
5 *
6 *   $Id: weapons.c 143 2003-11-10 22:43:30Z sam $
7 *
8 *   This program is free software; you can redistribute it and/or modify
9 *   it under the terms of the GNU General Public License as published by
10 *   the Free Software Foundation; either version 2 of the License, or
11 *   (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include "config.h"
24
25#include <stdlib.h>
26
27#include "common.h"
28
29static void draw_bomb(int x, int y, int vx, int vy);
30static void draw_nuke(int x, int y, int frame);
31static void draw_beam(int x, int y, int frame);
32static void draw_fragbomb(int x, int y, int frame);
33
34struct ee_sprite *bomb_sprite;
35struct ee_sprite *fragbomb_sprite;
36
37void init_weapons(game *g, weapons *wp)
38{
39    int i;
40
41    for(i = 0; i < WEAPONS; i++)
42    {
43        wp->type[i] = WEAPON_NONE;
44    }
45
46    bomb_sprite = ee_load_sprite("data/weapon_bomb");
47    fragbomb_sprite = ee_load_sprite("data/weapon_fragbomb");
48}
49
50void draw_weapons(game *g, weapons *wp)
51{
52    int i;
53
54    for(i = 0; i < WEAPONS; i++)
55    {
56        switch(wp->type[i])
57        {
58            case WEAPON_LASER:
59                ee_color(EE_WHITE);
60                ee_goto(wp->x[i] >> 4, wp->y[i] >> 4);
61                ee_putchar('|');
62                ee_color(EE_CYAN);
63                ee_goto(wp->x[i] >> 4, (wp->y[i] >> 4) + 1);
64                ee_putchar('|');
65                break;
66            case WEAPON_SEEKER:
67                ee_color(EE_CYAN);
68                ee_goto(wp->x3[i] >> 4, wp->y3[i] >> 4);
69                ee_putchar('.');
70                ee_goto(wp->x2[i] >> 4, wp->y2[i] >> 4);
71                ee_putchar('o');
72                ee_color(EE_WHITE);
73                ee_goto(wp->x[i] >> 4, wp->y[i] >> 4);
74                ee_putchar('@');
75                break;
76            case WEAPON_BOMB:
77                ee_color(EE_GRAY);
78                ee_goto((wp->x[i] - wp->vx[i]) >> 4, (wp->y[i] - wp->vy[i]) >> 4);
79                ee_putchar('.');
80                ee_goto((wp->x3[i] - wp->vx[i]) >> 4, (wp->y3[i] - wp->vy[i]) >> 4);
81                ee_putchar('.');
82                ee_goto((wp->x2[i] - wp->vx[i]) >> 4, (wp->y2[i] - wp->vy[i]) >> 4);
83                ee_putchar('.');
84                ee_goto(wp->x3[i] >> 4, wp->y3[i] >> 4);
85                ee_putchar('.');
86                ee_goto(wp->x2[i] >> 4, wp->y2[i] >> 4);
87                ee_putchar('.');
88                draw_bomb(wp->x[i] >> 4, wp->y[i] >> 4, wp->vx[i], wp->vy[i]);
89                break;
90            case WEAPON_FRAGBOMB:
91                draw_fragbomb(wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]);
92                break;
93            case WEAPON_BEAM:
94                draw_beam(wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]);
95                break;
96            case WEAPON_NUKE:
97                draw_nuke(wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]);
98                break;
99            case WEAPON_LIGHTNING:
100            case WEAPON_NONE:
101                break;
102        }
103    }
104}
105
106void update_weapons(game *g, weapons *wp)
107{
108    int i, j, dist, xmin, ymin, dx, dy, xnew, ynew;
109
110    for(i = 0; i < WEAPONS; i++)
111    {
112        switch(wp->type[i])
113        {
114            case WEAPON_LASER:
115                wp->x[i] += wp->vx[i];
116                wp->y[i] += wp->vy[i];
117                if(wp->y[i] < 0)
118                {
119                    wp->type[i] = WEAPON_NONE;
120                }
121                break;
122            case WEAPON_BOMB:
123            case WEAPON_SEEKER:
124                /* Update tail */
125                wp->x3[i] = wp->x2[i];
126                wp->y3[i] = wp->y2[i];
127
128                wp->x2[i] = wp->x[i];
129                wp->y2[i] = wp->y[i];
130
131                wp->x[i] += wp->vx[i];
132                wp->y[i] += wp->vy[i];
133
134                if(wp->y[i] < 0)
135                {
136                    wp->type[i] = WEAPON_NONE;
137                    break;
138                }
139
140                if(wp->n[i] < 0)
141                {
142                    /* Stop updating direction */
143                    break;
144                }
145
146                wp->n[i]--;
147
148                /* Estimate our position next frames */
149                xnew = wp->x[i] + wp->vx[i];
150                ynew = wp->y[i] + wp->vy[i];
151
152                xmin = xnew;
153                ymin = - (g->h << 4);
154                dist = (xnew - xmin) * (xnew - xmin)
155                        + 4 * (ynew - ymin) * (ynew - ymin);
156
157                /* Find the nearest alien */
158                for(j = 0; j < ALIENS; j++)
159                {
160                    if(g->al->type[j] != ALIEN_NONE)
161                    {
162                        int alx = g->al->x[j] << 4;
163                        int aly = g->al->y[j] << 4;
164                        int new = (xnew - alx) * (xnew - alx)
165                                   + 4 * (ynew - aly) * (ynew - aly);
166                        if(new <= dist)
167                        {
168                            dist = new;
169                            xmin = alx;
170                            ymin = aly;
171                        }
172                    }
173                }
174
175                /* Find our new direction */
176                dx = xmin - wp->x[i];
177                dy = ymin - wp->y[i];
178
179                /* Normalize direction */
180                if(dx | dy)
181                {
182                    int norm = ee_sqrt(dx * dx + 4 * dy * dy);
183                    dx = dx * 32 / norm;
184                    dy = dy * 32 / norm;
185                }
186
187                /* Find our new speed */
188                dx = (dx + 3 * wp->vx[i]) / 4;
189                dy = (dy + 3 * wp->vy[i]) / 4;
190
191                /* Normalize speed */
192                if(dx | dy)
193                {
194                    int norm = ee_sqrt(dx * dx + 4 * dy * dy);
195                    wp->vx[i] = dx * 32 / norm;
196                    wp->vy[i] = dy * 32 / norm;
197                }
198
199                break;
200
201            case WEAPON_FRAGBOMB:
202                /* If n was set to -1, the fragbomb just exploded */
203                if(wp->n[i] == -1)
204                {
205                    int coords[] =
206                    {
207                        32,  0,   -32,  0,    0,  16,     0, -16,
208                        28,  8,   -28,  8,   28,  -8,   -28,  -8,
209                        24, 12,   -24, 12,   24, -12,   -24, -12,
210                        16, 14,   -16, 14,   16, -14,   -16, -14
211                    };
212
213                    for(j = 0 ; j < sizeof(coords) / sizeof(int) ; j += 2)
214                    {
215                        add_weapon(g, g->wp, wp->x[i] + coords[j], wp->y[i] + coords[j+1] / 2, coords[j], coords[j+1], WEAPON_SEEKER);
216                        add_weapon(g, g->wp, wp->x[i] + coords[j] / 2, wp->y[i] + coords[j+1], coords[j], coords[j+1], WEAPON_SEEKER);
217                    }
218
219                    wp->type[i] = WEAPON_NONE;
220                }
221
222                wp->x[i] += wp->vx[i];
223                wp->y[i] += wp->vy[i];
224                wp->n[i]++;
225                if(wp->y[i] < 0)
226                {
227                    wp->type[i] = WEAPON_NONE;
228                }
229                break;
230
231            case WEAPON_BEAM:
232                wp->x[i] = (g->p->x + 2) << 4;
233                wp->y[i] = g->p->y << 4;
234                wp->n[i]--;
235                if(wp->n[i] < 0)
236                {
237                    wp->type[i] = WEAPON_NONE;
238                }
239                break;
240            case WEAPON_NUKE:
241                wp->n[i]--;
242                if(wp->n[i] < 0)
243                {
244                    wp->type[i] = WEAPON_NONE;
245                }
246                break;
247            case WEAPON_LIGHTNING:
248            case WEAPON_NONE:
249                break;
250        }
251    }
252}
253
254void add_weapon(game *g, weapons *wp, int x, int y, int vx, int vy, int type)
255{
256    int i;
257
258    for(i = 0; i < WEAPONS; i++)
259    {
260        if(wp->type[i] == WEAPON_NONE)
261        {
262            wp->x[i] = x;
263            wp->y[i] = y;
264            wp->vx[i] = vx;
265            wp->vy[i] = vy;
266            wp->type[i] = type;
267            wp->n[i] = 0;
268            switch(type)
269            {
270                case WEAPON_LASER:
271                    break;
272                case WEAPON_FRAGBOMB:
273                    break;
274                case WEAPON_SEEKER:
275                case WEAPON_BOMB:
276                    wp->x2[i] = x;
277                    wp->y2[i] = y;
278                    wp->x3[i] = x;
279                    wp->y3[i] = y;
280                    wp->n[i] = 20;
281                    break;
282                case WEAPON_BEAM:
283                    wp->n[i] = 25;
284                    break;
285                case WEAPON_NUKE:
286                    wp->n[i] = 25;
287                    break;
288                case WEAPON_NONE:
289                    break;
290            }
291            break;
292        }
293    }
294}
295
296static void draw_bomb(int x, int y, int vx, int vy)
297{
298    int frame;
299
300    /* We have 1x2 pixels */
301    vy *= 2;
302
303    if(vx > vy)
304    {
305        if(vx > -vy) /* right quarter */
306        {
307            if(vy > vx/4)
308                frame = 0; /* -pi/6 */
309            else if(vy < -vx/4)
310                frame = 1; /* pi/6 */
311            else
312                frame = 2; /* 0pi/6 */
313        }
314        else /* top quarter */
315        {
316            if(vx > -vy/4)
317                frame = 3; /* 2pi/6 */
318            else if(vx < vy/4)
319                frame = 4; /* 4pi/6 */
320            else
321                frame = 5; /* 3pi/6 */
322        }
323    }
324    else
325    {
326        if(vx > -vy) /* bottom quarter */
327        {
328            if(vx > vy/4)
329                frame = 6; /* -2pi/6 */
330            else if(vx < -vy/4)
331                frame = 7; /* -4pi/6 */
332            else
333                frame = 8; /* -3pi/6 */
334        }
335        else /* left quarter */
336        {
337            if(vy > -vx/4)
338                frame = 9; /* -5pi/6 */
339            else if(vy < vx/4)
340                frame = 10; /* 5pi/6 */
341            else
342                frame = 11; /* 6pi/6 */
343        }
344    }
345
346    ee_set_sprite_frame(bomb_sprite, frame);
347    ee_draw_sprite(x, y, bomb_sprite);
348}
349
350static void draw_fragbomb(int x, int y, int frame)
351{
352    /* Draw the head */
353    ee_set_sprite_frame(fragbomb_sprite, frame & 1);
354    ee_draw_sprite(x, y, fragbomb_sprite);
355
356    /* Draw the tail */
357    ee_set_sprite_frame(fragbomb_sprite, 2 + (frame % 4));
358    ee_draw_sprite(x, y, fragbomb_sprite);
359}
360
361static void draw_beam(int x, int y, int frame)
362{
363    int r = (29 - frame) * (29 - frame) / 8;
364    int i;
365
366    switch(frame)
367    {
368        case 24:
369            ee_color(EE_WHITE);
370            ee_goto(x, y-3);
371            ee_putstr("__");
372            ee_goto(x-1, y-2);
373            ee_putchar('\'');
374            ee_goto(x+2, y-2);
375            ee_putchar('`');
376            break;
377        case 23:
378            ee_color(EE_CYAN);
379            ee_goto(x, y-3);
380            ee_putstr("__");
381            ee_color(EE_WHITE);
382            ee_goto(x-2, y-2);
383            ee_putstr("-'");
384            ee_goto(x+2, y-2);
385            ee_putstr("`-");
386            break;
387        case 22:
388            ee_color(EE_CYAN);
389            ee_goto(x, y-3);
390            ee_putstr("__");
391            ee_goto(x-1, y-2);
392            ee_putchar('\'');
393            ee_goto(x+2, y-2);
394            ee_putchar('`');
395            ee_color(EE_WHITE);
396            ee_goto(x-3, y-2);
397            ee_putstr(",-");
398            ee_goto(x+3, y-2);
399            ee_putstr("-.");
400            break;
401        case 21:
402            ee_color(EE_CYAN);
403            ee_goto(x-1, y-3);
404            ee_putstr("____");
405            ee_goto(x-2, y-2);
406            ee_putchar('\'');
407            ee_goto(x+3, y-2);
408            ee_putchar('`');
409            ee_color(EE_WHITE);
410            ee_goto(x-4, y-2);
411            ee_putstr(",-");
412            ee_goto(x+4, y-2);
413            ee_putstr("-.");
414            break;
415        case 20:
416            ee_color(EE_WHITE);
417            ee_goto(x, y-3);
418            ee_putstr("%%");
419            ee_goto(x-4, y-2);
420            ee_putchar(',');
421            ee_goto(x+5, y-2);
422            ee_putchar('.');
423            ee_color(EE_CYAN);
424            ee_goto(x-1, y-3);
425            ee_putchar(':');
426            ee_goto(x+2, y-3);
427            ee_putchar(':');
428            ee_goto(x-3, y-2);
429            ee_putstr("-'");
430            ee_goto(x+3, y-2);
431            ee_putstr("`-");
432            break;
433        case 19:
434            ee_color(EE_WHITE);
435            ee_goto(x, y-4);
436            ee_putstr("%%");
437            ee_goto(x, y-3);
438            ee_putstr("##");
439            ee_color(EE_CYAN);
440            ee_goto(x-1, y-4);
441            ee_putchar(':');
442            ee_goto(x+2, y-4);
443            ee_putchar(':');
444            ee_goto(x-1, y-3);
445            ee_putchar('%');
446            ee_goto(x+2, y-3);
447            ee_putchar('%');
448            ee_goto(x-4, y-2);
449            ee_putstr(",-'");
450            ee_goto(x+3, y-2);
451            ee_putstr("`-.");
452            ee_color(EE_BLUE);
453            ee_goto(x-2, y-3);
454            ee_putchar(':');
455            ee_goto(x+3, y-3);
456            ee_putchar(':');
457            break;
458        case 18:
459        default:
460            r = (18 - frame) * (18 - frame);
461            ee_color(EE_WHITE);
462            ee_goto(x-1, y-5-r);
463            ee_putstr(":%%:");
464            ee_goto(x-1, y-4-r);
465            ee_putstr("%##%");
466            ee_color(EE_CYAN);
467            ee_goto(x-2, y-4-r);
468            ee_putchar(':');
469            ee_goto(x+3, y-4-r);
470            ee_putchar(':');
471            ee_goto(x-2, y-2);
472            ee_putchar('\'');
473            ee_goto(x+3, y-2);
474            ee_putchar('`');
475            ee_color(EE_BLUE);
476            ee_goto(x-3, y-2);
477            ee_putchar(':');
478            ee_goto(x+4, y-2);
479            ee_putchar(':');
480            for(i = 0; i <= r; i++)
481            {
482                ee_color(EE_WHITE);
483                ee_goto(x-1, y-3-i);
484                ee_putstr((i+frame) % 5 ? "####" : "%%%%");
485                ee_color(EE_CYAN);
486                ee_goto(x-2, y-3-i);
487                ee_putchar('%');
488                ee_goto(x+3, y-3-i);
489                ee_putchar('%');
490                ee_color(EE_BLUE);
491                ee_goto(x-3, y-3-i);
492                ee_putchar(':');
493                ee_goto(x+4, y-3-i);
494                ee_putchar(':');
495            }
496            break;
497    }
498}
499
500static void draw_nuke(int x, int y, int frame)
501{
502    int r = (29 - frame) * (29 - frame) / 8;
503
504    /* Lots of duplicate pixels, but we don't care */
505    ee_color(EE_BLUE);
506    ee_draw_circle(x, y, r++, ':');
507    ee_color(EE_CYAN);
508    ee_draw_circle(x, y, r++, '%');
509    ee_color(EE_WHITE);
510    ee_draw_circle(x, y, r++, '#');
511    ee_draw_circle(x, y, r++, '#');
512}
513
Note: See TracBrowser for help on using the repository browser.