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

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