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

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