//Uses $LK,"fixed-point",A="FI:::/Demo/Lectures/FixedPoint.ZC"$. RegDefault("ZealOS/CastleFrankenstein", "F64 best_score=9999;\n"); RegExe("ZealOS/CastleFrankenstein"); //Set snap to 4 and width to 4 //if you edit this map. //Don't forget to change the //starting pos. #define MAN_START_X 0 #define MAN_START_Y 4.5 $SP,"<1>",BI=1$ #define MONSTER_SCALE 2.0 $SP,"<2>",BI=2$ $SP,"<3>",BI=3$ $SP,"<4>",BI=4$ #define PLANT_SCALE 2.0 $SP,"<5>",BI=5$ $SP,"<6>",BI=6$ #define SCREEN_SCALE 512 #define PLOT_GRID_WIDTH 24 #define PLOT_GRID_HEIGHT 24 #define MAN_HEIGHT 125 #define MAP_SCALE 4 I64 map_width, map_height; U8 *map = NULL, *panels_processed_bitmap = NULL; I64 man_xx, man_yy; F64 man_Θ; F64 t0, tf; #define MONSTERS_NUM 10 I64 monsters_left; class Monster { I64 x, y; Bool dead, pad[7]; } monsters[MONSTERS_NUM]; U0 CFTransform(CDC *dc, I64 *x, I64 *y, I64 *z) { I64 zz; Mat4x4MulXYZ(dc->r, x, y, z); zz = SCREEN_SCALE / 3 + *z; if (zz < 1) zz = 1; *x = SCREEN_SCALE / 2 * *x / zz; *y = SCREEN_SCALE / 2 * (*y + MAN_HEIGHT) / zz; *x += dc->x; *y += dc->y; *z += dc->z; } #define LOS_SCALE 4 Bool LOSPlot(U8 *, I64 x, I64 y, I64) { if (!map[(y / LOS_SCALE) * map_width + (x / LOS_SCALE)]) return FALSE; else return TRUE; } Bool LOS(I64 x1, I64 y1, I64 x2, I64 y2) {//Line of sight return Line(NULL, x1 * LOS_SCALE / SCREEN_SCALE, y1 * LOS_SCALE / SCREEN_SCALE, 0, x2 * LOS_SCALE / SCREEN_SCALE, y2 * LOS_SCALE / SCREEN_SCALE, 0, &LOSPlot); } U0 DrawIt(CTask *task, CDC *dc) { I64 i, j, *r1, *r2, *r3, *s2w, xx, yy, zz, x, y, x1, y1, z1, c, x1w, y1w, x1h, y1h, xh, yh, zh, cx = task->pix_width / 2, cy = task->pix_height / 2; U8 *tmps; F64 tt; CD3I32 poly[4]; Monster *tmpm; DCDepthBufAlloc(dc); MemSet(panels_processed_bitmap, 0, (map_width * map_height + 7) >> 3); //World to screen Mat4x4RotZ(dc->r, man_Θ + π / 2); Mat4x4RotX(dc->r, π / 2); DCMat4x4Set(dc, dc->r); xh = -man_xx / SCREEN_SCALE; yh = -man_yy / SCREEN_SCALE; zh = 0; Mat4x4MulXYZ(dc->r, &xh, &yh, &zh); Mat4x4TranslationEqu(dc->r, xh, yh, zh); //Screen to world s2w = Mat4x4IdentNew(task); Mat4x4RotX(s2w, -π / 2); Mat4x4RotZ(s2w, -man_Θ - π / 2); xh = 0; yh = 0; zh = SCREEN_SCALE; Mat4x4MulXYZ(s2w, &xh, &yh, &zh); //Rotate light source xx = dc->ls.x; yy = dc->ls.y; zz = -dc->ls.z; (*dc->transform)(dc, &xx, &yy, &zz); dc->ls.x = xx; dc->ls.y = yy; dc->ls.z = zz; dc->flags |= DCF_TRANSFORMATION; dc->transform = &CFTransform; dc->x = cx; dc->y = cy; r1 = Mat4x4IdentNew(task); Mat4x4RotX(r1, -π / 2); Mat4x4RotZ(r1, tS); Mat4x4Scale(r1, MONSTER_SCALE); r2 = Mat4x4IdentNew(task); Mat4x4Scale(r2, MONSTER_SCALE); r3 = Mat4x4IdentNew(task); Mat4x4RotX(r3, -π / 2); Mat4x4Scale(r3, PLANT_SCALE); Seed(1); x1h = man_xx + yh * PLOT_GRID_WIDTH / 2 + xh * (PLOT_GRID_HEIGHT - 1); y1h = man_yy - xh * PLOT_GRID_WIDTH / 2 + yh * (PLOT_GRID_HEIGHT - 1); xh >>= 1; yh >>= 1; for (j = 0; j < PLOT_GRID_HEIGHT * 2; j++) { x1w = x1h; y1w = y1h; for (i = 0; i < PLOT_GRID_WIDTH * 4; i++) { xx = x1w / SCREEN_SCALE; yy = y1w / SCREEN_SCALE; x = xx * SCREEN_SCALE - man_xx; y = yy * SCREEN_SCALE - man_yy; if (1 <= xx < map_width - 1 && 1 <= yy < map_height - 1 && !LBts(panels_processed_bitmap, yy * map_width + xx)) { if ((c = map[yy * map_width + xx]) && LOS(xx * SCREEN_SCALE + SCREEN_SCALE / 2, yy * SCREEN_SCALE + SCREEN_SCALE / 2, man_xx, man_yy)) { if (c == YELLOW) dc->color = DKGRAY; else dc->color = c; poly[0].x = x; poly[0].y = y; poly[0].z = 0; poly[1].x = x + SCREEN_SCALE; poly[1].y = y; poly[1].z = 0; poly[2].x = x + SCREEN_SCALE; poly[2].y = y + SCREEN_SCALE; poly[2].z = 0; poly[3].x = x; poly[3].y = y + SCREEN_SCALE; poly[3].z = 0; GrFillPoly3(dc, 4, poly); if (c == GREEN) { x1 = x + SCREEN_SCALE / 2; y1 = y + SCREEN_SCALE / 2; z1 = 0; DCTransform(dc, &x1, &y1, &z1); if (z1 > 0) Sprite3Mat4x4B(dc, x + SCREEN_SCALE / 2, y + SCREEN_SCALE / 2, 0, $IB,"<5>",BI=5$, r3); } else if (c == YELLOW) { x1 = x + SCREEN_SCALE / 2; y1 = y + SCREEN_SCALE / 2; z1 = 0; DCTransform(dc, &x1, &y1, &z1); if (z1 > 0) Sprite3Mat4x4B(dc, x + SCREEN_SCALE / 2, y + SCREEN_SCALE / 2, 0, $IB,"<6>",BI=6$, r3); } if (!map[(yy + 1) * map_width + xx]) { dc->color = LTGRAY; poly[0].x = x; poly[0].y = y + SCREEN_SCALE; poly[0].z = 0; poly[1].x = x + SCREEN_SCALE; poly[1].y = y + SCREEN_SCALE; poly[1].z = 0; poly[2].x = x + SCREEN_SCALE; poly[2].y = y + SCREEN_SCALE; poly[2].z = SCREEN_SCALE; poly[3].x = x; poly[3].y = y + SCREEN_SCALE; poly[3].z = SCREEN_SCALE; GrFillPoly3(dc, 4, poly); } if (!map[yy * map_width + xx + 1]) { dc->color = WHITE; poly[0].x = x + SCREEN_SCALE; poly[0].y = y; poly[0].z = 0; poly[1].x = x + SCREEN_SCALE; poly[1].y = y + SCREEN_SCALE; poly[1].z = 0; poly[2].x = x + SCREEN_SCALE; poly[2].y = y + SCREEN_SCALE; poly[2].z = SCREEN_SCALE; poly[3].x = x + SCREEN_SCALE; poly[3].y = y; poly[3].z = SCREEN_SCALE; GrFillPoly3(dc, 4, poly); } if (!map[(yy - 1) * map_width + xx]) { dc->color =LTGRAY; poly[0].x = x; poly[0].y = y; poly[0].z = 0; poly[1].x = x + SCREEN_SCALE; poly[1].y = y; poly[1].z = 0; poly[2].x = x + SCREEN_SCALE; poly[2].y = y; poly[2].z = SCREEN_SCALE; poly[3].x = x; poly[3].y = y; poly[3].z = SCREEN_SCALE; GrFillPoly3(dc, 4, poly); } if (!map[yy * map_width + xx - 1]) { dc->color =WHITE; poly[0].x = x; poly[0].y = y; poly[0].z = 0; poly[1].x = x; poly[1].y = y + SCREEN_SCALE; poly[1].z = 0; poly[2].x = x; poly[2].y = y + SCREEN_SCALE; poly[2].z = SCREEN_SCALE; poly[3].x = x; poly[3].y = y; poly[3].z = SCREEN_SCALE; GrFillPoly3(dc, 4, poly); } } } x1w -= yh; y1w += xh; } x1h -= xh; y1h -= yh; } //Draw Monsters for (i = 0, tmpm = monsters; i < MONSTERS_NUM; i++, tmpm++) { x = tmpm->x; y = tmpm->y; if (LOS(x, y, man_xx, man_yy)) { x -= man_xx; y -= man_yy; xx = x; yy = y; zz = 0; DCTransform(dc, &xx, &yy, &zz); if (zz > 0) { if (tmpm->dead) Sprite3Mat4x4B(dc, x, y, 0, $IB,"<2>",BI=2$, r2); else { tt = Tri(tS, 1.0); tmps = SpriteInterpolate(tt, $IB,"<3>",BI=3$, $IB,"<4>",BI=4$); Sprite3Mat4x4B(dc, x, y, 0, tmps, r1); Free(tmps); } } } } Free(r1); Free(r2); Free(r3); //Draw Map heads-up display, scaled 2 pixs Free(dc->r); DCMat4x4Set(dc, Mat4x4IdentNew(task)); dc->x = task->pix_width - 2 * map_width; dc->y = task->pix_height - 2 * map_height; dc->z = 0; dc->transform = &DCTransform; dc->thick = 2; for (i = 0; i < map_height; i++) for (j = 0; j < map_width; j++) { dc->color = map[(map_height - 1 - i) * map_width + j]; GrPlot3(dc, 2 * j, 2 * i, 0); } //Draw Things on heads-up Map dc->color = LTPURPLE; for (i = 0, tmpm = monsters; i < MONSTERS_NUM; i++, tmpm++) if (!tmpm->dead) GrPlot3(dc, 2 * (tmpm->x / SCREEN_SCALE), 2 * (map_height - 1 - tmpm->y / SCREEN_SCALE), 0); dc->color = LTCYAN; GrPlot3(dc, 2 * (man_xx / SCREEN_SCALE), 2 * (map_height - 1 - man_yy / SCREEN_SCALE), 0); if (tf) { dc->color = LTRED; if (Blink) GrPrint(dc, cx - (FONT_WIDTH * 14) / 2, cy - FONT_HEIGHT / 2, "Game Completed"); tt = tf; } else { dc->color = LTGREEN; GrLine(dc, cx - 5, cy, cx + 5, cy); GrLine(dc, cx, cy - 5, cx, cy + 5); tt = tS; } GrPrint(dc, 0, 0, "Enemy:%d Time:%3.2f Best:%3.2f", monsters_left, tt - t0, best_score); Free(s2w); Seed(0); } U0 Fire() { I64 i, x, y; F64 d, dx, dy, xx = Cos(man_Θ), yy = Sin(man_Θ); Monster *tmpm; Noise(100, 53, 74); for (i = 0, tmpm = monsters; i < MONSTERS_NUM; i++, tmpm++) { x = tmpm->x; y = tmpm->y; if (!tmpm->dead && LOS(x, y, man_xx, man_yy)) { dx = x - man_xx; dy = man_yy - y; if (d = Sqrt(dx * dx + dy * dy)) { dx /= d; dy /= d; if (dx * xx + dy * yy > 0.995) { tmpm->dead = TRUE; if (!--monsters_left) { tf = tS; if (tf - t0 < best_score) best_score = tf - t0; } } } } } } U0 Init() { I64 i, x, y; CDC *dc; Monster *tmpm; DocClear; "$$BG,BLACK$$%h*c", TEXT_ROWS / 2, '\n'; dc = Sprite2DC($IB,"<1>",BI=1$); map_width = dc->width / MAP_SCALE + 2; map_height = dc->height / MAP_SCALE + 2; Free(map); Free(panels_processed_bitmap); map = CAlloc(map_width * map_height * sizeof(U8)); panels_processed_bitmap = MAlloc((map_width * map_height + 7) >> 3); for (y = 0; y < map_height - 2; y++) for (x = 0; x < map_width - 2; x++) map[(map_height - 2 - y) * map_width + x + 1] = GrPeek(dc, x * MAP_SCALE, y * MAP_SCALE); DCDel(dc); man_xx = (1 + MAN_START_X) * SCREEN_SCALE; man_yy = (map_height - 1 - MAN_START_Y) * SCREEN_SCALE; man_Θ = 0; for (i = 0, tmpm = monsters; i < MONSTERS_NUM; i++, tmpm++) { tmpm->dead = FALSE; do { tmpm->x = RandU64 % ((map_width - 2) * SCREEN_SCALE) + SCREEN_SCALE; tmpm->y = RandU64 % ((map_height - 2) * SCREEN_SCALE) + SCREEN_SCALE; } while (!map[(tmpm->y / SCREEN_SCALE) * map_width + tmpm->x / SCREEN_SCALE]); } monsters_left = MONSTERS_NUM; tf = 0; t0 = tS; } U0 AnimateTask(I64) { I64 i, x, y, dd; Monster *tmpm; while (TRUE) { dd = 0.25 * SCREEN_SCALE * Sin(tS / 2); for (i = 0, tmpm = monsters; i < MONSTERS_NUM; i++, tmpm++) if (!tmpm->dead) { x = tmpm->x; y = tmpm->y; if (i & 1) x += dd; else y += dd; if (0 <= x <= map_width * SCREEN_SCALE && 0 <= y <= map_height * SCREEN_SCALE && map[(y / SCREEN_SCALE) * map_width + x / SCREEN_SCALE]) { if (!map[(y / SCREEN_SCALE) * map_width + x / SCREEN_SCALE + 1] && x - RoundI64(x, SCREEN_SCALE) > SCREEN_SCALE / 2 || !map[(y / SCREEN_SCALE) * map_width + x / SCREEN_SCALE - 1] && x - RoundI64(x, SCREEN_SCALE) < SCREEN_SCALE / 2) x = RoundI64(x, SCREEN_SCALE) + SCREEN_SCALE / 2; if (!map[(y / SCREEN_SCALE + 1) * map_width + x / SCREEN_SCALE] && y - RoundI64(y, SCREEN_SCALE) > SCREEN_SCALE / 2 || !map[(y / SCREEN_SCALE - 1) * map_width + x / SCREEN_SCALE] && y - RoundI64(y, SCREEN_SCALE) < SCREEN_SCALE / 2) y = RoundI64(y, SCREEN_SCALE) + SCREEN_SCALE / 2; tmpm->x = x; tmpm->y = y; } } Sleep(20); } } U0 CleanUp() { Free(map); Free(panels_processed_bitmap); map = NULL; panels_processed_bitmap = NULL; } U0 SongTask(I64) {//Song by Terry A. Davis Fs->task_end_cb = &SoundTaskEndCB; MusicSettingsReset; while (TRUE) { Play("3q.A#eGAeA#qAq.A#eGeAeA#qA"); Play("3q.A#eGA#AqGq.A#eGA#AqG"); Play("4eA#AqGeA#AqGeA#AGAA#AqG"); } } U0 MoveMan(F64 Θ) { I64 x, y, color, step=SCREEN_SCALE / 2; do { x = man_xx + step * Cos(Θ); y = man_yy - step * Sin(Θ); x = Clamp(x, 0, map_width * SCREEN_SCALE); y = Clamp(y, 0, map_height * SCREEN_SCALE); color = map[y / SCREEN_SCALE * map_width + x / SCREEN_SCALE]; if (color == DKGRAY || color == GREEN) { man_xx = x; man_yy = y; break; } else step >>= 1; } while (step); } //#define MICRO_STEPS 4 #define MICRO_STEPS 32 U0 RotateMan(F64 d) { I64 i; for (i = 0; i < MICRO_STEPS; i++) { man_Θ += d / MICRO_STEPS; // Sleep(15); Sleep(1); } } CTask *mouse_task = NULL; CTask *game_task = Fs; F64 mouse_scale = 32.0; U0 MouseHandler() { Bool button; I64 x; while (MouseRawQueueFind(game_task)) { button = mouse_hard.raw_bttns[0]; x = mouse_hard.raw_data.x; if (button || x != 0) MouseRawReset; // Mark mouse data as consumed if (button) MessagePostWait(game_task, MESSAGE_KEY_DOWN_UP, CH_SPACE, 0); if (x != 0) man_Θ += (x / mouse_scale) / MICRO_STEPS; Sleep(10); } mouse_task = NULL; } U0 CastleFrankenstein() { I64 sc; Bool is_raw = TRUE; MouseRaw(is_raw); mouse_task = Spawn(&MouseHandler, NULL, "MouseHandler"); MenuPush( "File {" " Abort(,CH_SHIFT_ESC);" " Exit(,CH_ESC);" "}" "Play {" " Restart(,'\n');" " Fwd(,,SC_CURSOR_UP);" " Bwd(,,SC_CURSOR_DOWN);" " Left(,,SC_CURSOR_LEFT);" " Right(,,SC_CURSOR_RIGHT);" " Fire(,CH_SPACE);" " MouseMode(,'m');" " MouseScaleUp(,'+');" " MouseScaleDown(,'-');" "}" ); SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$ Fs->text_attr = DKGRAY << 4 + WHITE; AutoComplete; WinBorder; WinMax; DocCursor; Init; Fs->animate_task = Spawn(&AnimateTask, NULL, "Animate",, Fs); Fs->song_task = Spawn(&SongTask, NULL, "Song",, Fs); Fs->draw_it = &DrawIt; try { while (TRUE) { switch (KeyGet(&sc)) { case CH_SPACE: Fire; break; case 'm': if (is_raw) { is_raw = FALSE; MouseRaw(is_raw); Kill(mouse_task); } else { is_raw = TRUE; MouseRaw(is_raw); mouse_task = Spawn(&MouseHandler, NULL, "MouseHandler"); } break; case '+': case '=': mouse_scale *= 0.9; break; case '-': mouse_scale *= 1.1; break; case '\n': Init; break; case CH_ESC: case CH_SHIFT_ESC: goto fs_done; case 0: switch (sc.u8[0]) { case SC_CURSOR_RIGHT: // Spawn(&RotateMan, (π / 32)(I64)); RotateMan(π / 32); FlushMessages; break; case SC_CURSOR_LEFT: // Spawn(&RotateMan, (-π / 32)(I64)); RotateMan(-π / 32); FlushMessages; break; case SC_CURSOR_UP: MoveMan(man_Θ); break; case SC_CURSOR_DOWN: MoveMan(man_Θ + π); break; } break; } } fs_done: } catch PutExcept; DocClear; SettingsPop; CleanUp; MenuPop; RegWrite("ZealOS/CastleFrankenstein", "F64 best_score=%5.4f;\n", best_score); } CastleFrankenstein; MouseRaw(FALSE); &     < << <  ,,, $8 88 8$ $$ $4 44 4 ( ( ( (0 ,0T0 T0TL TL,L ,L,4 04P4 P4PH PH0H 0H08 08L8 L8LD LD4D 4D4< 4<H< H<H@ H@8@ T@l@ l4lL lLêL êLê$ ê$Ç$ Ç$Ç0 Ç0l0 p4ä4 ä(äH ÇHpH pDp8 p8Ç8 Ç8ÇD ÇDtH tDt< t<|< x@|@ |DxD ä ä ät pp p\ \\ \l lh ll l` `` `d dd h h XT PP PL LL (@@ 8H HH H8 88 8D D D D < Z,u @Z DD< DDD\ D\DdT0T8THL0LLd d hh88x8|8|4x4tt$t@8HLL,L4L<LZ<H±   ±   ╪   ∞   ╪   √   ┐   ┐   ╪   ╪   ∞   â   τ   â   √   â   â    t   ÷   t    ┐   ÷   ┐   â    t    â    √   â    τ   â    ┐    ┐    √   ┐    ÷   ┐    ∞   ╪    ±   ╪    ╪    ╪    √    √    ±   √    ∞   √    â    ∞   â    τ   ½   -∞   ½   -½   -½   -░   -░   -∞   ░   -τ   ░   -°   x    ²   |    x    x    |    ÷   t        x    ∞   √   ±   √   ±   √   √   ∞         !!&''"#%$$#       !    $%*$*+'&('()&(( $++ 0/.112-,7765343! 3 45833!839;:7;766;;1 Z<H±   ÷   ±   ╪   ∞   ╪   √   ┐   ┐   ╪   ╪   ∞   ÷   â   τ   â   √   â   â    t   ÷   t    ┐   ÷   ┐   â    t    â    √   â    τ   â    ┐    ┐    √   ┐    ÷   ┐    ∞   ╪    ±   ╪    ╪    ╪    √   √   ±   √   ∞   √   â    ∞   â    τ   ½   -∞   ½   -½   ╙   ½   ╙   ░   ╙   ░   ╙   ∞   ░   -τ   ░   -°   x    ²   |    x    x    |    ÷   t        x    ∞   √   ±   √   ±   √   -√   -∞   --      !!&''"#%$$#       !    $%*$*+'&('()&(( $++ 0/.112-,7765343! 3 45833!839;:7;766;;1 Z<H±   ±   ╪   ∞   ╪   √   ┐   ┐   ╪   ╪   ∞   ÷   â   τ   â   √   â   â    t   ÷   t    ┐   ÷   ┐   â    t    â    √   â    τ   â    ┐    ┐    √   ┐    ÷   ┐    ∞   ╪    ±   ╪    ╪    ╪    √   √   ±   √   ∞   √   â    ∞   â    τ   ½   ╙   ∞   ½   ╙   ½   -½   -░   -░   -∞   ░   ╙   τ   ░   ╙   °   x    ²   |    x    x    |    ÷   t        x    ∞   √   #±   √   #±   #√   √   ∞   #÷         !!&''"#%$$#       !    $%*$*+'&('()&(( $++ 0/.112-,7765343! 3 45833!839;:7;766;;1 ,╬   ╬   √   τ   √   τ   ╡   ì   â   ì   Γ   ╡   Γ   √   ╬   √   ╬   √   √   τ   √   √   τ   √   ╡   √   ì   √   ì   Γ   √   ╡   Γ   ì   ╡   Γ   ╡   Γ   ì   ì   √   ╡   √   Γ   ╡   √   Γ   ì   √                     ≈   ≈   ±   ≈    ⌠    ≈    °   τ   ∞   τ   ∞   τ   °   °   τ   ≡   τ   ≡   τ   °   τ   τ                     (╪   (╪   ╪   ╪   ∞   ╬   ╬   ∞   éé∞   é∞   ∞   é÷   Γ   é Γ   é∞