//Uses $LK,"fixed-point",A="FI:::/Demo/Lectures/FixedPoint.CC"$.

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_é;
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;

		$SP,"<1>",BI=1$


		$SP,"<2>",BI=2$

U0 DrawIt(CTask *task, CDC *dc)
{
	CDC		*map = map_dcs[active_map&1];
	MyMass	*tmpm;
	F64		 é = gun_é;
	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, $IB,"<2>",BI=2$);

	if (é < -ã / 2)
	{
		dc->flags |= DCF_SYMMETRY | DCF_JUST_MIRROR;
		DCSymmetrySet(dc, gun_x + h, 0, gun_x + h, 1);
		é = -ã - é;
	}
	Sprite3ZB(dc, gun_x + h - gun_recoil * Cos(é), gun_y + v - gun_recoil * Sin(é) - 10, 0, $IB,"<1>",BI=1$, é);
	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_é);
	tmpm->y						= gun_y - 15 + 27 * Sin(gun_é);
	tmpm->DxDt					= 600.0 * Cos(gun_é);
	tmpm->DyDt					= 600.0 * Sin(gun_é);
	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_é = 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 $LK,"SettingsPush",A="MN: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_é += 5.0 * ã / 180;
								if (gun_é > 0)
									gun_é = 0;
								else
									MoveTask;
//									Spawn(&MoveTask, NULL, "Move",, Fs);
								break;
							case SC_CURSOR_LEFT:
								gun_é -= 5.0 * ã / 180;
								if (gun_é < -ã)
									gun_é = -ã;
								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;
��������;����������
������� �������
���þÿÿÿ
���þÿÿÿ
��������������������n����������
���ñÿÿÿ���ýÿÿÿ
���ýÿÿÿúÿÿÿþÿÿÿ
úÿÿÿþÿÿÿ���ðÿÿÿ
õÿÿÿÿÿÿÿ���ÿÿÿÿ
����óÿÿÿ����ýÿÿÿ
ôÿÿÿ���
�������