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

Last change on this file since 149 was 149, checked in by Sam Hocevar, 20 years ago
  • src/weapons.c: + Use ee_draw_ellipse() instead of ee_draw_circle() to draw the nuke.
  • src/player.c: + Use ee_draw_sprite() to draw our ship.
  • Property svn:keywords set to Id
File size: 13.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 149 2003-11-11 08:00:36Z 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_putchar(wp->x[i] >> 4, wp->y[i] >> 4, '|');
61                ee_color(EE_CYAN);
62                ee_putchar(wp->x[i] >> 4, (wp->y[i] >> 4) + 1, '|');
63                break;
64            case WEAPON_SEEKER:
65                ee_color(EE_CYAN);
66                ee_putchar(wp->x3[i] >> 4, wp->y3[i] >> 4, '.');
67                ee_putchar(wp->x2[i] >> 4, wp->y2[i] >> 4, 'o');
68                ee_color(EE_WHITE);
69                ee_putchar(wp->x[i] >> 4, wp->y[i] >> 4, '@');
70                break;
71            case WEAPON_BOMB:
72                ee_color(EE_GRAY);
73                ee_putchar((wp->x[i] - wp->vx[i]) >> 4, (wp->y[i] - wp->vy[i]) >> 4, '.');
74                ee_putchar((wp->x3[i] - wp->vx[i]) >> 4, (wp->y3[i] - wp->vy[i]) >> 4, '.');
75                ee_putchar((wp->x2[i] - wp->vx[i]) >> 4, (wp->y2[i] - wp->vy[i]) >> 4, '.');
76                ee_putchar(wp->x3[i] >> 4, wp->y3[i] >> 4, '.');
77                ee_putchar(wp->x2[i] >> 4, wp->y2[i] >> 4, '.');
78                draw_bomb(wp->x[i] >> 4, wp->y[i] >> 4, wp->vx[i], wp->vy[i]);
79                break;
80            case WEAPON_FRAGBOMB:
81                draw_fragbomb(wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]);
82                break;
83            case WEAPON_BEAM:
84                draw_beam(wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]);
85                break;
86            case WEAPON_NUKE:
87                draw_nuke(wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]);
88                break;
89            case WEAPON_LIGHTNING:
90            case WEAPON_NONE:
91                break;
92        }
93    }
94}
95
96void update_weapons(game *g, weapons *wp)
97{
98    int i, j, dist, xmin, ymin, dx, dy, xnew, ynew;
99
100    for(i = 0; i < WEAPONS; i++)
101    {
102        switch(wp->type[i])
103        {
104            case WEAPON_LASER:
105                wp->x[i] += wp->vx[i];
106                wp->y[i] += wp->vy[i];
107                if(wp->y[i] < 0)
108                {
109                    wp->type[i] = WEAPON_NONE;
110                }
111                break;
112            case WEAPON_BOMB:
113            case WEAPON_SEEKER:
114                /* Update tail */
115                wp->x3[i] = wp->x2[i];
116                wp->y3[i] = wp->y2[i];
117
118                wp->x2[i] = wp->x[i];
119                wp->y2[i] = wp->y[i];
120
121                wp->x[i] += wp->vx[i];
122                wp->y[i] += wp->vy[i];
123
124                if(wp->y[i] < 0)
125                {
126                    wp->type[i] = WEAPON_NONE;
127                    break;
128                }
129
130                if(wp->n[i] < 0)
131                {
132                    /* Stop updating direction */
133                    break;
134                }
135
136                wp->n[i]--;
137
138                /* Estimate our position next frames */
139                xnew = wp->x[i] + wp->vx[i];
140                ynew = wp->y[i] + wp->vy[i];
141
142                xmin = xnew;
143                ymin = - (g->h << 4);
144                dist = (xnew - xmin) * (xnew - xmin)
145                        + 4 * (ynew - ymin) * (ynew - ymin);
146
147                /* Find the nearest alien */
148                for(j = 0; j < ALIENS; j++)
149                {
150                    if(g->al->type[j] != ALIEN_NONE)
151                    {
152                        int alx = g->al->x[j] << 4;
153                        int aly = g->al->y[j] << 4;
154                        int new = (xnew - alx) * (xnew - alx)
155                                   + 4 * (ynew - aly) * (ynew - aly);
156                        if(new <= dist)
157                        {
158                            dist = new;
159                            xmin = alx;
160                            ymin = aly;
161                        }
162                    }
163                }
164
165                /* Find our new direction */
166                dx = xmin - wp->x[i];
167                dy = ymin - wp->y[i];
168
169                /* Normalize direction */
170                if(dx | dy)
171                {
172                    int norm = ee_sqrt(dx * dx + 4 * dy * dy);
173                    dx = dx * 32 / norm;
174                    dy = dy * 32 / norm;
175                }
176
177                /* Find our new speed */
178                dx = (dx + 3 * wp->vx[i]) / 4;
179                dy = (dy + 3 * wp->vy[i]) / 4;
180
181                /* Normalize speed */
182                if(dx | dy)
183                {
184                    int norm = ee_sqrt(dx * dx + 4 * dy * dy);
185                    wp->vx[i] = dx * 32 / norm;
186                    wp->vy[i] = dy * 32 / norm;
187                }
188
189                break;
190
191            case WEAPON_FRAGBOMB:
192                /* If n was set to -1, the fragbomb just exploded */
193                if(wp->n[i] == -1)
194                {
195                    int coords[] =
196                    {
197                        32,  0,   -32,  0,    0,  16,     0, -16,
198                        28,  8,   -28,  8,   28,  -8,   -28,  -8,
199                        24, 12,   -24, 12,   24, -12,   -24, -12,
200                        16, 14,   -16, 14,   16, -14,   -16, -14
201                    };
202
203                    for(j = 0 ; j < sizeof(coords) / sizeof(int) ; j += 2)
204                    {
205                        add_weapon(g, g->wp, wp->x[i] + coords[j], wp->y[i] + coords[j+1] / 2, coords[j], coords[j+1], WEAPON_SEEKER);
206                        add_weapon(g, g->wp, wp->x[i] + coords[j] / 2, wp->y[i] + coords[j+1], coords[j], coords[j+1], WEAPON_SEEKER);
207                    }
208
209                    wp->type[i] = WEAPON_NONE;
210                }
211
212                wp->x[i] += wp->vx[i];
213                wp->y[i] += wp->vy[i];
214                wp->n[i]++;
215                if(wp->y[i] < 0)
216                {
217                    wp->type[i] = WEAPON_NONE;
218                }
219                break;
220
221            case WEAPON_BEAM:
222                wp->x[i] = g->p->x << 4;
223                wp->y[i] = g->p->y << 4;
224                wp->n[i]--;
225                if(wp->n[i] < 0)
226                {
227                    wp->type[i] = WEAPON_NONE;
228                }
229                break;
230            case WEAPON_NUKE:
231                wp->n[i]--;
232                if(wp->n[i] < 0)
233                {
234                    wp->type[i] = WEAPON_NONE;
235                }
236                break;
237            case WEAPON_LIGHTNING:
238            case WEAPON_NONE:
239                break;
240        }
241    }
242}
243
244void add_weapon(game *g, weapons *wp, int x, int y, int vx, int vy, int type)
245{
246    int i;
247
248    for(i = 0; i < WEAPONS; i++)
249    {
250        if(wp->type[i] == WEAPON_NONE)
251        {
252            wp->x[i] = x;
253            wp->y[i] = y;
254            wp->vx[i] = vx;
255            wp->vy[i] = vy;
256            wp->type[i] = type;
257            wp->n[i] = 0;
258            switch(type)
259            {
260                case WEAPON_LASER:
261                    break;
262                case WEAPON_FRAGBOMB:
263                    break;
264                case WEAPON_SEEKER:
265                case WEAPON_BOMB:
266                    wp->x2[i] = x;
267                    wp->y2[i] = y;
268                    wp->x3[i] = x;
269                    wp->y3[i] = y;
270                    wp->n[i] = 20;
271                    break;
272                case WEAPON_BEAM:
273                    wp->n[i] = 25;
274                    break;
275                case WEAPON_NUKE:
276                    wp->n[i] = 25;
277                    break;
278                case WEAPON_NONE:
279                    break;
280            }
281            break;
282        }
283    }
284}
285
286static void draw_bomb(int x, int y, int vx, int vy)
287{
288    int frame;
289
290    /* We have 1x2 pixels */
291    vy *= 2;
292
293    if(vx > vy)
294    {
295        if(vx > -vy) /* right quarter */
296        {
297            if(vy > vx/4)
298                frame = 0; /* -pi/6 */
299            else if(vy < -vx/4)
300                frame = 1; /* pi/6 */
301            else
302                frame = 2; /* 0pi/6 */
303        }
304        else /* top quarter */
305        {
306            if(vx > -vy/4)
307                frame = 3; /* 2pi/6 */
308            else if(vx < vy/4)
309                frame = 4; /* 4pi/6 */
310            else
311                frame = 5; /* 3pi/6 */
312        }
313    }
314    else
315    {
316        if(vx > -vy) /* bottom quarter */
317        {
318            if(vx > vy/4)
319                frame = 6; /* -2pi/6 */
320            else if(vx < -vy/4)
321                frame = 7; /* -4pi/6 */
322            else
323                frame = 8; /* -3pi/6 */
324        }
325        else /* left quarter */
326        {
327            if(vy > -vx/4)
328                frame = 9; /* -5pi/6 */
329            else if(vy < vx/4)
330                frame = 10; /* 5pi/6 */
331            else
332                frame = 11; /* 6pi/6 */
333        }
334    }
335
336    ee_set_sprite_frame(bomb_sprite, frame);
337    ee_draw_sprite(x, y, bomb_sprite);
338}
339
340static void draw_fragbomb(int x, int y, int frame)
341{
342    /* Draw the head */
343    ee_set_sprite_frame(fragbomb_sprite, frame & 1);
344    ee_draw_sprite(x, y, fragbomb_sprite);
345
346    /* Draw the tail */
347    ee_set_sprite_frame(fragbomb_sprite, 2 + (frame % 4));
348    ee_draw_sprite(x, y, fragbomb_sprite);
349}
350
351static void draw_beam(int x, int y, int frame)
352{
353    int r = (29 - frame) * (29 - frame) / 8;
354    int i;
355
356    switch(frame)
357    {
358        case 24:
359            ee_color(EE_WHITE);
360            ee_putstr(x, y-3, "__");
361            ee_putchar(x-1, y-2, '\'');
362            ee_putchar(x+2, y-2, '`');
363            break;
364        case 23:
365            ee_color(EE_CYAN);
366            ee_putstr(x, y-3, "__");
367            ee_color(EE_WHITE);
368            ee_putstr(x-2, y-2, "-'");
369            ee_putstr(x+2, y-2, "`-");
370            break;
371        case 22:
372            ee_color(EE_CYAN);
373            ee_putstr(x, y-3, "__");
374            ee_putchar(x-1, y-2, '\'');
375            ee_putchar(x+2, y-2, '`');
376            ee_color(EE_WHITE);
377            ee_putstr(x-3, y-2, ",-");
378            ee_putstr(x+3, y-2, "-.");
379            break;
380        case 21:
381            ee_color(EE_CYAN);
382            ee_putstr(x-1, y-3, "____");
383            ee_putchar(x-2, y-2, '\'');
384            ee_putchar(x+3, y-2, '`');
385            ee_color(EE_WHITE);
386            ee_putstr(x-4, y-2, ",-");
387            ee_putstr(x+4, y-2, "-.");
388            break;
389        case 20:
390            ee_color(EE_WHITE);
391            ee_putstr(x, y-3, "%%");
392            ee_putchar(x-4, y-2, ',');
393            ee_putchar(x+5, y-2, '.');
394            ee_color(EE_CYAN);
395            ee_putchar(x-1, y-3, ':');
396            ee_putchar(x+2, y-3, ':');
397            ee_putstr(x-3, y-2, "-'");
398            ee_putstr(x+3, y-2, "`-");
399            break;
400        case 19:
401            ee_color(EE_WHITE);
402            ee_putstr(x, y-4, "%%");
403            ee_putstr(x, y-3, "##");
404            ee_color(EE_CYAN);
405            ee_putchar(x-1, y-4, ':');
406            ee_putchar(x+2, y-4, ':');
407            ee_putchar(x-1, y-3, '%');
408            ee_putchar(x+2, y-3, '%');
409            ee_putstr(x-4, y-2, ",-'");
410            ee_putstr(x+3, y-2, "`-.");
411            ee_color(EE_BLUE);
412            ee_putchar(x-2, y-3, ':');
413            ee_putchar(x+3, y-3, ':');
414            break;
415        case 18:
416        default:
417            r = (18 - frame) * (18 - frame);
418            ee_color(EE_WHITE);
419            ee_putstr(x-1, y-5-r, ":%%:");
420            ee_putstr(x-1, y-4-r, "%##%");
421            ee_color(EE_CYAN);
422            ee_putchar(x-2, y-4-r, ':');
423            ee_putchar(x+3, y-4-r, ':');
424            ee_putchar(x-2, y-2, '\'');
425            ee_putchar(x+3, y-2, '`');
426            ee_color(EE_BLUE);
427            ee_putchar(x-3, y-2, ':');
428            ee_putchar(x+4, y-2, ':');
429            for(i = 0; i <= r; i++)
430            {
431                ee_color(EE_WHITE);
432                ee_putstr(x-1, y-3-i, ((i+frame) % 5) ? "####" : "%%%%");
433                ee_color(EE_CYAN);
434                ee_putchar(x-2, y-3-i, '%');
435                ee_putchar(x+3, y-3-i, '%');
436                ee_color(EE_BLUE);
437                ee_putchar(x-3, y-3-i, ':');
438                ee_putchar(x+4, y-3-i, ':');
439            }
440            break;
441    }
442}
443
444static void draw_nuke(int x, int y, int frame)
445{
446    int r = (29 - frame) * (29 - frame) / 8;
447
448    /* Lots of duplicate pixels, but we don't care */
449    ee_color(EE_BLUE);
450    ee_draw_ellipse(x, y, r, r / 2, ':');
451    ee_draw_ellipse(x, y, r + 1, r / 2, ':');
452    ee_draw_ellipse(x, y, r + 2, r / 2, ':');
453    ee_color(EE_CYAN);
454    ee_draw_ellipse(x, y, r + 2, r / 2 + 1, '%');
455    ee_draw_ellipse(x, y, r + 3, r / 2 + 1, '%');
456    ee_color(EE_WHITE);
457    ee_draw_ellipse(x, y, r + 3, r / 2 + 2, '#');
458    ee_draw_ellipse(x, y, r + 4, r / 2 + 2, '#');
459    ee_draw_ellipse(x, y, r + 4, r / 2 + 3, '#');
460}
461
Note: See TracBrowser for help on using the repository browser.