RegDefault("ZealOS/FlapBat", "F64 best_score=9999;\n"); RegExe("ZealOS/FlapBat"); <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 BORDER 6 #define EAT_TIME 0.5 #define FLAP_TIME 0.5 #define BAT_BOX 10 Bool flap_down, flap_up; F64 flap_phase, delta_phase, bat_y, bat_x, eat_timeout, flap_time; F64 frame_x, game_t0, game_tf; #define BUGS_NUM 32 I32 bug_count, bugs_x[BUGS_NUM], bugs_y[BUGS_NUM]; Bool bugs_dead[BUGS_NUM]; #define GLOW_PERIOD 3.0 F64 bugs_glow_phase[BUGS_NUM]; CDC *limit_flood_fill_dc; //Prevent uncontrolled flood-fill flicker. U0 DrawIt(CTask *task, CDC *dc) { I64 i, y, x, h = MaxI64(1, task->pix_width - 2 * BORDER), v = MaxI64(1, task->pix_height - 2 * BORDER); U8 *tmps, *tmps2, *tmps3; F64 tt = flap_phase * flap_phase * flap_phase, ts = tS; bat_x = task->pix_width >> 3; Sprite3(dc, (7 * task->pix_width) >> 3, 20, 0, <5>); dc->color = DKGRAY; GrCircle(dc, bat_x + 5 + 20 * Saw(15 * tS, 2), bat_y, 10 + 20 * Saw(15 * tS, 2), 5, -pi/4, pi/2); tmps = SpriteInterpolate(tt, <1>, <2>); if (eat_timeout && tS < eat_timeout) { tmps2 = SpriteInterpolate(tt, <3>, <4>); tmps3 = SpriteInterpolate(1.0 - (eat_timeout - tS) / EAT_TIME, tmps2, tmps); Free(tmps); Free(tmps2); tmps = tmps3; } DCFill(limit_flood_fill_dc); Sprite3(limit_flood_fill_dc, 16, 32, 0, tmps); if (GrPeek(limit_flood_fill_dc, 0, 0) != TRANSPARENT) {//Did FloodFill go crazy? limit_flood_fill_dc->color = TRANSPARENT; GrFloodFill(limit_flood_fill_dc, 0, 0); } GrBlot(dc, bat_x - 16, bat_y - 32, limit_flood_fill_dc); Free(tmps); for (i = 0; i < BUGS_NUM; i++) if (!bugs_dead[i]) { x = (bugs_x[i] + frame_x) % h + BORDER; y = bugs_y[i] % v + BORDER; if (Saw(ts + bugs_glow_phase[i], GLOW_PERIOD) < 0.2) { if (i & 1) dc->color = YELLOW; else dc->color = LTGREEN; } else dc->color = BLACK; GrPlot(dc, x, y); GrPlot(dc, x + 1, y); dc->color = BLACK; GrPlot(dc, x, y - 1); } if (game_tf) { dc->color = RED; GrPrint(dc, (task->pix_width - FONT_WIDTH * 14) / 2, (task->pix_height - FONT_HEIGHT) / 2, "Game Completed"); tt = game_tf; } else { dc->color = BLACK; tt = tS; } GrPrint(dc, 0, 0, "Bugs:%3.1f%% Time:%3.2f Best:%3.2f", 100.0 * (BUGS_NUM - bug_count) / BUGS_NUM, tt-game_t0, best_score); } U0 CheckBugs(CTask *task) { I64 i, x, y, h = MaxI64(1, task->pix_width - 2 * BORDER), v = MaxI64(1, task->pix_height - 2 * BORDER); if (eat_timeout && eat_timeout - tS < 0.75 * EAT_TIME) { Suspend(task->song_task, FALSE); if (tS >= eat_timeout) eat_timeout = 0; } for (i = 0; i < BUGS_NUM; i++) if (!bugs_dead[i]) { x = (bugs_x[i] + frame_x) % h + BORDER; y = bugs_y[i] % v + BORDER; if (AbsI64(x - bat_x) < BAT_BOX && AbsI64(y - bat_y) < BAT_BOX) { bugs_dead[i] = TRUE; eat_timeout = tS + EAT_TIME; Sound(74); Suspend(task->song_task); bug_count--; } } if (!game_tf && !bug_count) { game_tf = tS; Suspend(task->song_task); Sound; if (game_tf - game_t0 < best_score) best_score = game_tf - game_t0; } frame_x -= 0.1; if (frame_x < 0) frame_x += h; } U0 Init() { I64 i; limit_flood_fill_dc = DCNew(32, 40); flap_down = flap_up = FALSE; flap_phase = 0; bat_x = Fs->pix_width >> 3; bat_y = 0; frame_x = 0; bug_count = BUGS_NUM; for (i = 0; i < BUGS_NUM; i++) { bugs_dead[i] = FALSE; bugs_x[i] = RandU16; bugs_y[i] = RandU16; bugs_glow_phase[i] = GLOW_PERIOD * Rand; } Suspend(Fs->song_task, FALSE); flap_time = eat_timeout = 0; delta_phase = game_tf = 0; game_t0 = tS; } U0 SongTask(I64) {//Song by Terry A. Davis Fs->task_end_cb = &SoundTaskEndCB; MusicSettingsReset; while (TRUE) { Play("4eB5E4B5C4B5EsEFqE4eB5E4B5C4B5EsEF"); Play("5qE4eA5D4ABA5DsDCqD4eB5E4B5C4B"); Play("5EsEDqE"); } } U0 AnimateTask(I64) { while (TRUE) { if (flap_down) { flap_down = FALSE; delta_phase = -0.005 * Min(1.0, (tS - flap_time) / FLAP_TIME); flap_time = tS; } else if (flap_up) { flap_up = FALSE; delta_phase = 0.005; } if (delta_phase < 0) { bat_y += 75 * delta_phase; delta_phase += 0.000015; } else bat_y += 0.15; bat_y = Clamp(bat_y, BORDER, Fs->parent_task->pix_height - BORDER); flap_phase = Clamp(flap_phase + delta_phase, 0.0, 1.0); CheckBugs(Fs->parent_task); Sleep(1); } } U0 CleanUp() { DCDel(limit_flood_fill_dc); } U0 FlapBat() { Bool reset_space = TRUE; I64 arg1, arg2; MenuPush( "File {" " Abort(,CH_SHIFT_ESC);" " Exit(,CH_ESC);" "}" "Play {" " Restart(,'\n');" " Flap(,CH_SPACE);" "}" ); PopUpOk("Use $GREEN$<SPACE>$FG$ to flap.\nHold down to glide."); SettingsPush; //See SettingsPush Fs->text_attr = LTGRAY << 4 + WHITE; WinBorder(ON); WinHorz(1, TEXT_COLS / 2); WinVert(2, TEXT_ROWS / 2); DocCursor; DocClear; Fs->song_task = Spawn(&SongTask, NULL, "Song",, Fs); Init; Fs->animate_task = Spawn(&AnimateTask, NULL, "Animate",, Fs); Fs->draw_it = &DrawIt; try { while (TRUE) { switch (MessageGet(&arg1, &arg2, 1 << MESSAGE_KEY_DOWN + 1 << MESSAGE_KEY_UP)) { case MESSAGE_KEY_DOWN: switch (arg1) { case CH_SPACE: if (reset_space) { flap_down = TRUE; reset_space = FALSE; } break; case '\n': CleanUp; Init; break; case CH_SHIFT_ESC: case CH_ESC: goto bl_done; } break; case MESSAGE_KEY_UP: switch (arg1) { case CH_SPACE: flap_up = TRUE; reset_space = TRUE; break; } break; } } bl_done: MessageGet(,, 1 << MESSAGE_KEY_UP); } catch PutExcept; SettingsPop; CleanUp; MenuPop; RegWrite("ZealOS/FlapBat", "F64 best_score=%5.4f;\n", best_score); } FlapBat;