/* * ttyvaders Textmode shoot'em up * Copyright (c) 2002 Sam Hocevar * All Rights Reserved * * $Id$ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include "common.h" static void draw_bomb(int x, int y, int vx, int vy); static void draw_nuke(int x, int y, int frame); static void draw_beam(int x, int y, int frame); static void draw_fragbomb(int x, int y, int frame); void init_weapons(game *g, weapons *wp) { int i; for(i = 0; i < WEAPONS; i++) { wp->type[i] = WEAPON_NONE; } } void draw_weapons(game *g, weapons *wp) { int i; for(i = 0; i < WEAPONS; i++) { switch(wp->type[i]) { case WEAPON_LASER: ee_color(EE_WHITE); ee_goto(wp->x[i] >> 4, wp->y[i] >> 4); ee_putchar('|'); ee_color(EE_CYAN); ee_goto(wp->x[i] >> 4, (wp->y[i] >> 4) + 1); ee_putchar('|'); break; case WEAPON_SEEKER: ee_color(EE_CYAN); ee_goto(wp->x3[i] >> 4, wp->y3[i] >> 4); ee_putchar('.'); ee_goto(wp->x2[i] >> 4, wp->y2[i] >> 4); ee_putchar('o'); ee_color(EE_WHITE); ee_goto(wp->x[i] >> 4, wp->y[i] >> 4); ee_putchar('@'); break; case WEAPON_BOMB: ee_color(EE_GRAY); ee_goto((wp->x[i] - wp->vx[i]) >> 4, (wp->y[i] - wp->vy[i]) >> 4); ee_putchar('.'); ee_goto((wp->x3[i] - wp->vx[i]) >> 4, (wp->y3[i] - wp->vy[i]) >> 4); ee_putchar('.'); ee_goto((wp->x2[i] - wp->vx[i]) >> 4, (wp->y2[i] - wp->vy[i]) >> 4); ee_putchar('.'); ee_goto(wp->x3[i] >> 4, wp->y3[i] >> 4); ee_putchar('.'); ee_goto(wp->x2[i] >> 4, wp->y2[i] >> 4); ee_putchar('.'); draw_bomb(wp->x[i] >> 4, wp->y[i] >> 4, wp->vx[i], wp->vy[i]); break; case WEAPON_FRAGBOMB: draw_fragbomb(wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]); break; case WEAPON_BEAM: draw_beam(wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]); break; case WEAPON_NUKE: draw_nuke(wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]); break; case WEAPON_LIGHTNING: case WEAPON_NONE: break; } } } void update_weapons(game *g, weapons *wp) { int i, j, dist, xmin, ymin, dx, dy, xnew, ynew; for(i = 0; i < WEAPONS; i++) { switch(wp->type[i]) { case WEAPON_LASER: wp->x[i] += wp->vx[i]; wp->y[i] += wp->vy[i]; if(wp->y[i] < 0) { wp->type[i] = WEAPON_NONE; } break; case WEAPON_BOMB: case WEAPON_SEEKER: /* Update tail */ wp->x3[i] = wp->x2[i]; wp->y3[i] = wp->y2[i]; wp->x2[i] = wp->x[i]; wp->y2[i] = wp->y[i]; wp->x[i] += wp->vx[i]; wp->y[i] += wp->vy[i]; if(wp->y[i] < 0) { wp->type[i] = WEAPON_NONE; break; } if(wp->n[i] < 0) { /* Stop updating direction */ break; } wp->n[i]--; /* Estimate our position next frames */ xnew = wp->x[i] + wp->vx[i]; ynew = wp->y[i] + wp->vy[i]; xmin = xnew; ymin = - (g->h << 4); dist = (xnew - xmin) * (xnew - xmin) + 4 * (ynew - ymin) * (ynew - ymin); /* Find the nearest alien */ for(j = 0; j < ALIENS; j++) { if(g->al->type[j] != ALIEN_NONE) { int alx = g->al->x[j] << 4; int aly = g->al->y[j] << 4; int new = (xnew - alx) * (xnew - alx) + 4 * (ynew - aly) * (ynew - aly); if(new <= dist) { dist = new; xmin = alx; ymin = aly; } } } /* Find our new direction */ dx = xmin - wp->x[i]; dy = ymin - wp->y[i]; /* Normalize direction */ if(dx | dy) { int norm = ee_sqrt(dx * dx + 4 * dy * dy); dx = dx * 32 / norm; dy = dy * 32 / norm; } /* Find our new speed */ dx = (dx + 3 * wp->vx[i]) / 4; dy = (dy + 3 * wp->vy[i]) / 4; /* Normalize speed */ if(dx | dy) { int norm = ee_sqrt(dx * dx + 4 * dy * dy); wp->vx[i] = dx * 32 / norm; wp->vy[i] = dy * 32 / norm; } break; case WEAPON_FRAGBOMB: /* If n was set to -1, the fragbomb just exploded */ if(wp->n[i] == -1) { int coords[] = { 32, 0, -32, 0, 0, 16, 0, -16, 28, 8, -28, 8, 28, -8, -28, -8, 24, 12, -24, 12, 24, -12, -24, -12, 16, 14, -16, 14, 16, -14, -16, -14 }; for(j = 0 ; j < sizeof(coords) / sizeof(int) ; j += 2) { add_weapon(g, g->wp, wp->x[i] + coords[j], wp->y[i] + coords[j+1] / 2, coords[j], coords[j+1], WEAPON_SEEKER); add_weapon(g, g->wp, wp->x[i] + coords[j] / 2, wp->y[i] + coords[j+1], coords[j], coords[j+1], WEAPON_SEEKER); } wp->type[i] = WEAPON_NONE; } wp->x[i] += wp->vx[i]; wp->y[i] += wp->vy[i]; wp->n[i]++; if(wp->y[i] < 0) { wp->type[i] = WEAPON_NONE; } break; case WEAPON_BEAM: wp->x[i] = (g->p->x + 2) << 4; wp->y[i] = g->p->y << 4; wp->n[i]--; if(wp->n[i] < 0) { wp->type[i] = WEAPON_NONE; } break; case WEAPON_NUKE: wp->n[i]--; if(wp->n[i] < 0) { wp->type[i] = WEAPON_NONE; } break; case WEAPON_LIGHTNING: case WEAPON_NONE: break; } } } void add_weapon(game *g, weapons *wp, int x, int y, int vx, int vy, int type) { int i; for(i = 0; i < WEAPONS; i++) { if(wp->type[i] == WEAPON_NONE) { wp->x[i] = x; wp->y[i] = y; wp->vx[i] = vx; wp->vy[i] = vy; wp->type[i] = type; wp->n[i] = 0; switch(type) { case WEAPON_LASER: break; case WEAPON_FRAGBOMB: break; case WEAPON_SEEKER: case WEAPON_BOMB: wp->x2[i] = x; wp->y2[i] = y; wp->x3[i] = x; wp->y3[i] = y; wp->n[i] = 20; break; case WEAPON_BEAM: wp->n[i] = 25; break; case WEAPON_NUKE: wp->n[i] = 25; break; case WEAPON_NONE: break; } break; } } } static void draw_bomb(int x, int y, int vx, int vy) { vy *= 2; ee_color(EE_CYAN); if(vx > vy) { if(vx > -vy) /* right quarter */ { if(vy > vx/4) { /* -1pi/6 */ ee_goto(x-4, y-1); ee_putstr("/`-."); ee_goto(x-4, y); ee_putstr("`-._\\"); ee_color(EE_WHITE); ee_goto(x-1, y); ee_putstr("_\\"); ee_goto(x, y+1); ee_putchar('`'); } else if(vy < -vx/4) { /* 1pi/6 */ ee_goto(x-4, y); ee_putstr(",-' "); ee_goto(x-4, y+1); ee_putstr("\\,-'"); ee_color(EE_WHITE); ee_goto(x-1, y-1); ee_putstr("_,"); ee_goto(x, y); ee_putchar('/'); } else { /* 0pi/6 */ ee_goto(x-4, y-1); ee_putstr("____"); ee_goto(x-5, y); ee_putstr("|____"); ee_color(EE_WHITE); ee_goto(x, y); ee_putchar('>'); } } else /* top quarter */ { if(vx > -vy/4) { /* 2pi/6 */ ee_goto(x-2, y); ee_putstr("/ "); ee_goto(x-3, y+1); ee_putstr("/ /"); ee_goto(x-3, y+2); ee_putstr("`'"); ee_color(EE_WHITE); ee_goto(x-1, y-1); ee_putstr("_,"); ee_goto(x, y); ee_putchar('|'); } else if(vx < vy/4) { /* 4pi/6 */ ee_goto(x+1, y); ee_putstr(" \\"); ee_goto(x+1, y+1); ee_putstr("\\ \\"); ee_goto(x+2, y+2); ee_putstr("`'"); ee_color(EE_WHITE); ee_goto(x, y-1); ee_putstr("._"); ee_goto(x, y); ee_putchar('|'); } else { /* 3pi/6 */ ee_goto(x-1, y+1); ee_putstr("| |"); ee_goto(x-1, y+2); ee_putstr("|_|"); ee_color(EE_WHITE); ee_goto(x-1, y); ee_putstr(",^."); } } } else { if(vx > -vy) /* bottom quarter */ { if(vx > vy/4) { /* -2pi/6 */ ee_goto(x-2, y-2); ee_putstr(",."); ee_goto(x-2, y-1); ee_putstr("\\ \\"); ee_goto(x-1, y); ee_putchar('\\'); ee_color(EE_WHITE); ee_goto(x, y); ee_putstr("_|"); } else if(vx < -vy/4) { /* -4pi/6 */ ee_goto(x+1, y-2); ee_putstr(",."); ee_goto(x, y-1); ee_putstr("/ /"); ee_goto(x+1, y); ee_putchar('/'); ee_color(EE_WHITE); ee_goto(x-1, y); ee_putstr("|_/"); } else { /* -3pi/6 */ ee_goto(x, y-3); ee_putchar('_'); ee_goto(x-1, y-2); ee_putstr("| |"); ee_goto(x-1, y-1); ee_putstr("| |"); ee_color(EE_WHITE); ee_goto(x-1, y); ee_putstr("`v'"); } } else /* left quarter */ { if(vy > -vx/4) { /* -5pi/6 */ ee_goto(x+1, y-1); ee_putstr(",-'\\"); ee_goto(x+2, y); ee_putstr(",-'"); ee_goto(x, y+1); ee_putchar('\''); ee_color(EE_WHITE); ee_goto(x, y); ee_putstr("/_"); } else if(vy < vx/4) { /* 5pi/6 */ ee_goto(x+1, y); ee_putstr(" `-."); ee_goto(x+1, y+1); ee_putstr("`-./"); ee_color(EE_WHITE); ee_goto(x, y-1); ee_putstr("._"); ee_goto(x, y); ee_putchar('\\'); } else { /* 6pi/6 */ ee_goto(x+1, y-1); ee_putstr("____"); ee_goto(x+1, y); ee_putstr("____|"); ee_color(EE_WHITE); ee_goto(x, y); ee_putchar('<'); } } } } static void draw_fragbomb(int x, int y, int frame) { ee_color(EE_WHITE); ee_color(frame & 1 ? EE_CYAN : EE_WHITE); ee_goto(x-2, y); ee_putstr("( )"); ee_goto(x-1, y+1); ee_putstr("`--'"); ee_color(frame & 1 ? EE_WHITE : EE_CYAN); ee_goto(x-1, y-1); ee_putstr(",--."); ee_goto(x, y); ee_putstr("',"); switch(frame % 4) { case 0: ee_color(EE_CYAN); ee_goto(x, y + 2); ee_putchar('O'); ee_goto(x + 2, y + 2); ee_putchar('o'); ee_goto(x + 1, y + 3); ee_putchar('o'); ee_color(EE_GRAY); ee_goto(x - 1, y + 3); ee_putchar(':'); ee_goto(x + 2, y + 4); ee_putchar(':'); ee_goto(x, y + 4); ee_putchar('.'); ee_goto(x + 1, y + 5); ee_putchar('.'); break; case 1: ee_color(EE_CYAN); //ee_goto(x, y + 1); //ee_putchar('O'); ee_goto(x + 1, y + 2); ee_putchar('O'); ee_goto(x, y + 3); ee_putchar('o'); ee_color(EE_GRAY); ee_goto(x + 2, y + 3); ee_putchar(':'); ee_goto(x + 1, y + 4); ee_putchar(':'); ee_goto(x - 1, y + 4); ee_putchar('.'); ee_goto(x + 2, y + 5); ee_putchar('.'); break; case 2: ee_color(EE_CYAN); //ee_goto(x - 1, y + 1); //ee_putchar('O'); ee_goto(x + 2, y + 2); ee_putchar('O'); ee_goto(x, y + 2); ee_putchar('o'); ee_goto(x + 1, y + 3); ee_putchar('o'); ee_color(EE_GRAY); ee_goto(x, y + 4); ee_putchar(':'); ee_goto(x + 2, y + 4); ee_putchar('.'); ee_goto(x + 1, y + 5); ee_putchar('.'); break; case 3: ee_color(EE_CYAN); //ee_goto(x + 2, y + 1); //ee_putchar('O'); ee_goto(x + 1, y + 2); ee_putchar('O'); ee_goto(x - 1, y + 2); ee_putchar('o'); ee_goto(x + 2, y + 3); ee_putchar('o'); ee_color(EE_GRAY); ee_goto(x, y + 3); ee_putchar(':'); ee_goto(x + 1, y + 4); ee_putchar(':'); ee_goto(x, y + 5); ee_putchar('.'); break; } } static void draw_beam(int x, int y, int frame) { int r = (29 - frame) * (29 - frame) / 8; int i; switch(frame) { case 24: ee_color(EE_WHITE); ee_goto(x, y-3); ee_putstr("__"); ee_goto(x-1, y-2); ee_putchar('\''); ee_goto(x+2, y-2); ee_putchar('`'); break; case 23: ee_color(EE_CYAN); ee_goto(x, y-3); ee_putstr("__"); ee_color(EE_WHITE); ee_goto(x-2, y-2); ee_putstr("-'"); ee_goto(x+2, y-2); ee_putstr("`-"); break; case 22: ee_color(EE_CYAN); ee_goto(x, y-3); ee_putstr("__"); ee_goto(x-1, y-2); ee_putchar('\''); ee_goto(x+2, y-2); ee_putchar('`'); ee_color(EE_WHITE); ee_goto(x-3, y-2); ee_putstr(",-"); ee_goto(x+3, y-2); ee_putstr("-."); break; case 21: ee_color(EE_CYAN); ee_goto(x-1, y-3); ee_putstr("____"); ee_goto(x-2, y-2); ee_putchar('\''); ee_goto(x+3, y-2); ee_putchar('`'); ee_color(EE_WHITE); ee_goto(x-4, y-2); ee_putstr(",-"); ee_goto(x+4, y-2); ee_putstr("-."); break; case 20: ee_color(EE_WHITE); ee_goto(x, y-3); ee_putstr("%%"); ee_goto(x-4, y-2); ee_putchar(','); ee_goto(x+5, y-2); ee_putchar('.'); ee_color(EE_CYAN); ee_goto(x-1, y-3); ee_putchar(':'); ee_goto(x+2, y-3); ee_putchar(':'); ee_goto(x-3, y-2); ee_putstr("-'"); ee_goto(x+3, y-2); ee_putstr("`-"); break; case 19: ee_color(EE_WHITE); ee_goto(x, y-4); ee_putstr("%%"); ee_goto(x, y-3); ee_putstr("##"); ee_color(EE_CYAN); ee_goto(x-1, y-4); ee_putchar(':'); ee_goto(x+2, y-4); ee_putchar(':'); ee_goto(x-1, y-3); ee_putchar('%'); ee_goto(x+2, y-3); ee_putchar('%'); ee_goto(x-4, y-2); ee_putstr(",-'"); ee_goto(x+3, y-2); ee_putstr("`-."); ee_color(EE_BLUE); ee_goto(x-2, y-3); ee_putchar(':'); ee_goto(x+3, y-3); ee_putchar(':'); break; case 18: default: r = (18 - frame) * (18 - frame); ee_color(EE_WHITE); ee_goto(x-1, y-5-r); ee_putstr(":%%:"); ee_goto(x-1, y-4-r); ee_putstr("%##%"); ee_color(EE_CYAN); ee_goto(x-2, y-4-r); ee_putchar(':'); ee_goto(x+3, y-4-r); ee_putchar(':'); ee_goto(x-2, y-2); ee_putchar('\''); ee_goto(x+3, y-2); ee_putchar('`'); ee_color(EE_BLUE); ee_goto(x-3, y-2); ee_putchar(':'); ee_goto(x+4, y-2); ee_putchar(':'); for(i = 0; i <= r; i++) { ee_color(EE_WHITE); ee_goto(x-1, y-3-i); ee_putstr((i+frame) % 5 ? "####" : "%%%%"); ee_color(EE_CYAN); ee_goto(x-2, y-3-i); ee_putchar('%'); ee_goto(x+3, y-3-i); ee_putchar('%'); ee_color(EE_BLUE); ee_goto(x-3, y-3-i); ee_putchar(':'); ee_goto(x+4, y-3-i); ee_putchar(':'); } break; } } static void draw_nuke(int x, int y, int frame) { int r = (29 - frame) * (29 - frame) / 8; /* Lots of duplicate pixels, but we don't care */ ee_color(EE_BLUE); ee_draw_circle(x, y, r++, ':'); ee_color(EE_CYAN); ee_draw_circle(x, y, r++, '%'); ee_color(EE_WHITE); ee_draw_circle(x, y, r++, '#'); ee_draw_circle(x, y, r++, '#'); }