templeos-info/public/Wb/Demo/Games/Squirt.HC

383 lines
82 KiB
HolyC
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#define MT_HOSE 1
#define MT_DROPLET 2
class MyMass:CMass
{
I64 type;
F64 radius;
};
#define ST_HOSE 1
class MySpring:CSpring
{
I64 type;
};
$BG,11$
$SP,"<1>",BI=1$
$SP,"<2>",BI=2$
$SP,"<3>",BI=3$
$BG$
$SP,"",BI=4$
#define HOSE_RADIUS 3
#define LINK_SIZE 6
#define NOZZLE_START_Y (GR_HEIGHT-15*FONT_HEIGHT)
#define NOZZLE_LEN 18
#define FAUCET_X (5*HOSE_RADIUS)
#define FAUCET_Y (GR_HEIGHT-12*FONT_HEIGHT)
#define GROUND_Y (GR_HEIGHT-3*FONT_HEIGHT)
MyMass *faucet,*nozzle;
F64 nozzle_é;
CMathODE *ode=NULL;
F64 start_up_timeout;
U0 DrawIt(CTask *,CDC *dc)
{
Bool first;
F64 dx,dy,d;
I64 x1b,y1b,x2b,y2b,
x1a,y1a,x2a,y2a;
MyMass *tmpm,*tmpm1;
MySpring *tmps;
CD3I32 poly[4];
Sprite3(dc,0,GROUND_Y,0,$IB,"<4>",BI=4$);
if (start_up_timeout>tS) {
ode->drag_v2=0.01; //Let hose settle during start-up
ode->drag_v3=0.0001;
dc->color=RED;
GrPrint(dc,(GR_WIDTH-FONT_WIDTH*6)>>1,GR_HEIGHT>>1,"Squirt");
return;
} else {
ode->drag_v2=0.0005;
ode->drag_v3=0.0000025;
}
tmpm=faucet;
dc->color=BLACK;
GrRect(dc,tmpm->x+8,tmpm->y,8,GROUND_Y-FAUCET_Y);
Sprite3(dc,tmpm->x,tmpm->y,0,$IB,"<1>",BI=1$);
dc->color=BLACK;
GrCircle(dc,tmpm->x,tmpm->y,tmpm->radius);
dc->color=GREEN;
GrFloodFill(dc,tmpm->x,tmpm->y);
tmpm=nozzle;
tmpm1=nozzle->last;
dx=tmpm->x-tmpm1->x;
dy=tmpm->y-tmpm1->y;
nozzle_é=Wrap(Arg(dx,dy));
Sprite3ZB(dc,tmpm->x,tmpm->y,0,$IB,"<2>",BI=2$,nozzle_é);
dc->color=BLACK;
GrCircle(dc,tmpm->x,tmpm->y,tmpm->radius);
dc->color=GREEN;
GrFloodFill(dc,tmpm->x,tmpm->y);
first=TRUE;
tmpm=ode->next_mass;
while (tmpm!=&ode->next_mass) {
if (tmpm->type==MT_HOSE) {
tmpm1=tmpm->last;
dx=tmpm->x-tmpm1->x;
dy=tmpm->y-tmpm1->y;
d=HOSE_RADIUS/Max(Sqrt(dx*dx+dy*dy),0.001);
dx*=d;
dy*=d;
x2a=tmpm->x-dy;
y2a=tmpm->y+dx;
x2b=tmpm->x+dy;
y2b=tmpm->y-dx;
if (first)
first=FALSE;
else {
dc->color=GREEN;
poly[0].x=x1a;
poly[0].y=y1a;
poly[0].z=0;
poly[1].x=x2a;
poly[1].y=y2a;
poly[1].z=0;
poly[2].x=x2b;
poly[2].y=y2b;
poly[2].z=0;
poly[3].x=x1b;
poly[3].y=y1b;
poly[3].z=0;
GrFillPoly3(dc,4,poly);
}
//Fill gaps
GrLine(dc,x2a,y2a,x2b,y2b);
x1a=x2a;
y1a=y2a;
x1b=x2b;
y1b=y2b;
} else if (tmpm->type==MT_DROPLET)
Sprite3(dc,tmpm->x,tmpm->y,0,$IB,"<3>",BI=3$);
tmpm=tmpm->next;
}
tmps=ode->next_spring;
while (tmps!=&ode->next_spring) {
if (tmps->type==ST_HOSE) {
dx=tmps->end1->x-tmps->end2->x;
dy=tmps->end1->y-tmps->end2->y;
d=HOSE_RADIUS/Max(Sqrt(dx*dx+dy*dy),0.001);
dx*=d;
dy*=d;
dc->color=BLACK;
GrLine(dc,tmps->end1->x-dy,tmps->end1->y+dx,
tmps->end2->x-dy,tmps->end2->y+dx);
GrLine(dc,tmps->end1->x+dy,tmps->end1->y-dx,
tmps->end2->x+dy,tmps->end2->y-dx);
}
tmps=tmps->next;
}
}
U0 MyDerivative(CMathODE *ode,F64 t,COrder2D3 *state,COrder2D3 *DstateDt)
{//The forces due to springs and drag are
//automatically handled by the
//ode code.We can add new forces
//here.
no_warn t,state,DstateDt;
MyMass *tmpm1=ode->next_mass;
while (tmpm1!=&ode->next_mass) {
if (tmpm1->type==MT_HOSE) {
if (tmpm1->state->y+tmpm1->radius>GROUND_Y)
tmpm1->DstateDt->DyDt-=Sqr(Sqr(tmpm1->state->y+
tmpm1->radius-GROUND_Y))*tmpm1->mass;
else
tmpm1->DstateDt->DyDt+=500*tmpm1->mass;
if (tmpm1==nozzle || tmpm1==faucet) {
tmpm1->DstateDt->DxDt=0;
tmpm1->DstateDt->DyDt=0;
}
} else if (tmpm1->type==MT_DROPLET)
tmpm1->DstateDt->DyDt=500*tmpm1->mass;
tmpm1=tmpm1->next;
}
}
MyMass *PlaceMass(I64 type,I64 x, I64 y,F64 r,
F64 dx,F64 dy,F64 mass,CTask *mem_task)
{
MyMass *tmpm=CAlloc(sizeof(MyMass),mem_task);
tmpm->type=type;
tmpm->mass=mass;
tmpm->drag_profile_factor=250.0;
tmpm->x=x;
tmpm->y=y;
tmpm->DxDt=dx;
tmpm->DyDt=dy;
tmpm->radius=r;
QueIns(tmpm,ode->last_mass);
return tmpm;
}
MySpring PlaceSpring(MyMass *tmpm1,MyMass *tmpm2)
{
MySpring *tmps=CAlloc(sizeof(MySpring));
tmps->end1=tmpm1;
tmps->end2=tmpm2;
tmps->const=20000;
QueIns(tmps,ode->last_spring);
return tmps;
}
U0 HoseNew()
{
I64 i;
MyMass *tmpm1=NULL,*tmpm;
MySpring *tmps;
for (i=FAUCET_X;i<GR_WIDTH;i+=LINK_SIZE) {
tmpm=PlaceMass(MT_HOSE,i/2,GROUND_Y-HOSE_RADIUS,HOSE_RADIUS,0,0,1.0,Fs);
if (tmpm1) {
tmps=PlaceSpring(tmpm,tmpm1);
tmps->rest_len=LINK_SIZE;
tmps->type=ST_HOSE;
nozzle=tmpm;
} else
faucet=tmpm;
tmpm1=tmpm;
}
faucet->y=FAUCET_Y;
nozzle->y=NOZZLE_START_Y;
nozzle_é=0;
}
U0 AnimateTask(I64)
{
MyMass *tmpm,*tmpm1;
F64 dx,dy;
while (TRUE) {
dx=Cos(nozzle_é);
dy=Sin(nozzle_é);
PlaceMass(MT_DROPLET,
nozzle->x+NOZZLE_LEN*dx,nozzle->y+NOZZLE_LEN*dy,HOSE_RADIUS,
500*dx,500*dy,100.0,Fs->parent_task);
if (Rand<0.05) //faucet drip
PlaceMass(MT_DROPLET,
faucet->x,faucet->y,HOSE_RADIUS,
0,0,100.0,Fs->parent_task);
tmpm=ode->next_mass;
while (tmpm!=&ode->next_mass) {
tmpm1=tmpm->next;
if (tmpm->type==MT_DROPLET && tmpm->y+tmpm->radius>GROUND_Y) {
QueRem(tmpm);
Free(tmpm);
}
tmpm=tmpm1;
}
Refresh;
}
}
#define NOZZLE_MOVE_STEPS 5
#define NOZZLE_MOVE 15.0
U0 MoveNozzleTaskX(I64 sign)
{
I64 i;
for (i=0;i<NOZZLE_MOVE_STEPS;i++) {
nozzle->x=Clamp(nozzle->x+sign*NOZZLE_MOVE/NOZZLE_MOVE_STEPS,
HOSE_RADIUS*3,GR_WIDTH-HOSE_RADIUS*3);
Refresh;
}
}
U0 MoveNozzleTaskY(I64 sign)
{
I64 i;
for (i=0;i<NOZZLE_MOVE_STEPS;i++) {
nozzle->y=Clamp(nozzle->y+sign*NOZZLE_MOVE/NOZZLE_MOVE_STEPS,
HOSE_RADIUS*3,GROUND_Y);
Refresh;
}
}
U0 Init()
{
DocClear;
"$$BG,LTCYAN$$%h*c",ToI64(GROUND_Y/FONT_HEIGHT),'\n';
//Allow hose to settle.
start_up_timeout=tS+0.5;
ode=ODENew(0,5e-2,ODEF_HAS_MASSES);
ode->derive=&MyDerivative;
ode->acceleration_limit=5e3;
HoseNew;
QueIns(ode,Fs->last_ode);
}
U0 CleanUp()
{
Refresh(NOZZLE_MOVE_STEPS); //Let nozzle move tasks die
QueRem(ode);
QueDel(&ode->next_mass,TRUE);
QueDel(&ode->next_spring,TRUE);
ODEDel(ode);
DocClear;
}
U0 SongTask(I64)
{
Fs->task_end_cb=&SndTaskEndCB;
MusicSettingsRst;
while (TRUE) {
Play("5sDCDC4qA5DetDFFeDG4etA5EF4qG5eFC");
Play("5sDCDC4qA5DetDFFeDG4etA5EF4qG5eFC");
Play("5DCsG4A5G4AqBeBA5qEE4B5eC4B");
Play("5DCsG4A5G4AqBeBA5qEE4B5eC4B");
}
}
U0 Squirt()
{
I64 sc;
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
Fs->text_attr=YELLOW<<4+BLUE;
Fs->song_task=Spawn(&SongTask,NULL,"Song",,Fs);
AutoComplete;
WinBorder;
WinMax;
DocCursor;
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" Restart(,'\n');"
" Left(,,SC_CURSOR_LEFT);"
" Right(,,SC_CURSOR_RIGHT);"
" Up(,,SC_CURSOR_UP);"
" Down(,,SC_CURSOR_DOWN);"
"}"
);
Init;
Fs->animate_task=Spawn(&AnimateTask,NULL,"Animate",,Fs);
Fs->draw_it=&DrawIt;
try {
while (TRUE) {
switch (GetKey(&sc)) {
case 0:
switch (sc.u8[0]) {
case SC_CURSOR_LEFT:
Spawn(&MoveNozzleTaskX,-1,"Move Nozzle",,Fs);
break;
case SC_CURSOR_RIGHT:
Spawn(&MoveNozzleTaskX,1,"Move Nozzle",,Fs);
break;
case SC_CURSOR_UP:
Spawn(&MoveNozzleTaskY,-1,"Move Nozzle",,Fs);
break;
case SC_CURSOR_DOWN:
Spawn(&MoveNozzleTaskY,1,"Move Nozzle",,Fs);
break;
}
break;
case '\n':
CleanUp;
Init;
break;
case CH_SHIFT_ESC:
case CH_ESC:
goto sq_done;
}
}
sq_done: //Don't goto out of try
} catch
PutExcept;
SettingsPop;
CleanUp;
MenuPop;
}
Squirt;
R÷ÿÿÿìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ2ÿÿÿÿûÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿJýÿÿÿýÿÿÿÿÿÿ ÿÿ ÿ ÿÿ  ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ'ÿÿÿv