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

Last change on this file since 160 was 160, checked in by Sam Hocevar, 16 years ago
  • libee/ee.h: + Added ee_color_names[] containing our 16 color names.
  • libee/ee.c: + Extended our color set to the full 16 instead of 10. + Precalculate ncurses attributes.
  • libee/graphics.c: + Clip color value in ee_set_color(). + Clip characters in ee_putchar(). + Partially clip characters in ee_putstr(), overflows aren't checked yet.
  • libee/ee_internals.h: + New file to share extern variables within libee.
  • test/demo.c: + Added a simple demo_color() to output all colors. + Replaced four ee_draw_line() with ee_draw_thin_box(). + Replaced x1, y1, x2 etc. with xa, ya, xb etc. because <math.h> already

defines y1.

+ Randomized colours from 0 to 15 instead of 1 to 10.

  • src/Makefiles.am: + Added -lm to the ttyvaders linking flags because of the intro.
  • README BUGS TODO: + Updated.
  • 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 160 2003-11-12 21:18:50Z 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_set_color(EE_WHITE);
60                ee_putchar(wp->x[i] >> 4, wp->y[i] >> 4, '|');
61                ee_set_color(EE_CYAN);
62                ee_putchar(wp->x[i] >> 4, (wp->y[i] >> 4) + 1, '|');
63                break;
64            case WEAPON_SEEKER:
65                ee_set_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_set_color(EE_WHITE);
69                ee_putchar(wp->x[i] >> 4, wp->y[i] >> 4, '@');
70                break;
71            case WEAPON_BOMB:
72                ee_set_color(EE_DARKGRAY);
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_draw_sprite(x, y, bomb_sprite, frame);
337}
338
339static void draw_fragbomb(int x, int y, int frame)
340{
341    /* Draw the head */
342    ee_draw_sprite(x, y, fragbomb_sprite, frame & 1);
343
344    /* Draw the tail */
345    ee_draw_sprite(x, y, fragbomb_sprite, 2 + (frame % 4));
346}
347
348static void draw_beam(int x, int y, int frame)
349{
350    int r = (29 - frame) * (29 - frame) / 8;
351    int i;
352
353    switch(frame)
354    {
355        case 24:
356            ee_set_color(EE_WHITE);
357            ee_putstr(x, y-3, "__");
358            ee_putchar(x-1, y-2, '\'');
359            ee_putchar(x+2, y-2, '`');
360            break;
361        case 23:
362            ee_set_color(EE_CYAN);
363            ee_putstr(x, y-3, "__");
364            ee_set_color(EE_WHITE);
365            ee_putstr(x-2, y-2, "-'");
366            ee_putstr(x+2, y-2, "`-");
367            break;
368        case 22:
369            ee_set_color(EE_CYAN);
370            ee_putstr(x, y-3, "__");
371            ee_putchar(x-1, y-2, '\'');
372            ee_putchar(x+2, y-2, '`');
373            ee_set_color(EE_WHITE);
374            ee_putstr(x-3, y-2, ",-");
375            ee_putstr(x+3, y-2, "-.");
376            break;
377        case 21:
378            ee_set_color(EE_CYAN);
379            ee_putstr(x-1, y-3, "____");
380            ee_putchar(x-2, y-2, '\'');
381            ee_putchar(x+3, y-2, '`');
382            ee_set_color(EE_WHITE);
383            ee_putstr(x-4, y-2, ",-");
384            ee_putstr(x+4, y-2, "-.");
385            break;
386        case 20:
387            ee_set_color(EE_WHITE);
388            ee_putstr(x, y-3, "%%");
389            ee_putchar(x-4, y-2, ',');
390            ee_putchar(x+5, y-2, '.');
391            ee_set_color(EE_CYAN);
392            ee_putchar(x-1, y-3, ':');
393            ee_putchar(x+2, y-3, ':');
394            ee_putstr(x-3, y-2, "-'");
395            ee_putstr(x+3, y-2, "`-");
396            break;
397        case 19:
398            ee_set_color(EE_WHITE);
399            ee_putstr(x, y-4, "%%");
400            ee_putstr(x, y-3, "##");
401            ee_set_color(EE_CYAN);
402            ee_putchar(x-1, y-4, ':');
403            ee_putchar(x+2, y-4, ':');
404            ee_putchar(x-1, y-3, '%');
405            ee_putchar(x+2, y-3, '%');
406            ee_putstr(x-4, y-2, ",-'");
407            ee_putstr(x+3, y-2, "`-.");
408            ee_set_color(EE_BLUE);
409            ee_putchar(x-2, y-3, ':');
410            ee_putchar(x+3, y-3, ':');
411            break;
412        case 18:
413        default:
414            r = (18 - frame) * (18 - frame);
415            ee_set_color(EE_WHITE);
416            ee_putstr(x-1, y-5-r, ":%%:");
417            ee_putstr(x-1, y-4-r, "%##%");
418            ee_set_color(EE_CYAN);
419            ee_putchar(x-2, y-4-r, ':');
420            ee_putchar(x+3, y-4-r, ':');
421            ee_putchar(x-2, y-2, '\'');
422            ee_putchar(x+3, y-2, '`');
423            ee_set_color(EE_BLUE);
424            ee_putchar(x-3, y-2, ':');
425            ee_putchar(x+4, y-2, ':');
426            for(i = 0; i <= r; i++)
427            {
428                ee_set_color(EE_WHITE);
429                ee_putstr(x-1, y-3-i, ((i+frame) % 5) ? "####" : "%%%%");
430                ee_set_color(EE_CYAN);
431                ee_putchar(x-2, y-3-i, '%');
432                ee_putchar(x+3, y-3-i, '%');
433                ee_set_color(EE_BLUE);
434                ee_putchar(x-3, y-3-i, ':');
435                ee_putchar(x+4, y-3-i, ':');
436            }
437            break;
438    }
439}
440
441static void draw_nuke(int x, int y, int frame)
442{
443    int r = (29 - frame) * (29 - frame) / 8;
444
445    /* Lots of duplicate pixels, but we don't care */
446    ee_set_color(EE_BLUE);
447    ee_draw_ellipse(x, y, r, r / 2, ':');
448    ee_draw_ellipse(x, y, r + 1, r / 2, ':');
449    ee_draw_ellipse(x, y, r + 2, r / 2, ':');
450    ee_set_color(EE_CYAN);
451    ee_draw_ellipse(x, y, r + 2, r / 2 + 1, '%');
452    ee_draw_ellipse(x, y, r + 3, r / 2 + 1, '%');
453    ee_set_color(EE_WHITE);
454    ee_draw_ellipse(x, y, r + 3, r / 2 + 2, '#');
455    ee_draw_ellipse(x, y, r + 4, r / 2 + 2, '#');
456    ee_draw_ellipse(x, y, r + 4, r / 2 + 3, '#');
457}
458
Note: See TracBrowser for help on using the repository browser.