//Uses fixed-point. class MyMass:CMass { Bool collision; }; #define MAP_WIDTH 2048 #define MAP_HEIGHT (GR_HEIGHT - 3 * FONT_HEIGHT) I64 gun_x, gun_y, active_map = 0, gun_recoil; F64 gun_theta; CDC *map_dcs[2] = {NULL, NULL}; I16 elevs[MAP_WIDTH]; F64 wind_x; #define DUST_NUM 512 I64 dust_x[DUST_NUM], dust_y[DUST_NUM]; CMathODE *ode = NULL; <1>/* Graphics Not Rendered in HTML */ <2>/* Graphics Not Rendered in HTML */ U0 DrawIt(CTask *task, CDC *dc) { CDC *map = map_dcs[active_map&1]; MyMass *tmpm; F64 theta = gun_theta; I64 i, x, y, w, h = -task->horz_scroll.pos, v = -task->vert_scroll.pos; task->horz_scroll.min = 0; task->horz_scroll.max = MAP_WIDTH - task->pix_width; task->vert_scroll.min = 0; task->vert_scroll.max = MAP_HEIGHT - task->pix_height; map->flags |= DCF_NO_TRANSPARENTS; GrBlot(dc, h, v, map); Sprite3(dc, gun_x + h, gun_y + v, 0, <2>); if (theta < -pi / 2) { dc->flags |= DCF_SYMMETRY | DCF_JUST_MIRROR; DCSymmetrySet(dc, gun_x + h, 0, gun_x + h, 1); theta = -pi - theta; } Sprite3ZB(dc, gun_x + h - gun_recoil * Cos(theta), gun_y + v - gun_recoil * Sin(theta) - 10, 0, <1>, theta); dc->flags &= ~(DCF_SYMMETRY | DCF_JUST_MIRROR); tmpm = ode->next_mass; dc->color = BLACK; map->color = ROP_COLLISION; map->bkcolor = LTCYAN; while (tmpm != &ode->next_mass) { map->collision_count = 0; GrCircle(map, tmpm->x, tmpm->y, 2); if (map->collision_count) tmpm->collision = TRUE; GrCircle(dc, tmpm->x + h, tmpm->y + v, 2); tmpm = tmpm->next; } dc->color = LTGRAY; w = tS * wind_x; for (i = 0; i < DUST_NUM; i++) { x = (dust_x[i] + w) % MAP_WIDTH; y = dust_y[i]; if (y < elevs[x]) GrPlot(dc, x + h, y + v); } } U0 MyDerivative(CMathODE *ode, F64, COrder2D3 *, COrder2D3 *) { MyMass *tmpm = ode->next_mass; while (tmpm != &ode->next_mass) { tmpm->DstateDt->DyDt += 1000.0 * tmpm->mass; tmpm->DstateDt->DxDt += 25.0 * wind_x; tmpm = tmpm->next; } } U0 DrawMap() { CDC *map = map_dcs[(active_map + 1) & 1]; I64 x; map->color = LTCYAN; GrRect(map, 0, 0, MAP_WIDTH, MAP_HEIGHT); map->color = BLACK; for (x = 1; x < MAP_WIDTH; x++) GrLine(map, x - 1, elevs[x - 1], x, elevs[x]); map->color = BROWN; GrFloodFill(map, 0, MAP_HEIGHT - 1, FALSE); active_map++; } //U0 FireTask(I64) U0 FireTask() { MyMass *tmpm; I64 i; if (gun_recoil) return; tmpm = CAlloc(sizeof(MyMass), Fs->parent_task); tmpm->mass = 10.0; tmpm->drag_profile_factor = 0.1; tmpm->x = gun_x + 27 * Cos(gun_theta); tmpm->y = gun_y - 15 + 27 * Sin(gun_theta); tmpm->DxDt = 600.0 * Cos(gun_theta); tmpm->DyDt = 600.0 * Sin(gun_theta); tmpm->collision = FALSE; while (sys_task_being_screen_updated == Fs->parent_task) Yield; QueueInsert(tmpm, ode->last_mass); // Fs->task_end_cb = &SoundTaskEndCB; for (i = 0; i < 60; i++) { Sound(50 * Rand + 10); Sleep(2); gun_recoil = i / 12; } Sound; for (i = 0; i <= 60; i++) { Sleep(1); gun_recoil = 5 - i / 12; } } U0 ManageShots() { I64 i; MyMass *tmpm, *tmpm1; Bool chged = FALSE; tmpm = ode->next_mass; while (tmpm != &ode->next_mass) { tmpm1 = tmpm->next; if (!(0 <= tmpm->x < MAP_WIDTH) || tmpm->collision) { QueueRemove(tmpm); for (i = tmpm->x - 4; i <= tmpm->x + 4; i++) if (0 <= i < MAP_WIDTH) elevs[i] = ClampI64(elevs[i] + 10 - 2 * AbsI64(i - tmpm->x), 0, MAP_HEIGHT - 2); Free(tmpm); chged = TRUE; } tmpm = tmpm1; } if (chged) DrawMap; } //U0 MoveTask(I64) U0 MoveTask() { // static F64 quit_time = 0; F64 quit_time; // if (quit_time) // quit_time = tS + 0.1; // else // { Sound(34); // Fs->task_end_cb = &SoundTaskEndCB; quit_time = tS + 0.1; while (quit_time > tS) Sleep(1); // Yield; Sound; // quit_time = 0; // } } U0 Init() { CDC *map; I64 i, x, y, dy; if (!map_dcs[0]) map_dcs[0] = DCNew(MAP_WIDTH, MAP_HEIGHT); if (!map_dcs[1]) map_dcs[1] = DCNew(MAP_WIDTH, MAP_HEIGHT); map = map_dcs[active_map & 1]; Fs->horz_scroll.pos = 0; Fs->vert_scroll.pos = 0; y = ToI64(0.7 * MAP_HEIGHT) << 32; dy = 0; for (x = 0; x < MAP_WIDTH; x++) { dy = ClampI64(SignI64(RandI16) << 30 + dy, -3 << 32, 3 << 32); y = ClampI64(y + dy, ToI64(0.3 * MAP_HEIGHT) << 32, (MAP_HEIGHT - 2) << 32); elevs[x] = y.i32[1]; } gun_x = RandU32 % (MAP_WIDTH - 100) + 50; gun_y = elevs[gun_x]; gun_theta = 0; gun_recoil = 0; for (x = gun_x - 20; x <= gun_x + 20; x++) elevs[x] = gun_y; wind_x = RandI16 / 250.0; for (i = 0; i < DUST_NUM; i++) { dust_x[i] = RandU16 % MAP_WIDTH; dust_y[i] = RandU16 % MAP_HEIGHT; } ode = ODENew(0, 1e-4, ODEF_HAS_MASSES); ode->derive = &MyDerivative; ode->drag_v2 = 0.002; ode->drag_v3 = 0.0001; ode->acceleration_limit = 5e5; QueueInsert(ode, Fs->last_ode); Fs->horz_scroll.min = 0; Fs->horz_scroll.max = MAP_WIDTH - Fs->pix_width; Fs->horz_scroll.pos = gun_x - Fs->pix_width / 2; Fs->vert_scroll.min = 0; Fs->vert_scroll.max = MAP_HEIGHT - Fs->pix_height; Fs->vert_scroll.pos = 0; TaskDerivedValsUpdate; DrawMap; } U0 CleanUp(CMathODE *ode) { if (ode) { QueueRemove(ode); QueueDel(&ode->next_mass, TRUE); ODEDel(ode); } } U0 BigGuns() { I64 ch, sc; PopUpOk( "Terry refused to rip-off the original\n" "so this is intentionally crappy\n" "and included for demonstration\n" "purposes.\n\n" "Write games, don't play them.\n"); PopUpOk("The map scrolls.\n"); SettingsPush; //See SettingsPush MenuPush( "File {" " Abort(,CH_SHIFT_ESC);" " Exit(,CH_ESC);" "}" "Play {" " Restart(,'\n');" " Fire(,CH_SPACE);" " Left(,,SC_CURSOR_LEFT);" " Right(,,SC_CURSOR_RIGHT);" "}" ); AutoComplete; WinBorder(ON); WinMax; DocCursor; DocClear; DocScroll; Init; Fs->draw_it = &DrawIt; try { while (TRUE) { while (KeyScan(&ch, &sc)) { switch (ch) { case 0: switch (sc.u8[0]) { case SC_CURSOR_RIGHT: gun_theta += 5.0 * pi / 180; if (gun_theta > 0) gun_theta = 0; else MoveTask; // Spawn(&MoveTask, NULL, "Move",, Fs); break; case SC_CURSOR_LEFT: gun_theta -= 5.0 * pi / 180; if (gun_theta < -pi) gun_theta = -pi; else MoveTask; // Spawn(&MoveTask, NULL, "Move",, Fs); break; } break; case '\n': CleanUp(ode); Init; break; case CH_SPACE: // Spawn(&FireTask, NULL, "Fire",, Fs); FireTask; break; case CH_SHIFT_ESC: case CH_ESC: goto bg_done; } ManageShots; FlushMessages; } ManageShots; Refresh; } bg_done: } catch PutExcept; SettingsPop; DCDel(map_dcs[0]); map_dcs[0] = NULL; DCDel(map_dcs[1]); map_dcs[1] = NULL; CleanUp(ode); MenuPop; } BigGuns;