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
RevLine 
[36]1/*
2 *   ttyvaders     Textmode shoot'em up
3 *   Copyright (c) 2002 Sam Hocevar <sam@zoy.org>
4 *                 All Rights Reserved
5 *
[80]6 *   $Id: weapons.c 1057 2006-09-18 16:54:08Z sam $
[36]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 */
[18]22
[110]23#include "config.h"
24
[18]25#include <stdlib.h>
[1057]26#include <math.h>
[18]27
28#include "common.h"
29
[544]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);
[18]34
[1057]35cucul_canvas_t *bomb_sprite;
36cucul_canvas_t *fragbomb_sprite;
[142]37
[88]38void init_weapons(game *g, weapons *wp)
[18]39{
[1057]40    cucul_buffer_t *b;
[18]41    int i;
42
[88]43    for(i = 0; i < WEAPONS; i++)
[18]44    {
[20]45        wp->type[i] = WEAPON_NONE;
[18]46    }
[142]47
[1057]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);
[18]55}
56
[88]57void draw_weapons(game *g, weapons *wp)
[18]58{
[188]59    unsigned int i;
[18]60
[88]61    for(i = 0; i < WEAPONS; i++)
[18]62    {
[88]63        switch(wp->type[i])
[18]64        {
[20]65            case WEAPON_LASER:
[1057]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, '|');
[20]70                break;
71            case WEAPON_SEEKER:
[1057]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, '@');
[20]77                break;
[24]78            case WEAPON_BOMB:
[1057]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, '.');
[544]85                draw_bomb(g, wp->x[i] >> 4, wp->y[i] >> 4, wp->vx[i], wp->vy[i]);
[24]86                break;
[42]87            case WEAPON_FRAGBOMB:
[544]88                draw_fragbomb(g, wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]);
[42]89                break;
[22]90            case WEAPON_BEAM:
[544]91                draw_beam(g, wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]);
[22]92                break;
[20]93            case WEAPON_NUKE:
[544]94                draw_nuke(g, wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]);
[20]95                break;
[42]96            case WEAPON_LIGHTNING:
[20]97            case WEAPON_NONE:
98                break;
[18]99        }
100    }
101}
102
[88]103void update_weapons(game *g, weapons *wp)
[18]104{
[188]105    unsigned int i, j;
106    int dist, xmin, ymin, dx, dy, xnew, ynew;
[18]107
[88]108    for(i = 0; i < WEAPONS; i++)
[18]109    {
[88]110        switch(wp->type[i])
[18]111        {
[20]112            case WEAPON_LASER:
113                wp->x[i] += wp->vx[i];
114                wp->y[i] += wp->vy[i];
[88]115                if(wp->y[i] < 0)
[20]116                {
117                    wp->type[i] = WEAPON_NONE;
118                }
119                break;
[24]120            case WEAPON_BOMB:
[20]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
[88]132                if(wp->y[i] < 0)
[20]133                {
134                    wp->type[i] = WEAPON_NONE;
135                    break;
136                }
137
[88]138                if(wp->n[i] < 0)
[20]139                {
140                    /* Stop updating direction */
141                    break;
142                }
143
[18]144                wp->n[i]--;
[20]145
[48]146                /* Estimate our position next frames */
147                xnew = wp->x[i] + wp->vx[i];
148                ynew = wp->y[i] + wp->vy[i];
[20]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 */
[88]156                for(j = 0; j < ALIENS; j++)
[18]157                {
[88]158                    if(g->al->type[j] != ALIEN_NONE)
[20]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);
[88]164                        if(new <= dist)
[20]165                        {
166                            dist = new;
167                            xmin = alx;
168                            ymin = aly;
169                        }
170                    }
[18]171                }
[20]172
173                /* Find our new direction */
174                dx = xmin - wp->x[i];
175                dy = ymin - wp->y[i];
176
[48]177                /* Normalize direction */
[88]178                if(dx | dy)
[46]179                {
[1057]180                    unsigned int norm = (int)sqrt((double)(dx * dx + 4 * dy * dy));
[48]181                    dx = dx * 32 / norm;
182                    dy = dy * 32 / norm;
183                }
[20]184
[48]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 */
[88]190                if(dx | dy)
[48]191                {
[1057]192                    unsigned int norm = (int)sqrt((double)(dx * dx + 4 * dy * dy));
[48]193                    wp->vx[i] = dx * 32 / norm;
194                    wp->vy[i] = dy * 32 / norm;
[46]195                }
[48]196
[18]197                break;
[46]198
[42]199            case WEAPON_FRAGBOMB:
[46]200                /* If n was set to -1, the fragbomb just exploded */
[88]201                if(wp->n[i] == -1)
[42]202                {
[46]203                    int coords[] =
204                    {
[48]205                        32,  0,   -32,  0,    0,  16,     0, -16,
[50]206                        28,  8,   -28,  8,   28,  -8,   -28,  -8,
[48]207                        24, 12,   -24, 12,   24, -12,   -24, -12,
208                        16, 14,   -16, 14,   16, -14,   -16, -14
[46]209                    };
210
[88]211                    for(j = 0 ; j < sizeof(coords) / sizeof(int) ; j += 2)
[46]212                    {
[88]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);
[46]215                    }
216
[42]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]++;
[88]223                if(wp->y[i] < 0)
[42]224                {
225                    wp->type[i] = WEAPON_NONE;
226                }
227                break;
[46]228
[22]229            case WEAPON_BEAM:
[150]230                wp->x[i] = g->p->x << 4;
[22]231                wp->y[i] = g->p->y << 4;
232                wp->n[i]--;
[88]233                if(wp->n[i] < 0)
[22]234                {
235                    wp->type[i] = WEAPON_NONE;
236                }
237                break;
[20]238            case WEAPON_NUKE:
239                wp->n[i]--;
[88]240                if(wp->n[i] < 0)
[20]241                {
242                    wp->type[i] = WEAPON_NONE;
243                }
[18]244                break;
[42]245            case WEAPON_LIGHTNING:
[20]246            case WEAPON_NONE:
247                break;
[18]248        }
249    }
250}
251
[88]252void add_weapon(game *g, weapons *wp, int x, int y, int vx, int vy, int type)
[18]253{
254    int i;
255
[88]256    for(i = 0; i < WEAPONS; i++)
[18]257    {
[88]258        if(wp->type[i] == WEAPON_NONE)
[18]259        {
260            wp->x[i] = x;
261            wp->y[i] = y;
[20]262            wp->vx[i] = vx;
263            wp->vy[i] = vy;
[18]264            wp->type[i] = type;
[42]265            wp->n[i] = 0;
[88]266            switch(type)
[20]267            {
268                case WEAPON_LASER:
269                    break;
[42]270                case WEAPON_FRAGBOMB:
271                    break;
[20]272                case WEAPON_SEEKER:
[24]273                case WEAPON_BOMB:
[20]274                    wp->x2[i] = x;
275                    wp->y2[i] = y;
276                    wp->x3[i] = x;
277                    wp->y3[i] = y;
[26]278                    wp->n[i] = 20;
[20]279                    break;
[22]280                case WEAPON_BEAM:
281                    wp->n[i] = 25;
282                    break;
[20]283                case WEAPON_NUKE:
284                    wp->n[i] = 25;
285                    break;
286                case WEAPON_NONE:
287                    break;
288            }
[18]289            break;
290        }
291    }
292}
293
[544]294static void draw_bomb(game *g, int x, int y, int vx, int vy)
[24]295{
[142]296    int frame;
297
298    /* We have 1x2 pixels */
[24]299    vy *= 2;
300
[88]301    if(vx > vy)
[24]302    {
[88]303        if(vx > -vy) /* right quarter */
[24]304        {
[88]305            if(vy > vx/4)
[142]306                frame = 0; /* -pi/6 */
[88]307            else if(vy < -vx/4)
[142]308                frame = 1; /* pi/6 */
[24]309            else
[142]310                frame = 2; /* 0pi/6 */
[24]311        }
312        else /* top quarter */
313        {
[88]314            if(vx > -vy/4)
[142]315                frame = 3; /* 2pi/6 */
[88]316            else if(vx < vy/4)
[142]317                frame = 4; /* 4pi/6 */
[24]318            else
[142]319                frame = 5; /* 3pi/6 */
[24]320        }
321    }
322    else
323    {
[88]324        if(vx > -vy) /* bottom quarter */
[24]325        {
[88]326            if(vx > vy/4)
[142]327                frame = 6; /* -2pi/6 */
[88]328            else if(vx < -vy/4)
[142]329                frame = 7; /* -4pi/6 */
[24]330            else
[142]331                frame = 8; /* -3pi/6 */
[24]332        }
333        else /* left quarter */
334        {
[88]335            if(vy > -vx/4)
[142]336                frame = 9; /* -5pi/6 */
[88]337            else if(vy < vx/4)
[142]338                frame = 10; /* 5pi/6 */
[24]339            else
[142]340                frame = 11; /* 6pi/6 */
[24]341        }
342    }
[142]343
[1057]344    cucul_set_canvas_frame(bomb_sprite, frame);
345    cucul_blit(g->cv, x, y, bomb_sprite, NULL);
[24]346}
347
[544]348static void draw_fragbomb(game *g, int x, int y, int frame)
[42]349{
[144]350    /* Draw the head */
[1057]351    cucul_set_canvas_frame(fragbomb_sprite, frame & 1);
352    cucul_blit(g->cv, x, y, fragbomb_sprite, NULL);
[42]353
[144]354    /* Draw the tail */
[1057]355    cucul_set_canvas_frame(fragbomb_sprite, 2 + (frame % 4));
356    cucul_blit(g->cv, x, y, fragbomb_sprite, NULL);
[42]357}
358
[544]359static void draw_beam(game *g, int x, int y, int frame)
[22]360{
361    int r = (29 - frame) * (29 - frame) / 8;
362    int i;
363
[88]364    switch(frame)
[22]365    {
366        case 24:
[1057]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, '`');
[22]371            break;
372        case 23:
[1057]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, "`-");
[22]378            break;
379        case 22:
[1057]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, "-.");
[22]387            break;
388        case 21:
[1057]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, "-.");
[22]396            break;
397        case 20:
[1057]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, "`-");
[22]407            break;
408        case 19:
[1057]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, ':');
[22]422            break;
423        case 18:
424        default:
425            r = (18 - frame) * (18 - frame);
[1057]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, ':');
[88]437            for(i = 0; i <= r; i++)
[22]438            {
[1057]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, ':');
[22]447            }
448            break;
449    }
450}
451
[544]452static void draw_nuke(game *g, int x, int y, int frame)
[18]453{
[20]454    int r = (29 - frame) * (29 - frame) / 8;
[18]455
456    /* Lots of duplicate pixels, but we don't care */
[1057]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, " ");
[18]472}
473
Note: See TracBrowser for help on using the repository browser.