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

Last change on this file since 1460 was 1460, checked in by Sam Hocevar, 13 years ago
  • Bwarf, typo in the no warranty clause.
  • Property svn:keywords set to Id
File size: 15.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 1460 2006-12-12 01:49:48Z sam $
7 *
8 *  This program is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15#include "config.h"
16
17#include <stdlib.h>
18#include <math.h>
19
20#include "common.h"
21
22static void draw_bomb(game *g, int x, int y, int vx, int vy);
23static void draw_nuke(game *g, int x, int y, int frame);
24static void draw_beam(game *g, int x, int y, int frame);
25static void draw_fragbomb(game *g, int x, int y, int frame);
26
27cucul_canvas_t *bomb_sprite;
28cucul_canvas_t *fragbomb_sprite;
29
30void init_weapons(game *g, weapons *wp)
31{
32    cucul_buffer_t *b;
33    int i;
34
35    for(i = 0; i < WEAPONS; i++)
36    {
37        wp->type[i] = WEAPON_NONE;
38    }
39
40    b = cucul_load_file("data/wpnbomb.caca");
41    bomb_sprite = cucul_import_canvas(b, "");
42    cucul_free_buffer(b);
43
44    b = cucul_load_file("data/wpnfrag.caca");
45    bomb_sprite = cucul_import_canvas(b, "");
46    cucul_free_buffer(b);
47}
48
49void draw_weapons(game *g, weapons *wp)
50{
51    unsigned int i;
52
53    for(i = 0; i < WEAPONS; i++)
54    {
55        switch(wp->type[i])
56        {
57            case WEAPON_LASER:
58                cucul_set_color(g->cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLACK);
59                cucul_putchar(g->cv, wp->x[i] >> 4, wp->y[i] >> 4, '|');
60                cucul_set_color(g->cv, CUCUL_COLOR_CYAN, CUCUL_COLOR_BLACK);
61                cucul_putchar(g->cv, wp->x[i] >> 4, (wp->y[i] >> 4) + 1, '|');
62                break;
63            case WEAPON_SEEKER:
64                cucul_set_color(g->cv, CUCUL_COLOR_CYAN, CUCUL_COLOR_BLACK);
65                cucul_putchar(g->cv, wp->x3[i] >> 4, wp->y3[i] >> 4, '.');
66                cucul_putchar(g->cv, wp->x2[i] >> 4, wp->y2[i] >> 4, 'o');
67                cucul_set_color(g->cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLACK);
68                cucul_putchar(g->cv, wp->x[i] >> 4, wp->y[i] >> 4, '@');
69                break;
70            case WEAPON_BOMB:
71                cucul_set_color(g->cv, CUCUL_COLOR_DARKGRAY, CUCUL_COLOR_BLACK);
72                cucul_putchar(g->cv, (wp->x[i] - wp->vx[i]) >> 4, (wp->y[i] - wp->vy[i]) >> 4, '.');
73                cucul_putchar(g->cv, (wp->x3[i] - wp->vx[i]) >> 4, (wp->y3[i] - wp->vy[i]) >> 4, '.');
74                cucul_putchar(g->cv, (wp->x2[i] - wp->vx[i]) >> 4, (wp->y2[i] - wp->vy[i]) >> 4, '.');
75                cucul_putchar(g->cv, wp->x3[i] >> 4, wp->y3[i] >> 4, '.');
76                cucul_putchar(g->cv, wp->x2[i] >> 4, wp->y2[i] >> 4, '.');
77                draw_bomb(g, wp->x[i] >> 4, wp->y[i] >> 4, wp->vx[i], wp->vy[i]);
78                break;
79            case WEAPON_FRAGBOMB:
80                draw_fragbomb(g, wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]);
81                break;
82            case WEAPON_BEAM:
83                draw_beam(g, wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]);
84                break;
85            case WEAPON_NUKE:
86                draw_nuke(g, wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]);
87                break;
88            case WEAPON_LIGHTNING:
89            case WEAPON_NONE:
90                break;
91        }
92    }
93}
94
95void update_weapons(game *g, weapons *wp)
96{
97    unsigned int i, j;
98    int 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                    unsigned int norm = (int)sqrt((double)(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                    unsigned int norm = (int)sqrt((double)(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(game *g, 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    cucul_set_canvas_frame(bomb_sprite, frame);
337    cucul_blit(g->cv, x, y, bomb_sprite, NULL);
338}
339
340static void draw_fragbomb(game *g, int x, int y, int frame)
341{
342    /* Draw the head */
343    cucul_set_canvas_frame(fragbomb_sprite, frame & 1);
344    cucul_blit(g->cv, x, y, fragbomb_sprite, NULL);
345
346    /* Draw the tail */
347    cucul_set_canvas_frame(fragbomb_sprite, 2 + (frame % 4));
348    cucul_blit(g->cv, x, y, fragbomb_sprite, NULL);
349}
350
351static void draw_beam(game *g, 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            cucul_set_color(g->cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLACK);
360            cucul_putstr(g->cv, x, y-3, "__");
361            cucul_putchar(g->cv, x-1, y-2, '\'');
362            cucul_putchar(g->cv, x+2, y-2, '`');
363            break;
364        case 23:
365            cucul_set_color(g->cv, CUCUL_COLOR_CYAN, CUCUL_COLOR_BLACK);
366            cucul_putstr(g->cv, x, y-3, "__");
367            cucul_set_color(g->cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLACK);
368            cucul_putstr(g->cv, x-2, y-2, "-'");
369            cucul_putstr(g->cv, x+2, y-2, "`-");
370            break;
371        case 22:
372            cucul_set_color(g->cv, CUCUL_COLOR_CYAN, CUCUL_COLOR_BLACK);
373            cucul_putstr(g->cv, x, y-3, "__");
374            cucul_putchar(g->cv, x-1, y-2, '\'');
375            cucul_putchar(g->cv, x+2, y-2, '`');
376            cucul_set_color(g->cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLACK);
377            cucul_putstr(g->cv, x-3, y-2, ",-");
378            cucul_putstr(g->cv, x+3, y-2, "-.");
379            break;
380        case 21:
381            cucul_set_color(g->cv, CUCUL_COLOR_CYAN, CUCUL_COLOR_BLACK);
382            cucul_putstr(g->cv, x-1, y-3, "____");
383            cucul_putchar(g->cv, x-2, y-2, '\'');
384            cucul_putchar(g->cv, x+3, y-2, '`');
385            cucul_set_color(g->cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLACK);
386            cucul_putstr(g->cv, x-4, y-2, ",-");
387            cucul_putstr(g->cv, x+4, y-2, "-.");
388            break;
389        case 20:
390            cucul_set_color(g->cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLACK);
391            cucul_putstr(g->cv, x, y-3, "%%");
392            cucul_putchar(g->cv, x-4, y-2, ',');
393            cucul_putchar(g->cv, x+5, y-2, '.');
394            cucul_set_color(g->cv, CUCUL_COLOR_CYAN, CUCUL_COLOR_BLACK);
395            cucul_putchar(g->cv, x-1, y-3, ':');
396            cucul_putchar(g->cv, x+2, y-3, ':');
397            cucul_putstr(g->cv, x-3, y-2, "-'");
398            cucul_putstr(g->cv, x+3, y-2, "`-");
399            break;
400        case 19:
401            cucul_set_color(g->cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLACK);
402            cucul_putstr(g->cv, x, y-4, "%%");
403            cucul_putstr(g->cv, x, y-3, "##");
404            cucul_set_color(g->cv, CUCUL_COLOR_CYAN, CUCUL_COLOR_BLACK);
405            cucul_putchar(g->cv, x-1, y-4, ':');
406            cucul_putchar(g->cv, x+2, y-4, ':');
407            cucul_putchar(g->cv, x-1, y-3, '%');
408            cucul_putchar(g->cv, x+2, y-3, '%');
409            cucul_putstr(g->cv, x-4, y-2, ",-'");
410            cucul_putstr(g->cv, x+3, y-2, "`-.");
411            cucul_set_color(g->cv, CUCUL_COLOR_BLUE, CUCUL_COLOR_BLACK);
412            cucul_putchar(g->cv, x-2, y-3, ':');
413            cucul_putchar(g->cv, x+3, y-3, ':');
414            break;
415        case 18:
416        default:
417            r = (18 - frame) * (18 - frame);
418            cucul_set_color(g->cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLACK);
419            cucul_putstr(g->cv, x-1, y-5-r, ":%%:");
420            cucul_putstr(g->cv, x-1, y-4-r, "%##%");
421            cucul_set_color(g->cv, CUCUL_COLOR_CYAN, CUCUL_COLOR_BLACK);
422            cucul_putchar(g->cv, x-2, y-4-r, ':');
423            cucul_putchar(g->cv, x+3, y-4-r, ':');
424            cucul_putchar(g->cv, x-2, y-2, '\'');
425            cucul_putchar(g->cv, x+3, y-2, '`');
426            cucul_set_color(g->cv, CUCUL_COLOR_BLUE, CUCUL_COLOR_BLACK);
427            cucul_putchar(g->cv, x-3, y-2, ':');
428            cucul_putchar(g->cv, x+4, y-2, ':');
429            for(i = 0; i <= r; i++)
430            {
431                cucul_set_color(g->cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLACK);
432                cucul_putstr(g->cv, x-1, y-3-i, ((i+frame) % 5) ? "####" : "%%%%");
433                cucul_set_color(g->cv, CUCUL_COLOR_CYAN, CUCUL_COLOR_BLACK);
434                cucul_putchar(g->cv, x-2, y-3-i, '%');
435                cucul_putchar(g->cv, x+3, y-3-i, '%');
436                cucul_set_color(g->cv, CUCUL_COLOR_BLUE, CUCUL_COLOR_BLACK);
437                cucul_putchar(g->cv, x-3, y-3-i, ':');
438                cucul_putchar(g->cv, x+4, y-3-i, ':');
439            }
440            break;
441    }
442}
443
444static void draw_nuke(game *g, 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    cucul_set_color(g->cv, CUCUL_COLOR_BLUE, CUCUL_COLOR_BLACK);
450    cucul_draw_ellipse(g->cv, x, y, r, r / 2, ":");
451    cucul_set_color(g->cv, CUCUL_COLOR_LIGHTBLUE, CUCUL_COLOR_BLUE);
452    cucul_draw_ellipse(g->cv, x, y, r + 1, r / 2, "#");
453    cucul_set_color(g->cv, CUCUL_COLOR_BLUE, CUCUL_COLOR_LIGHTBLUE);
454    cucul_draw_ellipse(g->cv, x, y, r + 2, r / 2, "#");
455    cucul_set_color(g->cv, CUCUL_COLOR_CYAN, CUCUL_COLOR_LIGHTBLUE);
456    cucul_draw_ellipse(g->cv, x, y, r + 2, r / 2 + 1, "#");
457    cucul_set_color(g->cv, CUCUL_COLOR_LIGHTBLUE, CUCUL_COLOR_CYAN);
458    cucul_draw_ellipse(g->cv, x, y, r + 3, r / 2 + 1, "#");
459    cucul_set_color(g->cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_CYAN);
460    cucul_draw_ellipse(g->cv, x, y, r + 3, r / 2 + 2, "#");
461    cucul_set_color(g->cv, CUCUL_COLOR_CYAN, CUCUL_COLOR_WHITE);
462    cucul_draw_ellipse(g->cv, x, y, r + 4, r / 2 + 2, "#");
463    cucul_draw_ellipse(g->cv, x, y, r + 4, r / 2 + 3, " ");
464}
465
Note: See TracBrowser for help on using the repository browser.