source: ttyvaders/trunk/src/weapons.c @ 544

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