//Uses fixed-point. <1>/* Graphics Not Rendered in HTML */ <2>/* Graphics Not Rendered in HTML */ <3>/* Graphics Not Rendered in HTML */ <4>/* Graphics Not Rendered in HTML */ <5>/* Graphics Not Rendered in HTML */ #define FRAMES 6 U8 *imgs[FRAMES] = {<1>, <2>, <3>, <4>, <3>, <2>}; F64 fire_end_time; class Trooper { I64 x, y, dx, dy, att, def, rng, player; F64 animate_time_base, fire_end_time; Trooper *target; }; #define TROOPERS_NUM 100 Trooper tr[2][TROOPERS_NUM]; Bool time_lapse = FALSE; #define TAP_MODE_RADIUS 50 Bool tap_mode; #define AI_NOTHING 0 #define AI_TARGET 1 #define AI_RANDOM 2 #define AI_AI_NUM 3 I64 ai_mode; I64 ai_targets[10]; U0 DrawTrooper(CTask *, CDC *dc, Trooper *tmpt) { U8 *tmps; I64 x, y, gx, gy; F64 speed, tt; if (tmpt->def > 0) { x = tmpt->dx >> 28; y = tmpt->dy >> 28; speed = 0.5 * Sqrt(x * x + y * y); tt = tmpt->animate_time_base + tS * speed; if (time_lapse) { x = (tmpt->x + 500 * tmpt->dx) >> 32; y = (tmpt->y + 500 * tmpt->dy) >> 32; } else { x = tmpt->x.i32[1]; y = tmpt->y.i32[1]; } if (tmpt->target) { gx = x; gy = y; if (tmpt->dx < 0) { dc->flags |= DCF_SYMMETRY | DCF_JUST_MIRROR; DCSymmetrySet(dc, x, y, x, y + 1); gx -= 13; gy -= 7; } else { dc->flags &= ~DCF_SYMMETRY | DCF_JUST_MIRROR; gx += 13; gy -= 7; } dc->color = BLACK; Sprite3(dc, x + 1, y, 0, <5>); if (!tmpt->player) dc->color = LTCYAN; else dc->color = LTPURPLE; Sprite3(dc, x, y, 0, <5>); dc->flags &= ~(DCF_SYMMETRY | DCF_JUST_MIRROR); if (!tmpt->player) dc->color = WHITE; else dc->color = LTBLUE; GrLine3(dc, gx, gy, 0, tmpt->target->x.i32[1], tmpt->target->y.i32[1], 0); } else { if (tmpt->dx < 0) { dc->flags |= DCF_SYMMETRY | DCF_JUST_MIRROR; DCSymmetrySet(dc, x, y, x, y + 1); } else dc->flags &= ~DCF_SYMMETRY | DCF_JUST_MIRROR; tmps = SpriteInterpolate(tt % 1.0, imgs[tt % FRAMES], imgs[(tt + 1.0) % FRAMES]); dc->color = BLACK; Sprite3(dc, x + 1, y, 0, tmps); if (!tmpt->player) dc->color = LTCYAN; else dc->color = LTPURPLE; Sprite3(dc, x, y, 0, tmps); Free(tmps); dc->flags &= ~(DCF_SYMMETRY | DCF_JUST_MIRROR); } } } U0 DrawIt(CTask *task, CDC *dc) { Trooper *tmpt=tr; I64 i, j, count[2], x = mouse.pos.x - task->pix_left - task->scroll_x, y = mouse.pos.y - task->pix_top - task->scroll_y; Bool repulsive = mouse.pos.z > 0 ^^ mouse.rb, active = !winmgr.grab_scroll && (mouse.lb || mouse.rb); for (j = 0; j < 2; j++) { count[j] = 0; for (i = 0; i < TROOPERS_NUM; i++, tmpt++) { if (tmpt->def > 0) { DrawTrooper(task, dc, tmpt); count[j]++; } } } if (tap_mode) { dc->color = YELLOW; GrCircle(dc, x, y, TAP_MODE_RADIUS); } else { if (repulsive) { if (active) dc->color = LTRED; else dc->color = RED; } else { if (active) dc->color = LTBLUE; else dc->color = BLUE; } GrCircle(dc, x, y, AbsI64(mouse.pos.z)); } dc->color = LTCYAN; GrPrint(dc, (task->win_right - 8) * FONT_WIDTH, 0, "%03d", count[0]); dc->color = LTPURPLE; GrPrint(dc, (task->win_right - 4) * FONT_WIDTH, 0, "%03d", count[1]); } U0 DoAiTarget() { I64 i, j; Trooper *tmpt1, *tmpt0; for (i = 0; i < 10; i++) { tmpt0 = &tr[0][ai_targets[i]]; for (j = 0; j < 10; j++) { tmpt1 = &tr[1][i * 10 + j]; tmpt1->dx = (tmpt0->x - tmpt1->x) >> 11; tmpt1->dy = (tmpt0->y - tmpt1->y) >> 11; } } } U0 UpdatePos() { I64 i, j; Trooper *tmpt = tr; for (j = 0; j < 2; j++) for (i = 0; i < TROOPERS_NUM; i++, tmpt++) { tmpt->x += tmpt->dx; if (tmpt->x >= GR_WIDTH << 32) tmpt->x -= GR_WIDTH << 32; if (tmpt->x < 0) tmpt->x += GR_WIDTH << 32; tmpt->y += tmpt->dy; if (tmpt->y >= GR_HEIGHT << 32) tmpt->y -= GR_HEIGHT << 32; if (tmpt->y < 0) tmpt->y += GR_HEIGHT << 32; } } U0 ResolveFiring() { I64 i, j, dd, dx, dy; Trooper *tmpt = tr, *tmpt0, *tmpt1; for (j = 0; j < 2; j++) for (i = 0; i < TROOPERS_NUM; i++, tmpt++) { if (tmpt->target && tmpt->fire_end_time < tS) { tmpt->target->def -= tmpt->att; tmpt->fire_end_time = 0; tmpt->target = NULL; } } for (i = 0; i < TROOPERS_NUM; i++) { tmpt0 = &tr[0][i]; for (j = 0; j < TROOPERS_NUM; j++) { tmpt1 = &tr[1][j]; if (tmpt0->def > 0 && tmpt1->def > 0) { dx = (tmpt0->x - tmpt1->x) >> 32; dy = (tmpt0->y - tmpt1->y) >> 32; dd = dx * dx + dy * dy; if (dd < tmpt0->rng && !tmpt0->target) { fire_end_time = tmpt0->fire_end_time = tS + 0.125; Sound(86); tmpt0->target = tmpt1; } if (dd < tmpt1->rng && !tmpt1->target) { fire_end_time = tmpt1->fire_end_time = tS + 0.125; Sound(86); tmpt1->target = tmpt0; } } } } if (tS >= fire_end_time) Sound; } U0 UpdateHumanVelocities() { F64 intensity; I64 i, j, dx, dy, d, x = mouse.pos.x - Fs->pix_left - Fs->scroll_x, y = mouse.pos.y - Fs->pix_top - Fs->scroll_y; Bool active = !winmgr.grab_scroll && (mouse.lb || mouse.rb); Trooper *tmpt = &tr[0][0]; if (tap_mode) { for (i = 0; i < TROOPERS_NUM; i++, tmpt++) { dx = x - tmpt->x.i32[1]; dy = y - tmpt->y.i32[1]; if ((d = dx * dx + dy * dy) && d < TAP_MODE_RADIUS * TAP_MODE_RADIUS) { intensity = SqrI64(SqrI64(SqrI64(TAP_MODE_RADIUS) - d)); dx = intensity * dx / d; dy = intensity * dy / d; tmpt->dx = tmpt->dx - dx; tmpt->dy = tmpt->dy - dy; } else { tmpt->dx -= 0.2 * tmpt->dx; tmpt->dy -= 0.2 * tmpt->dy; } } } else if (active) { j = 400000000 * mouse.pos.z; if (mouse.rb) j =-j; for (i = 0; i < TROOPERS_NUM; i++, tmpt++) { dx = x - tmpt->x.i32[1]; dy = y - tmpt->y.i32[1]; if (d = dx * dx + dy * dy) { dx = j * dx / d; dy = j * dy / d; tmpt->dx = tmpt->dx - dx; tmpt->dy = tmpt->dy - dy; } } } } U0 Init() { I64 i, j, dx, dy; Trooper *tmpt; MouseSet(,, 25); tap_mode = FALSE; time_lapse = FALSE; fire_end_time = 0; MemSet(tr, 0, sizeof(tr)); for (i = 0; i < 10; i++) { ai_targets[i] = RandU16 % TROOPERS_NUM; dx = RandI32; dy = RandI32; for (j = 0; j < 10; j++) { tmpt = &tr[0][i * 10 + j]; tmpt->x = (GR_WIDTH - 100 - i * 10) << 32; tmpt->y = (GR_HEIGHT >> 1 - 50 + j * 10) << 32; tmpt->att = 3; tmpt->def = 10; tmpt->rng = 50 * 50; tmpt->animate_time_base = 10 * Rand; tmpt->player = 0; tmpt = &tr[1][i * 10 + j]; tmpt->x = (100 + i * 10) << 32; tmpt->y = (GR_HEIGHT >> 1 - 50 + j * 10) << 32; if (ai_mode == AI_RANDOM) { tmpt->dx = dx; tmpt->dy = dy; } tmpt->att = 3; tmpt->def = 10; tmpt->rng = 50 * 50; tmpt->animate_time_base = 10 * Rand; tmpt->player = 1; } } ai_mode = RandU16 % AI_AI_NUM; } U0 BattleLines() { CMenuEntry *tmpse; MenuPush( "File {" " Abort(,CH_SHIFT_ESC);" " Exit(,CH_ESC);" "}" "Play {" " Restart(,'\n');" " TimeLapse(,'1');" " TapMode(,'2');" "}" ); SettingsPush; //See SettingsPush Fs->text_attr = GREEN << 4 + WHITE; AutoComplete; WinBorder; WinMax; DocCursor; DocClear; Init; Fs->draw_it = &DrawIt; PopUpOk("The mouse wheel controls\n" "the command force.\n" "Attract or repel with\n" "left or right button.\n\n"); Fs->win_inhibit = WIG_TASK_DEFAULT - WIF_SELF_FOCUS - WIF_SELF_BORDER - WIF_FOCUS_TASK_MENU; try { while (TRUE) { switch (CharScan) { case '1': time_lapse = !time_lapse; tmpse = MenuEntryFind(Fs->cur_menu, "Play/TimeLapse"); tmpse->checked = time_lapse; break; case '2': tap_mode = !tap_mode; tmpse = MenuEntryFind(Fs->cur_menu, "Play/TapMode"); tmpse->checked = tap_mode; break; case CH_ESC: case CH_SHIFT_ESC: goto wg_done; case '\n': Init; break; } Sleep(40); if (ai_mode == AI_TARGET) DoAiTarget; UpdateHumanVelocities; UpdatePos; ResolveFiring; } wg_done: } catch PutExcept; SettingsPop; MenuPop; } BattleLines;