RegDefault("ZealOS/BomberGolf", "I64 best_score=99999;\n"); RegExe("ZealOS/BomberGolf"); <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 */ <6>/* Graphics Not Rendered in HTML */ <7>/* Graphics Not Rendered in HTML */ <8>/* Graphics Not Rendered in HTML */ <9>/* Graphics Not Rendered in HTML */ <10>/* Graphics Not Rendered in HTML */ #define MAP_WIDTH 600 #define MAP_HEIGHT 600 #define TREES_NUM 64 class Tree { I64 x, y; } trees[TREES_NUM]; I64 target_count, key_count; #define TARGETS_NUM 10 #define MDF_TANK 0 #define MDF_BUNKER 1 #define TANK_V 10.0 class Target { F64 x, y, theta; U8 *alive_img, *dead_img1, *dead_img2; U8 type; Bool dead, pad[6]; } targets[TARGETS_NUM]; #define FALL_TIME 3.00 #define EXPLODE_TIME 0.25 class Bomb { Bomb *next, *last; F64 x, y, t; Bool exploding; } bomb_head; F64 v, x, y, theta, thetaf; //thetaf is the final theta. theta is gradually changed until it reaches thetaf. U0 DrawIt(CTask *task, CDC *dc) { I64 i, j; Bomb *tmpb; Target *tmpt; F64 ts = tS, dx, dy; dc->color = ROPF_DITHER|BROWN << 16 | YELLOW; GrRect3(dc, 0, 0, 0, dc->width, dc->height); dc->x = task->pix_width >> 1; dc->y = task->pix_height >> 1; dc->flags |= DCF_TRANSFORMATION; Mat4x4TranslationEqu(dc->r, x, y, 0); Mat4x4RotZ(dc->r, theta); dc->color = BLACK; GrBorder(dc, -MAP_WIDTH >> 1, -MAP_HEIGHT >> 1, MAP_WIDTH >> 1, MAP_HEIGHT >> 1); for (i = 0; i < TARGETS_NUM; i++) { tmpt = &targets[i]; if (tmpt->dead) { if (i & 1) { dc->flags |= DCF_SYMMETRY | DCF_JUST_MIRROR; DCSymmetry3Set(dc, tmpt->x, tmpt->y, 0, tmpt->x, tmpt->y, 1, tmpt->x + 1024 * Cos(tmpt->theta), tmpt->y + 1024 * Sin(tmpt->theta), 0); } if (Blink(15)) Sprite3ZB(dc, tmpt->x, tmpt->y, 0, tmpt->dead_img1, tmpt->theta); else Sprite3ZB(dc, tmpt->x, tmpt->y, 0, tmpt->dead_img2, tmpt->theta); dc->flags &= ~(DCF_SYMMETRY|DCF_JUST_MIRROR); } else Sprite3ZB(dc, tmpt->x, tmpt->y, 0, tmpt->alive_img, tmpt->theta); } for (i = 0; i < TREES_NUM; i++) Sprite3(dc, trees[i].x, trees[i].y, 0, <2>); for (i = 0; i < TARGETS_NUM; i++) { tmpt = &targets[i]; if (tmpt->dead) { for (j = 0; j < 40; j++) { dc->thick = 4; if (j & 1) dc->color = ROPF_DITHER | LTGRAY << 16 | BLACK; else dc->color = ROPF_DITHER | DKGRAY << 16 | LTGRAY; dx = 15 * Sin(ts / 4 + j << 6) + j >> 2; dy = 10 * FullTri(ts / 3 + j / 2.0, 20) + j >> 2; GrPlot3(dc, tmpt->x + 5 + dx + 0.5 * dy, tmpt->y + 0.5 * dx + dy, 0); } } } tmpb = bomb_head.next; while (tmpb != &bomb_head) { if (tmpb->t + FALL_TIME < tS) { if (Blink(10)) Sprite3(dc, tmpb->x, tmpb->y, 0, <9>); else Sprite3(dc, tmpb->x, tmpb->y, 0, <10>); } tmpb = tmpb->next; } dc->flags &= ~DCF_TRANSFORMATION; Sprite3(dc, task->pix_width >> 1, task->pix_height >> 1, 0, <1>); dc->color = RED; GrPrint(dc, 0, 0, "Targets:%02d KeyStrokes:%04d Best:%04d", target_count, key_count, best_score); if (!target_count && Blink(4)) GrPrint(dc, (task->pix_width - FONT_WIDTH * 14) >> 1, (task->pix_height - FONT_HEIGHT) >> 1 - 32, "Game Completed"); } U0 BombHit(Bomb *tmpb) { I64 i; for (i = 0; i < TARGETS_NUM; i++) { if (!targets[i].dead && SqrI64(tmpb->x - targets[i].x) + SqrI64(tmpb->y - targets[i].y) < 20 * 20) { targets[i].dead = TRUE; target_count--; } } QueueRemove(tmpb); Free(tmpb); } U0 BombDrop(F64 x, F64 y) { Bomb *tmpb = MAlloc(sizeof(Bomb)); tmpb->x = x; tmpb->y = y; tmpb->t = tS; tmpb->exploding = FALSE; QueueInsert(tmpb, bomb_head.last); Sweep(FALL_TIME * 1000, 74, 62); } I64 AnimateTask(CTask *) { F64 last_t = tS, dt; I64 i; Bomb *tmpb, *tmpb1; Target *tmpt; while (TRUE) { dt = tS - last_t; last_t = tS; if (bomb_head.next == &bomb_head) { if (target_count) Sound(Freq2Ona(100 + 60 * Clamp(0.1 * (1.0 + Abs(Wrap(thetaf - theta, -pi))) ` 4.0, -3, 3))); else if (key_count < best_score) { best_score = key_count; Sleep(150); Sound(74); Sleep(150); Sound; Sleep(150); Sound(74); Sleep(150); Sound; } else Sound; } theta += dt * (thetaf - theta); x += dt * v * Sin(theta); y += dt * v * Cos(theta); for (i = 0; i < TARGETS_NUM; i++) { tmpt = &targets[i]; if (!tmpt->dead && tmpt->type == MDF_TANK) { tmpt->x += dt * TANK_V * Cos(tmpt->theta); tmpt->y += dt * TANK_V * Sin(tmpt->theta); if (i & 1) tmpt->theta += dt * pi / 16; else tmpt->theta -= dt * pi / 16; } } tmpb = bomb_head.next; while (tmpb != &bomb_head) { tmpb1 = tmpb->next; if (tmpb->t + FALL_TIME + EXPLODE_TIME < tS) BombHit(tmpb); else if (tmpb->t + FALL_TIME < tS && !tmpb->exploding) { Noise(EXPLODE_TIME * 1000, 62, 74); tmpb->exploding = TRUE; } tmpb = tmpb1; } Sleep(10); } return 0; } U0 Init() { I64 i; Target *tmpt; v = 20; x = -MAP_WIDTH >> 1; y = -MAP_HEIGHT >> 1; thetaf = theta = 1 * pi / 4; QueueInit(&bomb_head); MemSet(trees, 0, sizeof(trees)); for (i = 0; i < TREES_NUM; i++) { trees[i].x = RandU32 % MAP_WIDTH - MAP_WIDTH >> 1; trees[i].y = RandU32 % MAP_HEIGHT - MAP_HEIGHT >> 1; } MemSet(targets, 0, sizeof(targets)); for (i = 0; i < TARGETS_NUM; i++) { tmpt = &targets[i]; tmpt->x = RandU32 % MAP_WIDTH - MAP_WIDTH >> 1; tmpt->y = RandU32 % MAP_HEIGHT - MAP_HEIGHT >> 1; if (i < TARGETS_NUM / 3) { tmpt->type = MDF_BUNKER; tmpt->theta = (RandU16 & 3) * pi / 2; tmpt->alive_img = <6>; tmpt->dead_img1 = <7>; tmpt->dead_img2 = <8>; } else { tmpt->type = MDF_TANK; tmpt->theta = Rand * 2 * pi; tmpt->alive_img = <3>; tmpt->dead_img1 = <4>; tmpt->dead_img2 = <5>; } } key_count = 0; target_count = TARGETS_NUM; } U0 CleanUp() { QueueDel(&bomb_head, TRUE); } U0 BomberGolf() { I64 sc; MenuPush( "File {" " Abort(,CH_SHIFT_ESC);" " Exit(,CH_ESC);" "}" "Play {" " Restart(,'\n');" " Faster(,,SC_CURSOR_UP);" " Slower(,,SC_CURSOR_DOWN);" " Left(,,SC_CURSOR_LEFT);" " Right(,,SC_CURSOR_RIGHT);" " Bomb(,CH_SPACE);" "}" ); SettingsPush; //See SettingsPush AutoComplete; WinBorder; WinMax; DocCursor; DocClear; Fs->animate_task = Spawn(&AnimateTask, Fs, "Animate",, Fs); Fs->draw_it = &DrawIt; Init; try { while (TRUE) switch (KeyGet(&sc)) { case 0: switch (sc.u8[0]) { case SC_CURSOR_UP: v += 10; if (v > 300) v = 300; break; case SC_CURSOR_DOWN: v -= 10; if (v < 20) v = 20; break; case SC_CURSOR_LEFT: key_count++; thetaf += 1.0 / (Abs(Wrap(thetaf - theta, -pi)) + 2 * pi); break; case SC_CURSOR_RIGHT: key_count++; thetaf -= 1.0 / (Abs(Wrap(thetaf - theta, -pi)) + 2 * pi); break; } break; case CH_SPACE: key_count++; BombDrop(-x - 0.8 * FALL_TIME * v * Sin(theta), -y - 0.8 * FALL_TIME * v * Cos(theta)); break; case '\n': CleanUp; Init; break; case CH_ESC: case CH_SHIFT_ESC: goto bm_done; } bm_done: } catch PutExcept; SettingsPop; CleanUp; MenuPop; RegWrite("ZealOS/BomberGolf", "I64 best_score=%d;\n", best_score); } BomberGolf;