SparrowOSTS_121127.ISO

This commit is contained in:
Terry A. Davis authored and minexew committed 2018-09-08 21:45:28 +02:00
1 parent 0e9364ff4c
commit e57428affb
1218 files changed
+247142 -165507

No files matched your search

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large. Load diff
Binary file not shown.
+124
View File
@@ -0,0 +1,124 @@
//Practice tracing circles
AcctRegSetDftEntry("SparrowOS/CircleTrace","F64 best_score=999;\n");
AcctRegExecuteBranch("SparrowOS/CircleTrace");
I64 cx,cy;
F64 avg_error=0,elapsed_time=0,total_error=0,score=999;
U0 SongTask(I64)
{
Fs->task_end_cb=&SndTaskEndCB;
MusicSettingsRst;
while (TRUE)
Play("hEDCARCDECR");
}
U0 DrawIt(CTask *task,CDC *)
{
U8 buf[128];
SPrintF(buf,"Error:%6.3f Time:%6.3f Score:%6.3f Best:%8.3f",avg_error,elapsed_time,score,best_score);
PlotWinStr(task,buf,BLACK<<4+WHITE,0,0);
}
#define CIRCLE_RADIUS 100
#define CIRCUMFERENCE (2*ã*CIRCLE_RADIUS)
Bool CTPlot(CDC *dc,I64 x,I64 y,I64)
{
F64 rad=Sqrt(Sqr(x-cx)+Sqr(y-cy));
GrPlot(dc,x,y);
total_error+=Abs(rad-CIRCLE_RADIUS);
return TRUE;
}
U0 CircleTrace()
{
I64 msg_code,p1,p2,x1,y1;
F64 rad,t0,total_distance;
CDC *dc=DCAlias;
SettingsPush; //See $LK,"SettingsPush","MN:SettingsPush"$
Fs->song_task=Spawn(&SongTask,NULL,"Song",Fs);
WordStat;
cx=Fs->win_pixel_width/2;
cy=Fs->win_pixel_height/2;
Fs->win_inhibit=WIF_ALL-WIF_BORDER;
DocCursor;
DocClear;
Fs->draw_it=&DrawIt;
DCFill;
dc->color=ROP_XOR+BLACK^COLOR_TRANSPARENT;
GrCircle(dc,cx,cy,CIRCLE_RADIUS);
do {
msg_code=GetMsg(&p1,&p2,
1<<MSG_KEY_DOWN+1<<MSG_IP_L_DOWN);
switch (msg_code) {
case MSG_KEY_UP:
break;
case MSG_IP_L_DOWN:
DCFill;
dc->color=ROP_XOR+BLACK^COLOR_TRANSPARENT;
GrCircle(dc,cx,cy,CIRCLE_RADIUS);
dc->color=ROP_XOR+RED^COLOR_TRANSPARENT;
t0=tP;
total_distance=0.001;
total_error=0;
x1=p1; y1=p2;
do {
msg_code=ScanMsg(&p1,&p2,
1<<MSG_IP_L_UP+1<<MSG_IP_MOVE);
switch (msg_code) {
case MSG_IP_L_UP:
break;
case MSG_IP_MOVE:
if (x1!=p1 || y1!=p2) {
total_distance+=Sqrt(Sqr(x1-p1)+Sqr(y1-p2));
Line(dc,x1,y1,0,p1,p2,0,&CTPlot);
x1=p1;y1=p2;
//undo overlapping pixels on segments
GrPlot(dc,x1,y1);
rad=Sqrt(Sqr(x1-cx)+Sqr(y1-cy));
total_error-=Abs(rad-CIRCLE_RADIUS);
}
break;
}
elapsed_time=tP-t0;
avg_error=total_error/total_distance;
score=elapsed_time*avg_error;
//This $LK,"Sleep","MN:Sleep"$()s until the next time the
//window mgr task runs. The
//window mgr calls the UpdateWin() routine
//and places msgs in the que, so there's
//no need to do anything until the window mgr runs.
WinMgrSync;
} while (msg_code!=MSG_IP_L_UP);
music_mute=TRUE; Sleep(200);
if (total_distance>0.95*CIRCUMFERENCE) {
if (score<best_score) {
Snd(2000);Sleep(50);Snd(0);Sleep(50);
Snd(2000);Sleep(50);Snd(0);Sleep(50);
Snd(2000);Sleep(50);
best_score=score;
} else {
Snd(500);Sleep(50);
}
} else {
Snd(100);Sleep(1000);
}
Snd(0); Sleep(200); music_mute=FALSE;
break;
}
} while (msg_code!=MSG_KEY_DOWN || p1!=CH_SHIFT_ESC && p1!=CH_ESC);
SettingsPop;
DCFill;
DCDel(dc);
AcctRegWriteBranch("SparrowOS/CircleTrace","F64 best_score=%5.4f;\n",best_score);
}
CircleTrace; //Execute when #included
Binary file not shown.
Binary file not shown.
+509
View File
@@ -0,0 +1,509 @@
//Set snap to 4 and width to 4
//if you edit this map.
//Don't forget to change the
//starting pos.
$BG,0$
$SP,"map",1$
$SP,"hero",2$
$SP,"hero_attack",3$
$SP,"template",4$ //This is a template you can copy and use to make a tile.
//WHITE is the transparent color.
$SP,"tree",5$
$SP,"path",6$
$SP,"water1",7$
$SP,"water2",8$
$SP,"goblin",9$
$SP,"wall1",10$
$SP,"wall2",11$
$BG$
//These are indexed by color #.
//See $LK,"COLORS","MN:RED"$.
U8 *tiles1[16]=
{NULL,$IB,"<7>",7$ ,$IB,"<5>",5$ ,NULL,
$IB,"<6>",6$ ,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL};
U8 *tiles2[16]=
{NULL,$IB,"<8>",8$ ,$IB,"<5>",5$ ,NULL,
$IB,"<6>",6$ ,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL};
#define SCREEN_SCALE 24
#define SCREEN_WIDTH 24
#define SCREEN_HEIGHT 24
I64 screen_x,screen_y;
#define MAP_SCALE 4
I64 map_width,map_height;
U8 *map=NULL;
I64 man_x,man_y,man_dx,man_dy;
Bool man_attack;
F64 man_attack_t0;
#define NUM_MONSTERS 16
class Monster
{
I64 x,y,dx,dy;
Bool dead,pad[7];
} monsters[NUM_MONSTERS];
#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+LOS_SCALE/2,y1*LOS_SCALE+LOS_SCALE/2,0,
x2*LOS_SCALE+LOS_SCALE/2,y2*LOS_SCALE+LOS_SCALE/2,0,&LOSPlot);
}
U0 DrawIt(CTask *task,CDC *dc)
{
CDC *dc_t=DCAlias(gr_dc,task);
I64 i,x,y,xx,yy,x1,y1,z1,color;
CD3I32 poly[4];
U8 **_tiles;
task->text_attr=BLACK<<4;
if (Blink(5,tP(task)))
_tiles=tiles1;
else
_tiles=tiles2;
GrRotXEqu(dc_t->r,60*2*ã/360);
GrRotZEqu(dc_t->r,15*2*ã/360);
GrSetRotMat(dc_t,dc_t->r);
dc_t->x=task->win_pixel_width/2;
dc_t->y=task->win_pixel_height/2;
dc_t->flags|=DCF_TRANSFORMATION;
//You could make it much more efficient
//if you did it like $LK,"::/SparrowOS/Demo/GameStarters/BigGuns.CPP.Z","FI:::/SparrowOS/Demo/GameStarters/BigGuns.CPP.Z"$
//with a $LK,"CDC","MN:CDC"$.
for (y=-SCREEN_HEIGHT/2;y<SCREEN_HEIGHT/2;y++) {
yy=y+screen_y;
if (0<=yy<map_height)
for (x=-SCREEN_WIDTH/2;x<SCREEN_WIDTH/2;x++) {
xx=x+screen_x;
if (0<=xx<map_width) {
if ((color=map[yy*map_width+xx]) &&
LOS(xx,yy,man_x,man_y)) {
if (_tiles[color]) {
x1=x*SCREEN_SCALE;
y1=y*SCREEN_SCALE;
z1=0;
GrTransform(dc_t,&x1,&y1,&z1);
CSpritePlot3(dc,x1,y1,z1,_tiles[color]);
} else { //If no tile defined, do solid color.
poly[0].x=x*SCREEN_SCALE;
poly[0].y=y*SCREEN_SCALE;
poly[0].z=0;
poly[1].x=(x+1)*SCREEN_SCALE-1;
poly[1].y=y*SCREEN_SCALE;
poly[1].z=0;
poly[2].x=(x+1)*SCREEN_SCALE;
poly[2].y=(y+1)*SCREEN_SCALE-1;
poly[2].z=0;
poly[3].x=x*SCREEN_SCALE-1;
poly[3].y=(y+1)*SCREEN_SCALE-1;
poly[3].z=0;
dc_t->color=color;
GrFillPoly3(dc_t,4,poly);
}
}
}
}
}
dc_t->color=LTGRAY;
for (x=-SCREEN_WIDTH/2;x<=SCREEN_WIDTH/2;x++)
GrLine3(dc_t,x*SCREEN_SCALE,-SCREEN_HEIGHT/2*SCREEN_SCALE,0,x*SCREEN_SCALE,SCREEN_HEIGHT/2*SCREEN_SCALE-1,0);
for (y=-SCREEN_HEIGHT/2;y<=SCREEN_HEIGHT/2;y++)
GrLine3(dc_t,-SCREEN_WIDTH/2*SCREEN_SCALE,y*SCREEN_SCALE,0,SCREEN_WIDTH/2*SCREEN_SCALE,y*SCREEN_SCALE-1,0);
for (y=-SCREEN_HEIGHT/2;y<SCREEN_HEIGHT/2;y++) {
yy=y+screen_y;
if (0<=yy<map_height)
for (x=-SCREEN_WIDTH/2;x<SCREEN_WIDTH/2;x++) {
xx=x+screen_x;
if (0<=xx<map_width) {
if (!map[yy*map_width+xx]) {
if (yy+1<map_height && LOS(xx,yy+1,man_x,man_y)) {
x1=x*SCREEN_SCALE;
y1=y*SCREEN_SCALE;
z1=0;
GrTransform(dc_t,&x1,&y1,&z1);
CSpritePlot3(dc,x1,y1,z1,$IB,"<10>",10$);
}
if (xx+1<map_width && LOS(xx+1,yy,man_x,man_y)) {
x1=x*SCREEN_SCALE;
y1=y*SCREEN_SCALE;
z1=0;
GrTransform(dc_t,&x1,&y1,&z1);
CSpritePlot3(dc,x1,y1,z1,$IB,"<11>",11$);
}
}
}
}
}
for (i=0;i<NUM_MONSTERS;i++)
if (!monsters[i].dead && LOS(monsters[i].x,monsters[i].y,man_x,man_y)) {
x1=(monsters[i].x-screen_x)*SCREEN_SCALE+SCREEN_SCALE/2;
y1=(monsters[i].y-screen_y)*SCREEN_SCALE+SCREEN_SCALE/2;
z1=0;
GrTransform(dc_t,&x1,&y1,&z1);
if (monsters[i].dx<0) {
dc->flags|=DCF_SYMMETRY|DCF_JUST_MIRROR;
GrSetSymmetry(dc,x1,y1,x1,y1+1);
} else
dc->flags&=~(DCF_SYMMETRY|DCF_JUST_MIRROR);
CSpritePlot3(dc,x1,y1,z1,$IB,"<9>",9$);
}
x1=(man_x-screen_x)*SCREEN_SCALE+SCREEN_SCALE/2;
y1=(man_y-screen_y)*SCREEN_SCALE+SCREEN_SCALE/2;
z1=0;
if (tP(task)-man_attack_t0<0.2) {
x1+=Tri(tP(task)-man_attack_t0,0.2)*SCREEN_SCALE*man_dx;
y1+=Tri(tP(task)-man_attack_t0,0.2)*SCREEN_SCALE*man_dy;
}
GrTransform(dc_t,&x1,&y1,&z1);
if (man_dx<0) {
dc->flags|=DCF_SYMMETRY|DCF_JUST_MIRROR;
GrSetSymmetry(dc,x1,y1,x1,y1+1);
} else
dc->flags&=~(DCF_SYMMETRY|DCF_JUST_MIRROR);
if (tP(task)-man_attack_t0<0.2)
CSpritePlot3(dc,x1,y1,z1,$IB,"<3>",3$);
else
CSpritePlot3(dc,x1,y1,z1,$IB,"<2>",2$);
DCDel(dc_t);
}
U0 Attack()
{
I64 i;
man_attack_t0=tP;
Noise(100,300,1000);
for (i=0;i<NUM_MONSTERS;i++) {
if (!monsters[i].dead &&
man_x+man_dx==monsters[i].x && man_y+man_dy==monsters[i].y)
monsters[i].dead=TRUE;
}
}
U0 Init()
{
I64 i,x,y,minx,maxx,miny,maxy;
CDC *dc;
CSpriteExtents($IB,"<1>",1$,&minx,&maxx,&miny,&maxy);
map_width =(maxx-minx+1)/MAP_SCALE;
map_height=(maxy-miny+1)/MAP_SCALE;
Free(map);
map=MAlloc(map_width*map_height*sizeof(U8));
dc=DCNew(DCT_COLOR8,map_width*MAP_SCALE,map_height*MAP_SCALE);
CSpritePlot3(dc,-minx,-miny,0,$IB,"<1>",1$);
for (y=0;y<map_height;y++)
for (x=0;x<map_width;x++)
map[y*map_width+x]=GrPeek(dc,x*MAP_SCALE,y*MAP_SCALE);
DCDel(dc);
for (i=0;i<NUM_MONSTERS;i++) {
monsters[i].dead=FALSE;
monsters[i].dx=0;
monsters[i].dy=0;
do {
monsters[i].x=RandU64%(map_width-2)+1;
monsters[i].y=RandU64%(map_height-2)+1;
} while (!map[(monsters[i].y)*map_width+monsters[i].x]);
}
man_attack_t0=tP;
man_attack=FALSE;
man_x=0;
man_y=4;
man_dx=0;
man_dy=0;
screen_x=0;
screen_y=0;
}
U0 CleanUp()
{
Free(map);
map=NULL;
}
U0 AnimateTask(I64)
{
I64 i,x,y,dx,dy;
while (TRUE) {
for (i=0;i<NUM_MONSTERS;i++)
if (!monsters[i].dead) {
dx=RandU16%3-1;
dy=RandU16%3-1;
x=monsters[i].x+dx;
y=monsters[i].y+dy;
if (0<=x<=map_width && 0<=y<=map_height &&
map[y*map_width+x]) {
monsters[i].x=x;
monsters[i].y=y;
monsters[i].dx=dx;
monsters[i].dy=dy;
}
}
Sleep(1000);
}
}
U0 DunGen()
{
I64 ch,sc;
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" Restart(,CH_NEW_LINE);"
" Up(,,SC_CURSOR_UP);"
" Down(,,SC_CURSOR_DOWN);"
" Left(,,SC_CURSOR_LEFT);"
" Right(,,SC_CURSOR_RIGHT);"
" Attack(,CH_SPACE);"
"}"
);
SettingsPush; //See $LK,"SettingsPush","MN:SettingsPush"$
Preempt(OFF);
WinMax;
WordStat;
Init;
Fs->animate_task=Spawn(&AnimateTask,NULL,"Animate",Fs);
DocCursor;
DocClear;
Fs->draw_it=&DrawIt;
try {
while (TRUE) {
switch (GetMsg(&ch,&sc,1<<MSG_KEY_DOWN|1<<MSG_KEY_UP)) {
case MSG_KEY_DOWN:
switch (ch) {
case CH_NEW_LINE:
Init;
break;
case CH_SPACE:
man_attack=TRUE;
break;
case CH_ESC:
case CH_SHIFT_ESC:
goto dg_done;
case 0:
switch (sc.u8[0]) {
case SC_CURSOR_RIGHT:
if (man_attack) {
man_dx=1;
man_dy=0;
Attack;
} else
if (man_x+1<map_width && map[man_y*map_width+(man_x+1)]==RED) {
man_x++;
if (man_x-screen_x>SCREEN_WIDTH/2-3) {
screen_x+=SCREEN_WIDTH/2;
if (screen_x+SCREEN_WIDTH/2>map_width)
screen_x=map_width-SCREEN_WIDTH/2;
}
}
break;
case SC_CURSOR_LEFT:
if (man_attack) {
man_dx=-1;
man_dy=0;
Attack;
} else
if (man_x-1>=0 && map[man_y*map_width+(man_x-1)]==RED) {
man_x--;
if (man_x-screen_x<-SCREEN_WIDTH/2+3) {
screen_x-=SCREEN_WIDTH/2;
if (screen_x-SCREEN_WIDTH/2<0)
screen_x=SCREEN_WIDTH/2;
}
}
break;
case SC_CURSOR_UP:
if (man_attack) {
man_dx=0;
man_dy=-1;
Attack;
} else
if (man_y-1>=0 && map[(man_y-1)*map_width+man_x]==RED) {
man_y--;
if (man_y-screen_y<-SCREEN_HEIGHT/2+3) {
screen_y-=SCREEN_HEIGHT/2;
if (screen_y-SCREEN_HEIGHT/2<0)
screen_y=SCREEN_HEIGHT/2;
}
}
break;
case SC_CURSOR_DOWN:
if (man_attack) {
man_dx=0;
man_dy=1;
Attack;
} else
if (man_y+1<map_height && map[(man_y+1)*map_width+man_x]==RED) {
man_y++;
if (man_y-screen_y>SCREEN_HEIGHT/2-3) {
screen_y+=SCREEN_HEIGHT/2;
if (screen_y+SCREEN_HEIGHT/2>map_height)
screen_y=map_height-SCREEN_HEIGHT/2;
}
}
break;
}
}
break;
case MSG_KEY_UP:
if (ch==CH_SPACE)
man_attack=FALSE;
break;
}
}
dg_done:
GetMsg(,,1<<MSG_KEY_UP);
} catch
CatchAll;
SettingsPop;
MenuPop;
CleanUp;
}
DunGen;
£|˜˜øÿÿÿ˜˜´´´øÿÿÿ´øÿÿÿ˜øÿÿÿ¤¤ œ ° ° °üÿÿÿ°üÿÿÿœüÿÿÿœüÿÿÿœœ¬¬¬¬    ¨¤$Ì$Ì$Ì@Ì@¤@¤@¤(¨(È(È(È<È<¨<¨<¨,¨,Ä,Ä,Ä8Ä8¬8¬8¬0¬0À0À0À4À4°4Ì4ä4ä(ä@ä@@@øøø$ø$ä$è(ü(üü<ø<è<è8è,è,ø,ø,ø8ø8ì<ì8ì0ì0ô0ð4ô4ô8ð8üüüìèøÿÿÿèèÔÔÔøÿÿÿÔøÿÿÿäøÿÿÿäøÿÿÿà ä äüÿÿÿäüÿÿÿØüÿÿÿØüÿÿÿØ Ø Ü Ü ÜààÐÌÈüÿÿÿÈ È Ä Ä Äüÿÿÿ 4�4Œ,Œ<Œ<€<€<€,€,ˆ,ˆ,ˆ8ˆ8„8„8„0˜4˜L”LœLœLœXœX”X”X”P˜P˜T¼ôÿÿÿ¼0¼8¼P¼P¼X°Ä,Ä8Rýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²%þÿÿÿëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿJ$ýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ2ýÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿ    ÿÿÿÿÿÿÿ   ÿÿÿ    ÿÿ      ÿÿÿ    ÿÿ   ÿÿ  ÿÿÿÿÿÿ      ÿÿÿÿÿÿÿÿÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ2ýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿÿÿÿÿ     ÿÿÿ    ÿÿ    ÿÿÿ    ÿÿ    ÿÿ  ÿÿÿÿÿÿ       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ' ìÿÿÿéÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
òþÿÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ¢␍ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²'$ìÿÿÿäÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²öÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+990
View File
@@ -0,0 +1,990 @@
//This uses $LK,"fixed-point","FI:::/SparrowOS/Demo/Lectures/FixedPoint.CPP.Z"$.
//This program can be static compiled to a .BIN.Z or JIT.
//If static compiling, override the finename extention warning.
#ifstatic
#include "::/SparrowOS/OSMain/StaticAdam.HPP.Z"
I64 best_score=0; //Doesn't work yet for statics
#else
AcctRegSetDftEntry("SparrowOS/EagleDive","I64 best_score=0;\n");
AcctRegExecuteBranch("SparrowOS/EagleDive");
#endif
//Keep these power of two so shift is used instead of multiply
//to index arrays.
#define MAP_WIDTH 1024
#define MAP_HEIGHT 1024
#define MAP_SCALE 150
#define DISPLAY_SCALE 100
#define CTRLS_SCALE 0.05
//I think I did these so the heads-up showed intelligable numbers.
//Scaling is a mess.
#define COORDINATE_SCALE 256
#define COORDINATE_BITS 8
#define WATER_ELEVATION 15
#define ROCK_ELEVATION 45
#define SNOW_ELEVATION 55
//Too big makes off-screen draws take place.
#define MAX_PANEL_SIZE 16
class Panel
{
Panel *next;
I32 n, //num polygon sides
num; //panel number
CD3I32 *pts;
I64 color,cnt;
};
class Fish
{
Fish *next,*last;
I64 x,y,z;
} fish_root;
$SP,"<1>",1$
I64 critical_section_flag;
U0 CriticalSectionStart()
{
while (LBts(&critical_section_flag,0))
Yield;
}
U0 CriticalSectionEnd()
{
LBtr(&critical_section_flag,0);
}
//These are $BK,1$NOT$BK,0$ deallocated after the program ends,
//but I did them this way for your benefit
//so 2D array indexing is not done by hand.
//You can type "EagleDive;" at the command line
//to rerun without new allocations.
//Normally, just spawn a popup task,
//run it and kill it using an icon.
#ifstatic
#exe {OptOn(OPTf_GLBLS_ON_DATA_HEAP);};
#endif
I16 elevations[MAP_HEIGHT][MAP_WIDTH];
I32 normals[MAP_HEIGHT][MAP_WIDTH*2];
Panel *panels[MAP_HEIGHT][MAP_WIDTH*2];
#ifstatic
#exe {OptOff(OPTf_GLBLS_ON_DATA_HEAP);};
#endif
I64 num_panels;
Panel *panel_root;
U8 *panels_processed_bitmap;
F64 game_t0,v_grid_size,span_factor,è,é1,é2,speed;
I64 x,y,z,game_score;
Bool game_over;
class MPCtrl {
I64 mp_cnt;
I64 doc_update;
F64 update_done_t[MP_MAX_PROCESSORS];
I64 done_flags;
Bool app_done;
} mp;
U0 FSTransform(CDC *dc,I64 *x,I64 *y,I64 *z)
{
I64 zz;
//I accidentally made the Z coordinate sign backward
//from the fill-poly depth buf scheme, so it is negated at the end.
//Negative Z coordinates are the ones we want plotted.
GrRot(dc->r,x,y,z);
//We don't want divide by zero or make too monstrous foreground objects.
//The foreground object boundary is kinda crappy looking when
//you point toward the ground.
*z=-*z;
zz=*z+50;
if (zz>0) {
//The divide causes "foreshortening" which makes the distance go to a vanishing point.
*x = *x * DISPLAY_SCALE/ zz;
*y = *y * DISPLAY_SCALE/ zz;
}
*x+=dc->x;
*y =dc->y-*y;
}
U0 CalcNormals()
{
/*The idea is that there are two triangles
forming every grid square and we find the normal
vect with a curl.
i j k
0 1 dz2
1 0 dz1
Normal:
dz1*i + dz2*j - k
i j k
-1 0 -dz3
0 -1 -dz4
Normal:
-dz3*i - dz4*j + k
Basically, we want to combine grid
locations with the same normals. These
are not unit vects for one thing.
What I came-up with is dz1/dz2 and dz3/dz4.
It works pretty well. It combines
more than it should, but that's good
because it would result in too many
panels.
*/
I64 i,j,k,dz1,dz2;
for (j=0;j<MAP_HEIGHT-1;j++) {
k=0;
for (i=0;i<MAP_WIDTH-1;i++) {
dz1=elevations[j][i+1]-elevations[j][i];
dz2=elevations[j+1][i]-elevations[j][i];
if (dz2)
normals[j][k++]=dz1<<16/dz2;
else {
if (!dz1)
normals[j][k++]=0;
else if (dz1>0)
normals[j][k++]=MAX_I32;
else
normals[j][k++]=MIN_I32;
}
dz1=elevations[j+1][i+1]-elevations[j][i+1];
dz2=elevations[j+1][i+1]-elevations[j+1][i];
if (dz2)
normals[j][k++]=dz1<<16/dz2;
else {
if (!dz1)
normals[j][k++]=0;
else if (dz1>0)
normals[j][k++]=MAX_I32;
else
normals[j][k++]=MIN_I32;
}
}
normals[j][k++]=0;
normals[j][k++]=0;
}
k=0;
for (i=0;i<MAP_WIDTH-1;i++) {
normals[j][k++]=0;
normals[j][k++]=0;
}
}
Bool TestSameSlope(I64 x,I64 y,I64 w,I64 h)
{
I64 k1,k2,xx,yy,s;
if (!(0<=x && x+w<MAP_WIDTH && 0<=y && y+h<MAP_HEIGHT))
return FALSE;
//Works well averaging the two slopes of two triangles.
//If it is too picky, we get too many panels.
s=normals[y][x*2]+normals[y][x*2+1];
for (k2=0;k2<h;k2++)
for (k1=0;k1<w;k1++) {
xx=(x+k1)*2;
yy=y+k2;
if (normals[yy][xx]+normals[yy][xx+1]!=s)
return FALSE;
}
return TRUE;
}
U0 MPDoPanels(CTask *task)
{
I64 i,j,k,l,k1,k2,w,h,threshold,lo,hi;
Bool cont;
Panel *tempp,*start_ptr=NULL,*end_ptr=NULL;
CD3I32 *poly;
Fish *tempf;
lo=Gs->num*(MAP_HEIGHT-1)/mp.mp_cnt;
hi=(Gs->num+1)*(MAP_HEIGHT-1)/mp.mp_cnt;
for (threshold=8;threshold>=1;threshold--)
for (j=lo;j<hi;j++) {
k=0;
for (i=0;i<MAP_WIDTH-1;i++) {
if (!panels[j][k]) {
w=1;
h=1;
do {
cont=FALSE;
if (w<MAX_PANEL_SIZE && TestSameSlope(i,j,w+1,h)) {
w++;
cont=TRUE;
}
if (h<MAX_PANEL_SIZE && TestSameSlope(i,j,w,h+1)) {
h++;
cont=TRUE;
}
} while (cont);
if (w>=threshold || h>=threshold) {
tempp=CAlloc(sizeof(Panel),task);
lock {tempp->num=num_panels++;}
l=elevations[j][i];
if (l<=WATER_ELEVATION*MAP_SCALE &&
elevations[j][i+w-1]<=WATER_ELEVATION*MAP_SCALE &&
elevations[j+h-1][i]<=WATER_ELEVATION*MAP_SCALE &&
elevations[j+h-1][i+w-1]<=WATER_ELEVATION*MAP_SCALE) {
tempp->color=BLUE;
if (Rand<0.05) {
tempf=MAlloc(sizeof(Fish),task);
tempf->x=(i+w/2)*MAP_SCALE;
tempf->y=(j+h/2)*MAP_SCALE;
tempf->z=l;
CriticalSectionStart;
QueIns(tempf,fish_root.last);
CriticalSectionEnd;
}
} else {
if (RandI16&1) {
if (l<ROCK_ELEVATION*MAP_SCALE)
tempp->color=LTGREEN;
else if (l<SNOW_ELEVATION*MAP_SCALE) {
if (!(RandU16&3))
tempp->color=LTGRAY;
else
tempp->color=LTGREEN;
} else {
if (!(RandU16&3))
tempp->color=WHITE;
else
tempp->color=LTGRAY;
}
} else {
if (l<ROCK_ELEVATION*MAP_SCALE)
tempp->color=GREEN+LTGREEN<<16+ROPF_DITHER;
else if (l<SNOW_ELEVATION*MAP_SCALE) {
if (!(RandU16&3))
tempp->color=DKGRAY+LTGRAY<<16+ROPF_DITHER;
else
tempp->color=GREEN+LTGREEN<<16+ROPF_DITHER;
} else {
if (!(RandU16&3))
tempp->color=LTGRAY+WHITE<<16+ROPF_DITHER;
else
tempp->color=DKGRAY+LTGRAY<<16+ROPF_DITHER;
}
}
}
tempp->n=4;
poly=tempp->pts=MAlloc(sizeof(CD3I32)*tempp->n,task);
poly[0].x=MAP_SCALE*i;
poly[0].y=MAP_SCALE*j;
poly[0].z=elevations[j][i];
poly[1].x=MAP_SCALE*(i+w);
poly[1].y=MAP_SCALE*j;
poly[1].z=elevations[j][i+w];
poly[2].x=MAP_SCALE*(i+w);
poly[2].y=MAP_SCALE*(j+h);
poly[2].z=elevations[j+h][i+w];
poly[3].x=MAP_SCALE*i;
poly[3].y=MAP_SCALE*(j+h);
poly[3].z=elevations[j+h][i];
tempp->next=start_ptr;
start_ptr=tempp;
if (!end_ptr)
end_ptr=tempp;
for (k2=0;k2<h;k2++)
for (k1=0;k1<w;k1++) {
panels[j+k2][(i+k1)*2]=tempp;
panels[j+k2][(i+k1)*2+1]=tempp;
}
}
}
k+=2;
}
}
if (end_ptr) {
CriticalSectionStart;
if (end_ptr)
end_ptr->next=panel_root;
panel_root=start_ptr;
CriticalSectionEnd;
}
LBts(&mp.done_flags,Gs->num);
}
U0 InitMap()
{
//We make a topographic data structure "elevations[][]"
//and convert it to panels. The conversion to panels leaves
//gaps the way I did it, but it looks good, except for sky leaking through
//There is no wrong way to pick colors if it looks good, unless
//you wanted to do lighting.
//"panels[][]" holds the flat and sloped panels for each spot, while
//"hstep_panels[][]" holds side panels in cases of step-like formations.
//They require a separate array because a single "elevation[][]" spot can
//have a panel on top and a panel on the side like stairs.
I64 i,j,l,k1,k2,x,y,xx,yy;
MemSet(elevations,0,sizeof(elevations));
MemSet(panels,0,sizeof(panels));
for (i=0;i<MAP_WIDTH*MAP_HEIGHT/128;i++) {
x=RandU32%MAP_WIDTH;
y=RandU32%MAP_HEIGHT;
j=1<<(RandU32%6);
l=0;
while (j--) {
if (!l && RandU16<MAX_U16/4)
l=RandU16%(j+1);
if (l) {
for (k1=-j;k1<=j;k1++)
for (k2=-j;k2<=j;k2++) {
xx=x+k2; yy=y+k1;
if (0<=xx<MAP_WIDTH &&
0<=yy<MAP_HEIGHT)
elevations[yy][xx]+=MAP_SCALE/2;
}
l--;
}
}
}
xx=x/(MAP_SCALE*COORDINATE_SCALE);
yy=y/(MAP_SCALE*COORDINATE_SCALE);
z+=elevations[yy][xx]*COORDINATE_SCALE;
for (j=0;j<MAP_HEIGHT;j++)
for (i=0;i<MAP_WIDTH;i++)
if (elevations[j][i]<WATER_ELEVATION*MAP_SCALE)
elevations[j][i]=WATER_ELEVATION*MAP_SCALE;
CalcNormals;
panel_root=NULL;
num_panels=0;
mp.done_flags=0;
for (i=1;i<mp.mp_cnt;i++)
MPSpawn(&MPDoPanels,Fs,"Do Panels",i);
MPDoPanels(Fs);
while (mp.done_flags!=1<<mp.mp_cnt-1)
Yield;
panels_processed_bitmap=MAlloc((num_panels+7)>>3);
}
CDC *main_dc;
U0 DrawIt(CTask *,CDC *dc)
{
main_dc->flags|=DCF_NO_TRANSPARENTS;
GrBlot(dc,0,0,main_dc);
}
/*$SP,"",2$
Cores render strips. The strips are wider toward the horizon by span_factor
and overlap +/- 15%. The cores check the panel map array
and render the panel for each square and mark-it done.
The depth buf is not locked in the graphic routines
so we get some glitches.
*/
U0 MPDrawIt(CTask *task,CDC *dc)
{
//This is identical to the previous routine but is run by core#1
I64 i,j,ww,hh,*s2w,x1,y1,z1, xx,yy,
xh,yh,zh, yh2,xh2, reg x1w, reg y1w, x1h,y1h,
x3,y3,z3,
cx=task->win_pixel_width>>1,
cy=task->win_pixel_height>>1;
F64 h_grid_size,t0=tNP;
Panel reg *tempp;
xx=x/(MAP_SCALE*COORDINATE_SCALE);
yy=y/(MAP_SCALE*COORDINATE_SCALE);
//World to screen coordinates
GrIdentEqu(dc->r);
GrRotZEqu(dc->r,é2);
GrRotXEqu(dc->r,è);
GrRotZEqu(dc->r,é1);
GrSetRotMat(dc,dc->r);
//Screen to world coordinates
//This gives us the vects for stepping through the grid in
//the direction the plane is facing. we step horizontally and vertically
//and use the reciprocal slope principle y=mx+b and y=(-1/m)x+b are perpendicular.
s2w=GrIdent;
GrRotZEqu(s2w,-é1);
GrRotXEqu(s2w,-è);
GrRotZEqu(s2w,-é2);
xh=0;
yh=0;
zh=-256;
GrRot(s2w,&xh,&yh,&zh);
//The layer for core#1 is not cleared automatically
//it is persistent. I have carefully syncronized to the update
//cycle initiated by core#0 to prevent flicker.
dc->flags|=DCF_TRANSFORMATION;
dc->transform=&FSTransform;
dc->x=cx;
dc->y=cy;
//dc->x and the translation part of dc->r are identical in effect,
//but we use both to show-off. We could add offsets together and use one or the other.
x1=-x>>COORDINATE_BITS;
y1=-y>>COORDINATE_BITS;
z1=-z>>COORDINATE_BITS;
GrRot(dc->r,&x1,&y1,&z1);
GrSetTranslation(dc->r,x1,y1,z1);
//This is a refinement.
if (Abs(è*180/ã)>90) {
x3=0;
y3=-cy;
z3=0;
GrRot(s2w,&x3,&y3,&z3);
xx+=x3;
yy+=y3;
}
h_grid_size=4.0*v_grid_size*(Gs->num+span_factor)/span_factor;
if (Gs->num&1) { //alternate left-right,right-left
yh2=-yh;
xh2=-xh;
} else {
yh2=yh;
xh2=xh;
}
ww=h_grid_size;
hh=1.30*v_grid_size; //Cores overlap 15% on each side of strip.
//Calc starting point.
x1h=xx<<8+0.5*yh2*h_grid_size+xh*v_grid_size*(Gs->num+1.15);
y1h=yy<<8-0.5*xh2*h_grid_size+yh*v_grid_size*(Gs->num+1.15);
xh=-xh; //Back to front to help with depth.
yh=-yh;
//Take half steps to cover whole grid.
xh>>=1; yh>>=1;
xh2>>=1; yh2>>=1;
ww<<=1;
hh<<=1;
for (j=0;j<hh;j++) {
x1w=x1h;
y1w=y1h;
for (i=0;i<ww;i++) {
x1=x1w>>8; y1=y1w>>8;
if (0<=x1<MAP_WIDTH && 0<=y1<MAP_HEIGHT) {
if ((tempp=panels[y1][x1*2]) && !LBts(panels_processed_bitmap,tempp->num)) {
if (tempp->cnt>8*(1.1-Gs->idle_factor)) {
dc->color=tempp->color;
tempp->cnt=GrFillPoly3(dc,tempp->n,tempp->pts);
} else
tempp->cnt++;
}
}
x1w-=yh2;
y1w+=xh2;
}
x1h+=xh;
y1h+=yh;
}
Free(s2w);
mp.update_done_t[Gs->num]=tNP-t0;
}
U0 APEagleDiveTask(CTask *master_task)
{
CDC *dc=DCAlias(main_dc,master_task);
if (!IsSysDeterministic)
Preempt(ON);
while (!mp.app_done) {
LBts(&Fs->task_flags,TASKf_IDLE);
while (!LBtr(&mp.doc_update,Gs->num) && !mp.app_done)
Yield;
LBtr(&Fs->task_flags,TASKf_IDLE);
if (!mp.app_done)
MPDrawIt(master_task,dc);
}
//We made an alias of this we don't want freed.
dc->depth_buf=NULL;
DCDel(dc);
LBts(&mp.done_flags,Gs->num);
}
U0 DrawHorizon(CDC *dc)
{
I64 x1,y1,z1,x2,y2,z2,xh,yh,zh,*s2w=GrIdent,
cx=Fs->win_pixel_width>>1,
cy=Fs->win_pixel_height>>1;
CD3I32 p[4];
I32 *old_db=dc->depth_buf;
dc->depth_buf=NULL;
GrIdentEqu(dc->r);
GrRotZEqu(dc->r,é2);
GrRotXEqu(dc->r,è);
GrRotZEqu(dc->r,é1);
GrSetRotMat(dc,dc->r);
dc->flags&=~DCF_TRANSFORMATION;
dc->transform=&FSTransform;
dc->x=cx;
dc->y=cy;
GrRotZEqu(s2w,-é1);
GrRotXEqu(s2w,-è);
GrRotZEqu(s2w,-é2);
xh=0;
yh=0;
zh=-256;
GrRot(s2w,&xh,&yh,&zh);
Free(s2w);
x1=xh+yh*32; y1=yh-xh*32; z1=0;
(*dc->transform)(dc,&x1,&y1,&z1);
x2=xh-yh*32; y2=yh+xh*32; z2=0;
(*dc->transform)(dc,&x2,&y2,&z2);
DCClipLine(dc,&x1,&y1,&x2,&y2);
MemSet(p,0,sizeof(p));
if (x2<x1) {
SwapU64(&x1,&x2);
SwapU64(&y1,&y2);
}
if (!x1 && x2==dc->width-1) {
p[0].x=0;
p[0].y=0;
p[1].x=dc->width-1;
p[1].y=0;
p[2].x=dc->width-1;
p[2].y=y2;
p[3].x=0;
p[3].y=y1;
if (-ã/2<=é1<ã/2 ^^ -ã/2<=Wrap(è-ã/2)<ã/2)
dc->color=LTCYAN;
else
dc->color=LTGREEN;
GrFillPoly3(dc,4,p);
p[0].y=dc->height-1;
p[1].y=dc->height-1;
if (-ã/2<=é1<ã/2 ^^ -ã/2<=Wrap(è-ã/2)<ã/2)
dc->color=LTGREEN;
else
dc->color=LTCYAN;
GrFillPoly3(dc,4,p);
} else {
if (y2<y1) {
SwapU64(&x1,&x2);
SwapU64(&y1,&y2);
}
if (!y1 && y2==dc->height-1) {
p[0].x=0;
p[0].y=0;
p[1].x=0;
p[1].y=dc->height-1;
p[2].x=x2;
p[2].y=dc->height-1;
p[3].x=x1;
p[3].y=0;
if (x1<x2 ^^ -ã/2<=é1<ã/2 ^^ -ã/2<=Wrap(è-ã/2)<ã/2)
dc->color=LTCYAN;
else
dc->color=LTGREEN;
GrFillPoly3(dc,4,p);
p[0].x=dc->width-1;
p[1].x=dc->width-1;
if (x1<x2 ^^ -ã/2<=é1<ã/2 ^^ -ã/2<=Wrap(è-ã/2)<ã/2)
dc->color=LTGREEN;
else
dc->color=LTCYAN;
GrFillPoly3(dc,4,p);
}
}
dc->depth_buf=old_db;
}
U0 BSPEagleDive()
{
CDC *dc=DCAlias(main_dc,Fs);
F64 last_t;
I64 i,xx,yy,height,bkcolor,
cx=Fs->win_pixel_width>>1,
cy=Fs->win_pixel_height>>1;
Fish *tempf;
MemSet(panels_processed_bitmap,0,(num_panels+7)>>3);
MemSet(mp.update_done_t,0,sizeof(F64)*MP_MAX_PROCESSORS);
xx=x/(MAP_SCALE*COORDINATE_SCALE);
yy=y/(MAP_SCALE*COORDINATE_SCALE);
height=z/COORDINATE_SCALE-elevations[yy][xx];
if (height<0) {
if (elevations[yy][xx]>WATER_ELEVATION*MAP_SCALE) {
dc->color=bkcolor=BLACK;
if (!game_over) {
GrRect(dc,0,0,dc->width,dc->height);
music_mute=TRUE;
Beep;
game_over=TRUE;
music_mute=FALSE;
}
} else
bkcolor=BLUE;
} else
bkcolor=LTCYAN;
if (height>=0 && !(-ã/4<=Wrap(è-ã)<ã/4)) {
DrawHorizon(dc);
DCDepthBufRst(dc);
//Signal all cores to start update
mp.doc_update=1<<mp.mp_cnt-1-1;
//Wait for all cores to start
while (mp.doc_update)
Yield;
MPDrawIt(Fs,dc);
xx=x/COORDINATE_SCALE;
yy=y/COORDINATE_SCALE;
tempf=fish_root.next;
while (tempf!=&fish_root) {
if (SqrI64(tempf->x-xx)+SqrI64(tempf->y-yy)<MAP_SCALE*MAP_SCALE*20*20)
CSpritePlot3(dc,tempf->x,tempf->y,tempf->z,$IB,"<1>",1$);
tempf=tempf->next;
}
//Wait for all cores to complete.
LBts(&Fs->task_flags,TASKf_IDLE);
for (i=1;i<mp.mp_cnt;i++)
while (!mp.update_done_t[i])
Yield;
LBtr(&Fs->task_flags,TASKf_IDLE);
last_t=mp.update_done_t[0];
for (i=1;i<mp.mp_cnt;i++)
last_t=Max(last_t,mp.update_done_t[i]);
//Adjust size of updated grid.
v_grid_size *=0.90+0.10*(0.65/Fs->win_max_refresh)/last_t;
v_grid_size=Limit(v_grid_size,20,200);
//Regulate how much grid expands in the distance.
if (mp.mp_cnt>1)
span_factor*=0.90+0.10*mp.update_done_t[mp.mp_cnt-1]/mp.update_done_t[0];
span_factor=Limit(span_factor,.30,3.0);
} else {
dc->color=bkcolor;
GrRect(dc,0,0,dc->width,dc->height);
}
dc->pen_width=2;
if (bkcolor==BLUE)
dc->color=WHITE;
else
dc->color=BLACK;
dc->flags&=~DCF_TRANSFORMATION;
GrLine3(dc,cx+5,cy,0,cx-5,cy,0);
GrLine3(dc,cx,cy+5,0,cx,cy-5,0);
GrPrintF(dc,0,0,"é1:%5.1f è:%5.1f é2:%5.1f Box:%5.1f",
é1*180/ã,è*180/ã,é2*180/ã,v_grid_size);
GrPrintF(dc,0,FONT_HEIGHT,"x:%5.1f y:%5.1f z:%5.1f height:%3d score:%d high:%d",
ToF64(x)/COORDINATE_SCALE,ToF64(y)/COORDINATE_SCALE,ToF64(z)/COORDINATE_SCALE,
height,game_score,best_score);
if (game_over && Blink(,tP)) {
dc->color=RED;
GrPutS(dc,(Fs->win_pixel_width-9*FONT_WIDTH)/2,
(Fs->win_pixel_height-FONT_HEIGHT)/2,"Game Over");
} else if (tP-game_t0<5.0 && Blink(,tP)) {
dc->color=WHITE;
GrPutS(dc,(Fs->win_pixel_width-10*FONT_WIDTH)/2,
(Fs->win_pixel_height-FONT_HEIGHT)/2,"Catch Fish");
}
//We made an alias of this we don't want freed.
dc->depth_buf=NULL;
DCDel(dc);
WinMgrSync;
}
#define ANIMATE_MS 10
U0 AnimateTask(I64)
{
//This just steadily moves the airplane fwd.
I64 *s2w,x1,y1,z1;
F64 t0=tP(Fs->parent_task),mS;
Fish *tempf,*tempf1;
while (TRUE) {
mS=1000*(tP(Fs->parent_task)-t0);
t0=tP(Fs->parent_task);
if (!game_over) {
//Screen to world coordinates
s2w=GrIdent;
GrRotZEqu(s2w,-é1);
GrRotXEqu(s2w,-è);
GrRotZEqu(s2w,-é2);
x1=0;y1=0;z1=-speed*mS*COORDINATE_SCALE;
GrRot(s2w,&x1,&y1,&z1);
x+=x1;
y+=y1;
z+=z1;
Free(s2w);
x1=x/COORDINATE_SCALE; y1=y/COORDINATE_SCALE; z1=z/COORDINATE_SCALE;
if (z1<WATER_ELEVATION*MAP_SCALE) {
speed=0.5;
tempf=fish_root.next;
while (tempf!=&fish_root) {
tempf1=tempf->next;
if (SqrI64(tempf->x-x1)+SqrI64(tempf->y-y1)<MAP_SCALE*MAP_SCALE*5*5) {
game_score++;
if (game_score>best_score)
best_score=game_score;
QueRem(tempf);
Free(tempf);
music_mute=TRUE;
Snd(1000); Sleep(200); Snd(0);
music_mute=FALSE;
}
tempf=tempf1;
}
} else {
if (-ã/4<=è<=ã/4)
speed+=0.0005;
else if (-3*ã/4<=è<=3*ã/4)
speed+=0.0001;
else
speed-=0.0001;
speed=Limit(speed+(0.0005-0.0002*Abs(è)/(ã/4)),0.1,5.0);
}
}
WinMgrSync;
}
}
U0 MPEnd()
{
mp.done_flags=0;
mp.app_done=TRUE;
//Wait for all cores to exit
while (mp.done_flags!=1<<mp.mp_cnt-1-1)
Yield;
}
U0 TaskEndCB()
{
MPEnd;
Exit;
}
U0 SongTask(I64)
{ //Song by Terry A. Davis
#ifstatic
Fs->task_end_cb=ExtFind("SndTaskEndCB");//(Can't take addr of an extern function.)
#else
Fs->task_end_cb=&SndTaskEndCB;
#endif
MusicSettingsRst;
music_stacatto_factor=0.2;
while (TRUE) {
Play("W13eBDEDBDEDFEEDFEED");
Play("BDEDBDEDFEEDFEED");
}
}
U0 Init(I64 _mp_cnt)
{
I64 i;
main_dc=DCNew(DCT_COLOR8,GR_WIDTH,GR_HEIGHT);
critical_section_flag=0;
game_over=FALSE;
game_score=0;
MemSet(&mp,0,sizeof(MPCtrl));
if (_mp_cnt<=mp_cnt)
mp.mp_cnt=_mp_cnt;
else
mp.mp_cnt=mp_cnt;
QueInit(&fish_root);
InitMap;
DCAllocDepthBuf(main_dc);
Fs->win_max_refresh=30.0;
v_grid_size=64.0;
span_factor=1.0;
è =-90.0*ã/180.0;
é1= 0.0*ã/180.0;
é2= 0.0*ã/180.0;
speed = 2.5;
x=MAP_WIDTH>>1 *COORDINATE_SCALE*MAP_SCALE;
y=MAP_HEIGHT>>1*COORDINATE_SCALE*MAP_SCALE;
z=64 *COORDINATE_SCALE*MAP_SCALE;
for (i=1;i<mp.mp_cnt;i++)
MPSpawn(&APEagleDiveTask,Fs,"AP EagleDive",i);
Fs->task_end_cb=&TaskEndCB;
game_t0=tP;
}
U0 CleanUp()
{
Fish *tempf=fish_root.next,*tempf1;
Panel *tempp=panel_root,*tempp1;
MPEnd;
while (tempf!=&fish_root) {
tempf1=tempf->next;
QueRem(tempf);
Free(tempf);
tempf=tempf1;
}
while (tempp) {
tempp1=tempp->next;
Free(tempp->pts);
Free(tempp);
tempp=tempp1;
}
Free(panels_processed_bitmap);
DCDel(main_dc);
}
U0 EagleDive(I64 _mp_cnt=MP_MAX_PROCESSORS)
{
I64 ch,sc;
F64 pp,tt1,tt2;
SettingsPush; //See $LK,"SettingsPush","MN:SettingsPush"$
//We really can't afford to run at 60Hz. This is how often VGA
//memory is updated, not related to actual hardware refresh rates.
WordStat;
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" Restart(,CH_NEW_LINE);"
" Down(,,SC_CURSOR_UP);"
" Up(,,SC_CURSOR_DOWN);"
" Left(,,SC_CURSOR_LEFT);"
" Right(,,SC_CURSOR_RIGHT);"
"}"
);
WinMax;
WinBorder;
"Initializing...\n";
Fs->song_task=Spawn(&SongTask,NULL,"Song",Fs);
Init(_mp_cnt);
Fs->animate_task=Spawn(&AnimateTask,NULL,"Animate",Fs);
DocCursor;
DocClear;
Fs->draw_it=&DrawIt;
try //in case <CTRL-ALT-C> is pressed.
do {
if (ScanKey(&ch,&sc)) {
pp=è; tt1=é1; tt2=é2;
switch (ch) {
case 0:
switch (sc.u8[0]) {
case SC_CURSOR_DOWN:
è +=-CTRLS_SCALE*Cos(tt1);
é2+=-CTRLS_SCALE*Sin(tt1)*Sin(è);
break;
case SC_CURSOR_UP:
è -=-CTRLS_SCALE*Cos(tt1);
é2-=-CTRLS_SCALE*Sin(tt1)*Sin(è);
break;
case SC_CURSOR_RIGHT:
é1+=CTRLS_SCALE;
break;
case SC_CURSOR_LEFT:
é1-=CTRLS_SCALE;
break;
}
break;
case CH_NEW_LINE:
Fs->draw_it=NULL;
CleanUp;
WinMgrSync;
Init(_mp_cnt);
Fs->draw_it=&DrawIt;
break;
}
é1=Wrap(é1);
è =Wrap(è);
é2=Wrap(é2);
} else
BSPEagleDive;
} while (ch!=CH_SHIFT_ESC && ch!=CH_ESC);
catch
CatchAll;
SettingsPop;
CleanUp;
#ifnstatic
AcctRegWriteBranch("SparrowOS/EagleDive","I64 best_score=%d;\n",best_score);
#endif
MenuPop;
}
EagleDive;
.¨¢¢¨¢¨¢¨˜˜¢ˆ¢ˆxx¢h¢hXX¢H¢H88¢(¢(¢¨¨""2¨2¨BBR¨R¨bbr¨r¨‚‚’¨’!r8P"!t2R!v,T!N*p@!L.lD!L4hH!Tx&!Xz !\|!ZDtLâÿÿÿ%ãÿÿÿ#
+659
View File
@@ -0,0 +1,659 @@
//This uses $LK,"fixed-point","FI:::/SparrowOS/Demo/Lectures/FixedPoint.CPP.Z"$.
AcctRegSetDftEntry("SparrowOS/FPS","F64 best_score=9999;\n");
AcctRegExecuteBranch("SparrowOS/FPS");
//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>",1$
#define MONSTER_SCALE 2.0
$SP,"<2>",2$
$SP,"<3>",3$
$SP,"<4>",4$
#define PLANT_SCALE 2.0
$SP,"<5>",5$
#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 NUM_MONSTERS 16
I64 monsters_left;
class Monster
{
I64 x,y;
Bool dead,pad[7];
} monsters[NUM_MONSTERS];
U0 FPSTransform(CDC *dc,I64 *x,I64 *y,I64 *z)
{
I64 zz;
GrRot(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,
x1w,y1w,x1h,y1h,xh,yh,zh,
cx=task->win_pixel_width/2,
cy=task->win_pixel_height/2,
_man_xx=man_xx,_man_yy=man_yy;
U8 *inter;
F64 tt,_man_é=man_é;
CD3I32 poly[4];
task->text_attr=BLACK<<4;
DCAllocDepthBuf(dc);
MemSet(panels_processed_bitmap,0,(map_width*map_height+7)>>3);
//World to screen
GrRotZEqu(dc->r,_man_é+ã/2);
GrRotXEqu(dc->r,ã/2);
GrSetRotMat(dc,dc->r);
xh=-_man_xx/SCREEN_SCALE; yh=-_man_yy/SCREEN_SCALE; zh=0;
GrRot(dc->r,&xh,&yh,&zh);
GrSetTranslation(dc->r,xh,yh,zh);
//Screen to world
s2w=GrRotX(-ã/2,task);
GrRotZEqu(s2w,-_man_é-ã/2);
xh=0; yh=0; zh=SCREEN_SCALE;
GrRot(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=&FPSTransform;
dc->x=cx;
dc->y=cy;
r1=GrRotX(-ã/2,task);
GrRotZEqu(r1,tP(task));
GrScaleMatEqu(r1,MONSTER_SCALE);
r2=GrIdent(task);
GrScaleMatEqu(r2,MONSTER_SCALE);
r3=GrRotX(-ã/2,task);
GrScaleMatEqu(r3,PLANT_SCALE);
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 ((dc->color=map[yy*map_width+xx]) &&
LOS(xx*SCREEN_SCALE+SCREEN_SCALE/2,yy*SCREEN_SCALE+SCREEN_SCALE/2,
_man_xx,_man_yy)) {
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 (dc->color==GREEN) {
x1=x+SCREEN_SCALE/2;
y1=y+SCREEN_SCALE/2;
z1=0;
GrTransform(dc,&x1,&y1,&z1);
if (z1>0)
CSpritePlotRotMat3b(dc,x+SCREEN_SCALE/2,y+SCREEN_SCALE/2,0,$IB,"<5>",5$,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=DKGRAY;
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=DKGRAY;
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;i<NUM_MONSTERS;i++) {
x=monsters[i].x;
y=monsters[i].y;
if (LOS(x,y,_man_xx,_man_yy)) {
x-=_man_xx;
y-=_man_yy;
xx=x;
yy=y;
zz=0;
GrTransform(dc,&xx,&yy,&zz);
if (zz>0) {
if (monsters[i].dead)
CSpritePlotRotMat3b(dc,x,y,0,$IB,"<2>",2$,r2);
else {
tt=Tri(tP(task),1.0);
inter=CSpriteInterpolate($IB,"<3>",3$,$IB,"<4>",4$,tt);
CSpritePlotRotMat3b(dc,x,y,0,inter,r1);
Free(inter);
}
}
}
}
Free(r1);
Free(r2);
Free(r3);
//Draw Map heads-up display, scaled 2 pixels
Free(dc->r);
GrSetRotMat(dc,GrIdent(task));
dc->x=task->win_pixel_width -2*map_width;
dc->y=task->win_pixel_height-2*map_height;
dc->z=0;
dc->transform=&GrTransform;
dc->pen_width=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;i<NUM_MONSTERS;i++)
if (!monsters[i].dead)
GrPlot3(dc,2*(monsters[i].x/SCREEN_SCALE),2*(map_height-1-monsters[i].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(,tP(task)))
GrPutS(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=tP(task);
}
GrPrintF(dc,0,0,"Enemy:%d Time:%3.2f Best:%3.2f",monsters_left,tt-t0,best_score);
Free(s2w);
}
U0 Fire()
{
I64 i,x,y;
F64 d,dx,dy,xx=Cos(man_é),yy=Sin(man_é);
Noise(100,300,1000);
for (i=0;i<NUM_MONSTERS;i++) {
x=monsters[i].x;
y=monsters[i].y;
if (!monsters[i].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) {
monsters[i].dead=TRUE;
if (!--monsters_left) {
tf=tP;
if (tf-t0<best_score)
best_score=tf-t0;
}
}
}
}
}
}
U0 Init()
{
I64 i,x,y;
I64 min_map_x,max_map_x,min_map_y,max_map_y;
CDC *dc;
CSpriteExtents($IB,"<1>",1$,&min_map_x,&max_map_x,&min_map_y,&max_map_y);
map_width =(max_map_x-min_map_x+1)/MAP_SCALE+2;
map_height=(max_map_y-min_map_y+1)/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);
dc=DCNew(DCT_COLOR8,map_width*MAP_SCALE,map_height*MAP_SCALE);
CSpritePlot3(dc,-min_map_x+MAP_SCALE,-min_map_y+MAP_SCALE,0,$IB,"<1>",1$);
for (y=1;y<map_height-1;y++)
for (x=1;x<map_width-1;x++)
map[(map_height-1-y)*map_width+x]=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;i<NUM_MONSTERS;i++) {
monsters[i].dead=FALSE;
do {
monsters[i].x=RandU64%((map_width-2)*SCREEN_SCALE)+SCREEN_SCALE;
monsters[i].y=RandU64%((map_height-2)*SCREEN_SCALE)+SCREEN_SCALE;
} while (!map[(monsters[i].y/SCREEN_SCALE)*map_width+monsters[i].x/SCREEN_SCALE]);
}
monsters_left=NUM_MONSTERS;
tf=0;
t0=tP;
}
U0 AnimateTask(I64)
{
I64 i,x,y,dd;
while (TRUE) {
dd=0.25*SCREEN_SCALE*Sin(tP(Fs->parent_task)/2);
for (i=0;i<NUM_MONSTERS;i++)
if (!monsters[i].dead) {
x=monsters[i].x;
y=monsters[i].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;
monsters[i].x=x;
monsters[i].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=&SndTaskEndCB;
MusicSettingsRst;
while (TRUE) {
Play("W12q.A#1eG2AeA#qAq.A#1eG2eAeA#qA");
Play("q.A#1eG2A#A1qG2q.A#1eG2A#A1qG");
Play("3eA#A2qG3eA#A2qG3eA#A2G3AA#A2qG");
}
}
U0 MoveMan(F64 é)
{
I64 x,y,color,step=SCREEN_SCALE/2;
do {
x=man_xx+step*Cos(é);
y=man_yy-step*Sin(é);
x=Limit(x,0,map_width*SCREEN_SCALE);
y=Limit(y,0,map_height*SCREEN_SCALE);
color=map[y/SCREEN_SCALE*map_width+x/SCREEN_SCALE];
if (color==RED || color==GREEN) {
man_xx=x;
man_yy=y;
break;
} else
step>>=1;
} while (step);
}
#define MICRO_STEPS 4
U0 RotateMan(F64 d)
{
I64 i;
for (i=0;i<MICRO_STEPS;i++) {
man_é+=d/MICRO_STEPS;
Sleep(15);
}
}
U0 FPS()
{
I64 sc;
PopUpOk(
"I refuse 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");
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" Restart(,CH_NEW_LINE);"
" Fwd(,,SC_CURSOR_UP);"
" Backward(,,SC_CURSOR_DOWN);"
" Left(,,SC_CURSOR_LEFT);"
" Right(,,SC_CURSOR_RIGHT);"
" Fire(,CH_SPACE);"
"}"
);
SettingsPush; //See $LK,"SettingsPush","MN:SettingsPush"$
Preempt(OFF);
WinMax;
WordStat;
Init;
Fs->animate_task=Spawn(&AnimateTask,NULL,"Animate",Fs);
Fs->song_task=Spawn(&SongTask,NULL,"Song",Fs);
DocCursor;
DocClear;
Fs->draw_it=&DrawIt;
try {
while (TRUE) {
switch (GetKey(&sc)) {
case CH_SPACE:
Fire;
break;
case CH_NEW_LINE:
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));
break;
case SC_CURSOR_LEFT:
Spawn(&RotateMan,(-ã/32)(I64));
break;
case SC_CURSOR_UP:
MoveMan(man_é);
break;
case SC_CURSOR_DOWN:
MoveMan(man_é+ã);
break;
}
break;
}
}
fs_done:
} catch
CatchAll;
SettingsPop;
CleanUp;
MenuPop;
AcctRegWriteBranch("SparrowOS/FPS","F64 best_score=%5.4f;\n",best_score);
}
FPS;
Æ    <<<< ,,,$8888$$$$444 4 ( ( ((0,0T0T0TLTL,L,L,404P4P4PHPH0H0H0808L8L8LDLD4D4D4<4<H<H<H@H@8@T@l@l4lLlLˆLˆLˆ$ˆ$€$€$€0€0l0p4„4„(„H€HpHpDp8p8€8€8€D€DtHtDt<t<|<x@|@|DxD„ „„tppp\\\\llhlll````ddd h hXTPPPLLL(@@8HHHH8888DD D D <Z,u @ ZDD<DDD\D\DdT0T8THL0LLd d hh88x8|8|4x4Z<HñÿÿÿñÿÿÿØÿÿÿìÿÿÿØÿÿÿûÿÿÿ¿ÿÿÿ¿ÿÿÿØÿÿÿØÿÿÿìÿÿÿƒÿÿÿçÿÿÿƒÿÿÿûÿÿÿƒÿÿÿƒÿÿÿ
tÿÿÿöÿÿÿtÿÿÿ
¿ÿÿÿöÿÿÿ¿ÿÿÿƒÿÿÿ
tÿÿÿ
ƒÿÿÿ
ûÿÿÿƒÿÿÿ
çÿÿÿƒÿÿÿ
¿ÿÿÿ
¿ÿÿÿ
ûÿÿÿ¿ÿÿÿ
öÿÿÿ¿ÿÿÿ
ìÿÿÿØÿÿÿ
ñÿÿÿØÿÿÿ
Øÿÿÿ
Øÿÿÿ
ûÿÿÿ
ûÿÿÿ
ñÿÿÿûÿÿÿ
ìÿÿÿûÿÿÿ
ƒÿÿÿ
ìÿÿÿƒÿÿÿ
çÿÿÿ«ÿÿÿ-ìÿÿÿ«ÿÿÿ-«ÿÿÿ-«ÿÿÿ-°ÿÿÿ-°ÿÿÿ-ìÿÿÿ°ÿÿÿ-çÿÿÿ°ÿÿÿ-øÿÿÿxÿÿÿ ýÿÿÿ|ÿÿÿ xÿÿÿ xÿÿÿ |ÿÿÿ öÿÿÿtÿÿÿ
ÿÿÿÿxÿÿÿ ìÿÿÿûÿÿÿñÿÿÿûÿÿÿñÿÿÿûÿÿÿûÿÿÿìÿÿÿ
 ␍    !!&''"#%$$#    ␍ ␍!


 $%*$*+'&('()&(( $++
0/.112-,7 765343! 3 45833!839;:7;766;;1␍Z<HñÿÿÿöÿÿÿñÿÿÿØÿÿÿìÿÿÿØÿÿÿûÿÿÿ¿ÿÿÿ¿ÿÿÿØÿÿÿØÿÿÿìÿÿÿöÿÿÿƒÿÿÿçÿÿÿƒÿÿÿûÿÿÿƒÿÿÿƒÿÿÿ
tÿÿÿöÿÿÿtÿÿÿ
¿ÿÿÿöÿÿÿ¿ÿÿÿƒÿÿÿ
tÿÿÿ
ƒÿÿÿ
ûÿÿÿƒÿÿÿ
çÿÿÿƒÿÿÿ
¿ÿÿÿ
¿ÿÿÿ
ûÿÿÿ¿ÿÿÿ
öÿÿÿ¿ÿÿÿ
ìÿÿÿØÿÿÿ
ñÿÿÿØÿÿÿ
Øÿÿÿ
Øÿÿÿ
ûÿÿÿûÿÿÿñÿÿÿûÿÿÿìÿÿÿûÿÿÿƒÿÿÿ
ìÿÿÿƒÿÿÿ
çÿÿÿ«ÿÿÿ-ìÿÿÿ«ÿÿÿ-«ÿÿÿÓÿÿÿ«ÿÿÿÓÿÿÿ°ÿÿÿÓÿÿÿ°ÿÿÿÓÿÿÿìÿÿÿ°ÿÿÿ-çÿÿÿ°ÿÿÿ-øÿÿÿxÿÿÿ ýÿÿÿ|ÿÿÿ xÿÿÿ xÿÿÿ |ÿÿÿ öÿÿÿtÿÿÿ
ÿÿÿÿxÿÿÿ ìÿÿÿûÿÿÿñÿÿÿûÿÿÿñÿÿÿûÿÿÿ-ûÿÿÿ-ìÿÿÿ--
 ␍    !!&''"#%$$#    ␍ ␍!


 $%*$*+'&('()&(( $++
0/.112-,7 765343! 3 45833!839;:7;766;;1␍Z<HñÿÿÿñÿÿÿØÿÿÿìÿÿÿØÿÿÿûÿÿÿ¿ÿÿÿ¿ÿÿÿØÿÿÿØÿÿÿìÿÿÿöÿÿÿƒÿÿÿçÿÿÿƒÿÿÿûÿÿÿƒÿÿÿƒÿÿÿ
tÿÿÿöÿÿÿtÿÿÿ
¿ÿÿÿöÿÿÿ¿ÿÿÿƒÿÿÿ
tÿÿÿ
ƒÿÿÿ
ûÿÿÿƒÿÿÿ
çÿÿÿƒÿÿÿ
¿ÿÿÿ
¿ÿÿÿ
ûÿÿÿ¿ÿÿÿ
öÿÿÿ¿ÿÿÿ
ìÿÿÿØÿÿÿ
ñÿÿÿØÿÿÿ
Øÿÿÿ
Øÿÿÿ
ûÿÿÿûÿÿÿñÿÿÿûÿÿÿìÿÿÿûÿÿÿƒÿÿÿ
ìÿÿÿƒÿÿÿ
çÿÿÿ«ÿÿÿÓÿÿÿìÿÿÿ«ÿÿÿÓÿÿÿ«ÿÿÿ-«ÿÿÿ-°ÿÿÿ-°ÿÿÿ-ìÿÿÿ°ÿÿÿÓÿÿÿçÿÿÿ°ÿÿÿÓÿÿÿøÿÿÿxÿÿÿ ýÿÿÿ|ÿÿÿ xÿÿÿ xÿÿÿ |ÿÿÿ öÿÿÿtÿÿÿ
ÿÿÿÿxÿÿÿ ìÿÿÿûÿÿÿ#ñÿÿÿûÿÿÿ#ñÿÿÿ#ûÿÿÿûÿÿÿìÿÿÿ#öÿÿÿ
 ␍    !!&''"#%$$#    ␍ ␍!


 $%*$*+'&('()&(( $++
0/.112-,7 765343! 3 45833!839;:7;766;;1␍,ÎÿÿÿÎÿÿÿûÿÿÿçÿÿÿûÿÿÿçÿÿÿµÿÿÿ�ÿÿÿƒÿÿÿ�ÿÿÿâÿÿÿµÿÿÿâÿÿÿûÿÿÿÎÿÿÿûÿÿÿÎÿÿÿûÿÿÿûÿÿÿçÿÿÿûÿÿÿûÿÿÿçÿÿÿûÿÿÿµÿÿÿûÿÿÿ�ÿÿÿûÿÿÿ�ÿÿÿâÿÿÿûÿÿÿµÿÿÿâÿÿÿ�ÿÿÿµÿÿÿâÿÿÿµÿÿÿâÿÿÿ�ÿÿÿ�ÿÿÿûÿÿÿµÿÿÿûÿÿÿâÿÿÿµÿÿÿûÿÿÿâÿÿÿ�ÿÿÿûÿÿÿ 


  ␍␍ ␍ 
 

 ␍
␍÷ÿÿÿ÷ÿÿÿñÿÿÿ÷ÿÿÿ ôÿÿÿ ÷ÿÿÿ øÿÿÿçÿÿÿìÿÿÿçÿÿÿìÿÿÿçÿÿÿøÿÿÿøÿÿÿçÿÿÿðÿÿÿçÿÿÿðÿÿÿçÿÿÿøÿÿÿçÿÿÿçÿÿÿ   ␍ ␍ 
   


   ␍ ␍␍
+163
View File
@@ -0,0 +1,163 @@
#define NUM_ROAD 512
#define ROAD_WIDTH_BY_2 200
#define CAR_WIDTH_BY_2 100
I64 road_x[NUM_ROAD],road_trend;
F64 speed,distance;
I64 road_ptr=0,car_x;
F64 t_last;
Bool crash;
U0 DrawIt(CTask *task,CDC *dc)
{
I64 h=task->win_pixel_width,v=task->win_pixel_height;
I64 i,x,y,xx;
Bool old_preempt=Preempt(OFF);
xx=h>>1-car_x+road_x[road_ptr&(NUM_ROAD-1)];
task->text_attr=BLACK+BLACK<<4;
dc->color=LTGRAY;
for (i=0;i<NUM_ROAD;i++) {
x=h>>1-car_x+road_x[(i+road_ptr)&(NUM_ROAD-1)];
y=v-0.5*i;
if (y<v/2) break;
GrPlot(dc,x+ROAD_WIDTH_BY_2-0.4*i,y);
GrPlot(dc,x-ROAD_WIDTH_BY_2+0.4*i,y);
}
dc->color=WHITE;
x=h>>1-CAR_WIDTH_BY_2;
if (x<xx-ROAD_WIDTH_BY_2)
crash=TRUE;
GrLine(dc,x-10,v,x-40,v-100);
GrLine(dc,x+10,v,x+40,v-100);
x=h>>1+CAR_WIDTH_BY_2;
if (x>xx+ROAD_WIDTH_BY_2)
crash=TRUE;
GrLine(dc,x-10,v,x-40,v-100);
GrLine(dc,x+10,v,x+40,v-100);
dc->color=YELLOW;
if (crash)
GrPutS(dc,h>>1-FONT_WIDTH*4,(v-FONT_HEIGHT)>>1,"Game Over");
Preempt(old_preempt);
}
U0 UpdateRoad()
{
F64 t0=tP;
distance+=speed*(t0-t_last);
t_last=t0;
while (distance>1.0) {
road_trend=LimitI64(road_trend+SignI64(RandU16%3-1),-5,5);
road_x[road_ptr&(NUM_ROAD-1)]=
road_x[(road_ptr-1)&(NUM_ROAD-1)]+=road_trend/3;
road_ptr++;
distance-=1.0;
}
}
U0 Init()
{
I64 i,x=0;
speed=0;
distance=0;
road_trend=0;
road_ptr=0;
car_x=0;
for (i=0;i<NUM_ROAD;i++) {
road_x[i]=x;
road_trend=LimitI64(road_trend+SignI64(RandU16%3-1),-5,5);
x+=road_trend/3;
}
t_last=tP;
crash=FALSE;
}
U0 Halogen()
{
I64 p1,p2,ch=0,sc=0;
SettingsPush; //See $LK,"SettingsPush","MN:SettingsPush"$
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" Restart(,CH_NEW_LINE);"
" Accelerate(,,SC_CURSOR_UP);"
" Deccellerate(,,SC_CURSOR_DOWN);"
" Left(,,SC_CURSOR_LEFT);"
" Right(,,SC_CURSOR_RIGHT);"
"}"
);
Preempt(OFF);
WordStat;
WinMax;
Init;
DocCursor;
DocClear;
Fs->draw_it=&DrawIt;
try {
while (TRUE) {
switch (ScanMsg(&p1,&p2,1<<MSG_KEY_DOWN|1<<MSG_KEY_UP)) {
case MSG_KEY_DOWN:
ch=p1;sc=p2;
switch (ch) {
case CH_NEW_LINE:
Init;
break;
case CH_ESC:
case CH_SHIFT_ESC:
goto ha_done;
}
break;
case MSG_KEY_UP:
ch=p1;sc=p2;
if (!ch)
switch (sc.u8[0]) {
case SC_CURSOR_RIGHT:
case SC_CURSOR_LEFT:
case SC_CURSOR_UP:
case SC_CURSOR_DOWN:
sc=0;
break;
}
break;
}
switch (sc.u8[0]) {
case SC_CURSOR_RIGHT:
car_x++;
break;
case SC_CURSOR_LEFT:
car_x--;
break;
case SC_CURSOR_UP:
if (++speed>200) speed=200;
break;
case SC_CURSOR_DOWN:
if (--speed<0) speed=0;
break;
}
if (crash)
Snd(0);
else {
if (speed)
Snd(speed+10);
else
Snd(0);
UpdateRoad;
}
Sleep(10);
}
ha_done:
GetMsg(,,1<<MSG_KEY_UP);
} catch
CatchAll;
MenuPop;
SettingsPop;
}
Halogen;
+189
View File
@@ -0,0 +1,189 @@
class MyMass:CMass
{
F64 radius;
};
class MySpring:CSpring
{
};
CMathODE *ode=NULL;
U0 DrawIt(CTask *task,CDC *dc)
{
Bool old_suspend;
MyMass *tempm;
MySpring *temps;
old_suspend=Suspend(task);
dc->color=RED;
temps=ode->next_spring;
while (temps!=&ode->next_spring) {
GrLine(dc,temps->end1->x,temps->end1->y,
temps->end2->x,temps->end2->y);
temps=temps->next;
}
dc->color=BLACK;
tempm=ode->next_mass;
while (tempm!=&ode->next_mass) {
GrCircle(dc,tempm->x,tempm->y,tempm->radius);
tempm=tempm->next;
}
Suspend(task,old_suspend);
}
U0 MyDerivative(CMathODE *ode,F64,COrder2D3 *,COrder2D3 *)
{
//The forces due to springs and drag are
//automatically handled by the
//ode code. We can add new forces
//here.
F64 d,dd;
CD3 p;
MyMass *tempm1,*tempm2;
tempm1=ode->next_mass;
while (tempm1!=&ode->next_mass) {
tempm2=tempm1->next;
while (tempm2!=&ode->next_mass) {
D3Sub(&tempm2->state->x,&tempm1->state->x,&p);
dd=D3SqrNorm(&p);
if (dd<=Sqr(tempm1->radius+tempm2->radius)) {
d=Sqrt(dd)+0.0001;
dd=10.0*Sqr(Sqr(Sqr(tempm1->radius+tempm2->radius)-dd));
D3MulEqu(&p,dd/d);
D3AddEqu(&tempm2->DstateDt->DxDt,&p);
D3SubEqu(&tempm1->DstateDt->DxDt,&p);
}
tempm2=tempm2->next;
}
tempm1=tempm1->next;
}
}
U0 PlaceMass(I64 x, I64 y)
{
MyMass *tempm=CAlloc(sizeof(MyMass));
tempm->mass=1.0;
tempm->drag_profile_factor=100.0;
tempm->x=x;
tempm->y=y;
tempm->radius=10*(Rand+0.25);
QueIns(tempm,ode->last_mass);
}
U0 PlaceSpring(MyMass *tempm1,MyMass *tempm2)
{
MySpring *temps=CAlloc(sizeof(MySpring));
temps->end1=tempm1;
temps->end2=tempm2;
temps->constant=10000;
temps->rest_len=100;
QueIns(temps,ode->last_spring);
}
U0 Init()
{
ode=ODENew(0,1e-4,ODEF_HAS_MASSES);
ode->derivative=&MyDerivative;
ode->drag_v2=0.002;
ode->drag_v3=0.00001;
ode->acceleration_limit=5e3;
QueIns(ode,Fs->last_ode);
}
U0 CleanUp()
{
QueRem(ode);
QueDel(&ode->next_mass,TRUE);
QueDel(&ode->next_spring,TRUE);
ODEDel(ode);
}
U0 MassSpringDemo()
{
I64 msg_code,p1,p2;
MyMass *tempm1=NULL,*tempm2=NULL;
PopUpOk("Left-Click to place mas\n"
"Right-Click and drag to\n"
"connect with spring.\n\n"
"Springs are 100 pixels long.\n");
SettingsPush; //See $LK,"SettingsPush","MN:SettingsPush"$
WinMax;
//This Preempt() eliminates a lot of hassles.
//The concern is about changing
//que links while the winmgr task
//is updating the ode or screen.
//The Window mgr suspends this
//task while updating the ode. It
//will not be interrupted and with this
//preempt, we will not be interrupted.
//There is little downside to Preempt()
//since we will yield during GetMsg().
Preempt(OFF);
Fs->win_inhibit|=WIF_DBL_CLICK;
WordStat;
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" Restart(,CH_NEW_LINE);"
"}"
);
Init;
DocCursor;
DocClear;
Fs->draw_it=&DrawIt;
try {
while (TRUE) {
msg_code=GetMsg(&p1,&p2,1<<MSG_IP_L_DOWN|1<<MSG_IP_R_DOWN|1<<MSG_IP_R_UP|1<<MSG_KEY_DOWN);
switch (msg_code) {
case MSG_IP_L_DOWN:
PlaceMass(p1,p2);
break;
case MSG_IP_R_DOWN:
tempm1=MassFind(ode,p1,p2);
tempm2=NULL;
break;
case MSG_IP_R_UP:
if (tempm1 && (tempm2=MassFind(ode,p1,p2)) && tempm1!=tempm2)
PlaceSpring(tempm1,tempm2);
tempm1=tempm2=NULL;
break;
case MSG_KEY_DOWN:
switch (p1) {
case CH_NEW_LINE:
CleanUp;
Init;
break;
case CH_SHIFT_ESC:
case CH_ESC:
goto ms_done;
}
break;
}
}
ms_done: //Don't goto out of try
GetMsg(,,1<<MSG_KEY_UP);
} catch
CatchAll;
SettingsPop;
CleanUp;
MenuPop;
}
MassSpringDemo;
Binary file not shown.
+770
View File
@@ -0,0 +1,770 @@
#define GAME_SPEED_SCALE 0.1
F64 game_speed,
launch_unit_x1,launch_unit_y1,launch_unit_x2,launch_unit_y2,launch_t,
return_unit_x1,return_unit_y1,return_unit_x2,return_unit_y2,return_t,
set_é_unit_x1,set_é_unit_y1,set_é_unit_x2,set_é_unit_y2,set_é_t;
CTask *main_task;
#define OT_CARRIER 0
#define OT_CRUISER 1
#define OT_FIGHTER 2
#define OT_NUM_TYPES 3
#define OF_SHIP 1
#define OF_ACTIVE 2
#define OF_RETURNING 4
#define OF_SHOOTING 8
class Obj
{
Obj *next,*last;
Obj *next_in_squadron,*last_in_squadron;
Obj *host;
U8 player,type;
U16 flags;
I16 squadron,member_num;
F64 x,y,é,dé,
speed,turn_rate,
life_percent,
target_x,target_y,
ship_guns,ship_guns_range,
air_guns,air_guns_range,
fuel,max_fuel,fuel_burn_rate,
death_time,next_action_time;
I32 torpedos,max_torpedos;
F64 torpedos_range;
} obj_root;
class Torpedo
{
Torpedo *next,*last;
Obj *target;
F64 x,y,é,speed,timeout;
} torpedo_root;
#define SA_PARKED 0
#define SA_LAUNCHING 1
#define SA_FLYING 2
#define SA_SET_é 3
#define SA_RETURNING 4
#define SA_DEAD 5
class Squadron : Obj
{
I64 action,dead_mask,total_mask;
} *squadrons;
U0 SquadronIns(Obj *o,Obj *pred)
{
Obj *succ=pred->next_in_squadron;
o->next_in_squadron=succ;
o->last_in_squadron=pred;
pred->next_in_squadron=o;
succ->last_in_squadron=o;
}
U0 SquadronRem(Obj *o)
{
Obj *pred=o->last_in_squadron,*succ=o->next_in_squadron;
pred->next_in_squadron=succ;
succ->last_in_squadron=pred;
}
#define NUM_PLAYERS 2
I64 num_carriers[NUM_PLAYERS]={2,3},
num_cruisers[NUM_PLAYERS]={2,3},
num_planes_per_squadron[NUM_PLAYERS]={6,5},
num_squadrons_per_carrier[NUM_PLAYERS]={2,3},
num_alive[NUM_PLAYERS],
num_squadrons;
Obj *ObjFind(F64 x,F64 y,
I64 flag_mask=OF_ACTIVE|OF_RETURNING,I64 flag_val=OF_ACTIVE,
I64 type_mask=-1,I64 player_mask=-1,F64 *_d=NULL)
{
Obj *tempo=obj_root.next,*best=NULL;
F64 dd,best_dd=MAX_F64;
while (tempo!=&obj_root) {
if (tempo->flags&flag_mask==flag_val &&
Bt(&type_mask,tempo->type)&&Bt(&player_mask,tempo->player)) {
dd=Sqr(tempo->x-x)+Sqr(tempo->y-y);
if (dd<best_dd) {
best=tempo;
best_dd=dd;
}
}
tempo=tempo->next;
}
if (_d) *_d=Sqrt(best_dd);
return best;
}
U0 ObjDel(Obj *tempo)
{
if (tempo) {
if (tP(main_task)<tempo->death_time)
tempo->flags&=~OF_ACTIVE;
else {
if (tempo->squadron>=0)
SquadronRem(tempo);
QueRem(tempo);
if (tempo->squadron>=0)
LBts(&squadrons[tempo->squadron].dead_mask,tempo->member_num);
num_alive[tempo->player]--;
Free(tempo);
}
}
}
$BG,1$
$SP,"<1>",1$
$SP,"<2>",2$
$SP,"<3>",3$
$SP,"<4>",4$
$SP,"<5>",5$
$SP,"<6>",6$
$BG$
U8 *imgs[NUM_PLAYERS][OT_NUM_TYPES]={{$IB,"<1>",1$,$IB,"<2>",2$,$IB,"<3>",3$},{$IB,"<4>",4$,$IB,"<5>",5$,$IB,"<6>",6$}};
U0 DrawIt(CTask *task,CDC *dc)
{
F64 d,cur_time=tP(task);
Obj *tempo;
Torpedo *tempt;
Bool old_preempt=Preempt(OFF);
task->text_attr=BLUE<<4+WHITE;
tempt=torpedo_root.next;
while (tempt!=&torpedo_root) {
dc->color=WHITE;
GrPlot(dc,tempt->x,tempt->y);
tempt=tempt->next;
}
tempo=obj_root.next;
while (tempo!=&obj_root) {
if (tempo->flags&OF_ACTIVE && tempo->flags&OF_SHIP) {
CSpritePlotRotZ3b(dc,tempo->x,tempo->y,0,imgs[tempo->player][tempo->type],tempo->é+ã/2);
if (Blink(,cur_time)) {
dc->color=BLACK;
GrLine(dc,tempo->x+5,tempo->y,tempo->x+5+10,tempo->y);
if (tempo->life_percent>0) {
if (tempo->life_percent<33)
dc->color=RED;
else if (tempo->life_percent<66)
dc->color=YELLOW;
else
dc->color=GREEN;
GrLine(dc,tempo->x+5,tempo->y,tempo->x+5+10*tempo->life_percent/100,tempo->y);
}
dc->color=BLACK;
GrLine(dc,tempo->x+5,tempo->y+2,tempo->x+5+10,tempo->y+2);
d=tempo->fuel*100/tempo->max_fuel;
if (d>0) {
if (d<33)
dc->color=RED;
else if (d<66)
dc->color=YELLOW;
else
dc->color=GREEN;
GrLine(dc,tempo->x+5,tempo->y+2,tempo->x+5+10*d/100,tempo->y+2);
}
}
}
tempo=tempo->next;
}
tempo=obj_root.next;
while (tempo!=&obj_root) {
if (tempo->flags&OF_ACTIVE && !(tempo->flags&OF_SHIP))
CSpritePlotRotZ3b(dc,tempo->x,tempo->y,0,imgs[tempo->player][tempo->type],tempo->é+ã/2);
if (tempo->flags&OF_SHOOTING) {
dc->color=LTRED;
GrLine(dc,tempo->x,tempo->y,tempo->target_x,tempo->target_y,3);
}
tempo=tempo->next;
}
dc->flags|=DCF_TRANSFORMATION;
if (cur_time<launch_t) {
dc->color=LTGREEN;
GrArrow3(dc,launch_unit_x1,launch_unit_y1,0,launch_unit_x2,launch_unit_y2,0);
}
if (cur_time<return_t) {
dc->color=LTRED;
GrArrow3(dc,return_unit_x1,return_unit_y1,0,return_unit_x2,return_unit_y2,0);
}
if (cur_time<set_é_t) {
dc->color=YELLOW;
GrArrow3(dc,set_é_unit_x1,set_é_unit_y1,0,set_é_unit_x2,set_é_unit_y2,0);
}
dc->color=YELLOW;
GrPrintF(dc,-task->win_scroll_x,-task->win_scroll_y,"Game Speed: %5.2f",game_speed);
dc->color=LTCYAN;
GrPrintF(dc,-task->win_scroll_x,-task->win_scroll_y+ FONT_HEIGHT,"Player 1: %d",num_alive[0]);
dc->color=LTPURPLE;
GrPrintF(dc,-task->win_scroll_x,-task->win_scroll_y+2*FONT_HEIGHT,"Player 2: %d",num_alive[1]);
if ((!num_alive[0]||!num_alive[1]) && Blink(,cur_time)) {
if (!num_alive[1]) {
dc->color=LTGREEN;
GrPutS(dc,task->win_pixel_width>>1 -(FONT_WIDTH*14)/2-task->win_scroll_x,
task->win_pixel_height>>1-FONT_HEIGHT/2-task->win_scroll_y,"Game Completed");
} else {
dc->color=LTRED;
GrPutS(dc,task->win_pixel_width>>1 -(FONT_WIDTH*9)/2-task->win_scroll_x,
task->win_pixel_height>>1-FONT_HEIGHT/2-task->win_scroll_y,"Game Over");
}
}
Preempt(old_preempt);
}
U0 Init()
{
I64 i,fighter,ship,player,squadron,
w=Fs->win_pixel_width,h=Fs->win_pixel_height;
Squadron *temps;
Obj *tempo,*tempo1;
QueInit(&obj_root);
QueInit(&torpedo_root);
Fs->win_scroll_x=0;
Fs->win_scroll_y=0;
game_speed=1.0;
launch_t=return_t=set_é_t=0;
main_task=Fs;
num_squadrons=0;
for (player=0;player<NUM_PLAYERS;player++) {
num_alive[player]=0;
for (ship=0;ship<num_cruisers[player];ship++) {
tempo1=CAlloc(sizeof(Obj));
num_alive[player]++;
tempo1->type=OT_CRUISER; tempo1->player=player;
tempo1->squadron=-1; tempo1->member_num=ship;
tempo1->flags=OF_ACTIVE|OF_SHIP;
tempo1->x=0.8*w*(Rand-0.5)+w>>1; tempo1->y=0.8*h*(Rand-0.5)+h>>1;
tempo1->host=NULL;
tempo1->speed=35.0; tempo1->turn_rate=2.5;
tempo1->é=2*ã*(Rand-0.5); tempo1->dé=0;
tempo1->life_percent=100.0;
tempo1->fuel=tempo1->max_fuel=100000;
tempo1->fuel_burn_rate=100.0;
tempo1->air_guns =5000; tempo1->air_guns_range =30.0;
tempo1->ship_guns=10000; tempo1->ship_guns_range=30.0;
tempo1->torpedos =tempo1->max_torpedos=0;
tempo1->torpedos_range =0.0;
tempo1->next_action_time=0;
QueIns(tempo1,obj_root.last);
}
for (ship=0;ship<num_carriers[player];ship++) {
tempo1=CAlloc(sizeof(Obj));
num_alive[player]++;
tempo1->type=OT_CARRIER; tempo1->player=player;
tempo1->squadron=-1; tempo1->member_num=ship;
tempo1->flags=OF_ACTIVE|OF_SHIP;
tempo1->x=0.8*w*(Rand-0.5)+w>>1; tempo1->y=0.8*h*(Rand-0.5)+h>>1;
tempo1->host=NULL;
tempo1->speed=28.0; tempo1->turn_rate=1.0;
tempo1->é=2*ã*(Rand-0.5); tempo1->dé=0;
tempo1->life_percent=100.0;
tempo1->fuel=tempo1->max_fuel=750000;
tempo1->fuel_burn_rate=500.0;
tempo1->air_guns =5000; tempo1->air_guns_range =20.0;
tempo1->ship_guns=2000; tempo1->ship_guns_range=30.0;
tempo1->torpedos =tempo1->max_torpedos=0;
tempo1->torpedos_range =0.0;
tempo1->next_action_time=0;
QueIns(tempo1,obj_root.last);
for (squadron=0;squadron<num_squadrons_per_carrier[player];squadron++,num_squadrons++) {
for (fighter=0;fighter<num_planes_per_squadron[player];fighter++) {
tempo=CAlloc(sizeof(Obj));
num_alive[player]++;
tempo->type=OT_FIGHTER; tempo->player=player;
tempo->squadron=num_squadrons; tempo->member_num=fighter;
tempo->flags=0;
tempo->host=tempo1;
tempo->speed=300.0; tempo->turn_rate=25.0;
tempo->life_percent=100.0;
tempo->fuel=tempo->max_fuel=1000;
tempo->fuel_burn_rate=1.0;
tempo->air_guns =35000; tempo->air_guns_range =8.0;
tempo->ship_guns=0; tempo->ship_guns_range=0.0;
tempo->torpedos =tempo->max_torpedos=1;
tempo->torpedos_range =20.0;
QueIns(tempo,obj_root.last);
}
}
}
}
squadrons=CAlloc(num_squadrons*sizeof(Squadron));
for (i=0,temps=squadrons;i<num_squadrons;i++,temps++) {
temps->next_in_squadron=temps->last_in_squadron=temps;
temps->squadron=i;
}
tempo=obj_root.next;
while (tempo!=&obj_root) {
if (tempo->squadron>=0) {
temps=&squadrons[tempo->squadron];
temps->host =tempo->host;
temps->player=tempo->player;
temps->total_mask=1<<num_planes_per_squadron[tempo->player]-1;
SquadronIns(tempo,temps->last_in_squadron);
}
tempo=tempo->next;
}
}
U0 CleanUp()
{
QueDel(&obj_root,TRUE);
QueDel(&torpedo_root,TRUE);
Free(squadrons);
}
Obj *ObjLaunch(I64 player,I64 squadron=-1,Obj *host=NULL,F64 x=MAX_F64,F64 y=MAX_F64,F64 é=MAX_F64)
{
Obj *tempo;
F64 cur_time=tP(main_task);
if (!host)
host=ObjFind(x,y,,,1<<OT_CARRIER,1<<player);
if (host && cur_time>host->next_action_time) {
if (é==MAX_F64)
é=Arg(x-host->x,y-host->y);
tempo=obj_root.next;
while (tempo!=&obj_root) {
if (tempo->host==host && (squadron<0||tempo->squadron==squadron) && !(tempo->flags&OF_ACTIVE) &&
(tempo->squadron<0||squadrons[tempo->squadron].action==SA_PARKED||squadrons[tempo->squadron].action==SA_LAUNCHING)) {
if (tempo->fuel<=0.0) //When low on fuel, not zero, gets launched and captured.
LBts(&squadrons[tempo->squadron].dead_mask,tempo->member_num);
else {
tempo->flags=tempo->flags&~OF_RETURNING|OF_ACTIVE;
tempo->é=host->é;
if (x==MAX_F64 || y==MAX_F64 || Sqr(x-host->x)+Sqr(y-host->y)>3*3)
tempo->dé=Wrap(é-tempo->é,-ã);
else
tempo->dé=0;
tempo->x=host->x;
tempo->y=host->y;
host->next_action_time=cur_time+0.25/game_speed;
return tempo;
}
}
tempo=tempo->next;
}
}
return NULL;
}
Squadron *SquadronLaunch(I64 player,F64 x=MAX_F64,F64 y=MAX_F64)
{
Squadron *temps;
Obj *tempo;
if (tempo=ObjLaunch(player,,,x,y)) {
if (player==0) {
launch_unit_x1=tempo->x;
launch_unit_y1=tempo->y;
launch_unit_x2=ipx-main_task->win_pixel_left-main_task->win_scroll_x;
launch_unit_y2=ipy-main_task->win_pixel_top -main_task->win_scroll_y;
launch_t=tP(main_task)+0.5;
}
if (tempo->squadron>=0) {
temps=&squadrons[tempo->squadron];
if (temps->action==SA_PARKED) {
temps->action=SA_LAUNCHING;
temps->é=tempo->é+tempo->dé;
}
return temps;
}
}
return NULL;
}
Obj *ObjReturn(I64 player,F64 x,F64 y)
{
Obj *tempo;
if (tempo=ObjFind(x,y,OF_ACTIVE,OF_ACTIVE,1<<OT_FIGHTER,1<<player))
tempo->flags|=OF_RETURNING;
return tempo;
}
Squadron *SquadronReturn(I64 player,F64 x,F64 y)
{
Squadron *temps;
Obj *tempo;
if (tempo=ObjReturn(player,x,y)) {
if (player==0) {
return_unit_x1=tempo->x;
return_unit_y1=tempo->y;
if (tempo->host) {
return_unit_x2=tempo->host->x;
return_unit_y2=tempo->host->y;
return_t=tP(main_task)+0.5;
}
}
if (tempo->squadron>=0) {
temps=&squadrons[tempo->squadron];
if (temps->action==SA_FLYING)
temps->action=SA_RETURNING;
return temps;
}
}
return NULL;
}
Obj *ObjSeté(I64 player,F64 x=MAX_F64,F64 y=MAX_F64,F64 é=MAX_F64)
{
Obj *tempo;
if ((tempo=ObjFind(x,y,,,,1<<player)) && tempo->flags&OF_ACTIVE && !(tempo->flags&OF_RETURNING)) {
if (é==MAX_F64)
é=Arg(x-tempo->x,y-tempo->y);
tempo->dé+=Wrap(é-(tempo->é+tempo->dé),-ã);
return tempo;
}
return NULL;
}
Squadron *SquadronSeté(I64 player,F64 x=MAX_F64,F64 y=MAX_F64,F64 é=MAX_F64)
{
Squadron *temps;
Obj *tempo;
if (tempo=ObjSeté(player,x,y,é)) {
if (player==0) {
set_é_unit_x1=tempo->x;
set_é_unit_y1=tempo->y;
set_é_unit_x2=ipx-main_task->win_pixel_left-main_task->win_scroll_x;
set_é_unit_y2=ipy-main_task->win_pixel_top -main_task->win_scroll_y;
set_é_t=tP(main_task)+0.5;
}
if (tempo->squadron>=0) {
temps=&squadrons[tempo->squadron];
if (temps->action==SA_FLYING) {
temps->action=SA_SET_é;
temps->é=tempo->é+tempo->dé;
}
return temps;
}
}
return NULL;
}
U0 SquadronActions()
{
I64 i,completed_mask;
Obj *tempo;
Squadron *temps;
for (i=0,temps=squadrons;i<num_squadrons;i++,temps++) {
completed_mask=0;
switch (temps->action) {
case SA_LAUNCHING:
ObjLaunch(temps->player,i,temps->host,,,temps->é);
tempo=temps->next_in_squadron;
while (tempo!=temps) {
LBEqu(&completed_mask,tempo->member_num,tempo->flags&OF_ACTIVE);
tempo=tempo->next_in_squadron;
}
if (completed_mask|temps->dead_mask==temps->total_mask)
temps->action=SA_FLYING;
break;
case SA_FLYING:
tempo=temps->next_in_squadron;
while (tempo!=temps) {
LBEqu(&completed_mask,tempo->member_num,!(tempo->flags&OF_ACTIVE));
tempo=tempo->next_in_squadron;
}
if (completed_mask|temps->dead_mask==temps->total_mask)
temps->action=SA_PARKED;
break;
case SA_SET_é:
tempo=temps->next_in_squadron;
while (tempo!=temps) {
tempo->dé+=Wrap(temps->é-(tempo->é+tempo->dé),-ã);
tempo=tempo->next_in_squadron;
}
temps->action=SA_FLYING;
break;
case SA_RETURNING:
tempo=temps->next_in_squadron;
while (tempo!=temps) {
tempo->flags|=OF_RETURNING;
LBEqu(&completed_mask,tempo->member_num,!(tempo->flags&OF_ACTIVE));
tempo=tempo->next_in_squadron;
}
if (completed_mask|temps->dead_mask==temps->total_mask)
temps->action=SA_PARKED;
break;
}
if (temps->dead_mask==temps->total_mask)
temps->action=SA_DEAD;
}
}
U0 AI(I64 player,F64 period)
{
Obj *tempo;
tempo=obj_root.next;
while (tempo!=&obj_root) {
if (tempo->player==player) {
if (tempo->type==OT_CARRIER && Rand<5*period)
SquadronLaunch(player,tempo->x,tempo->y);
if (tempo->flags&OF_ACTIVE && !(tempo->flags&OF_RETURNING) && Rand<10.0*period)
SquadronSeté(player,tempo->x,tempo->y,tempo->é+pi/2*(Rand-0.5));
}
tempo=tempo->next;
}
}
U0 Combat(F64 period)
{
F64 d;
Obj *tempo,*tempo1;
Torpedo *tempt;
tempo=obj_root.next;
while (tempo!=&obj_root) {
tempo->flags&=~OF_SHOOTING;
if (tempo->flags&OF_ACTIVE &&
(tempo1=ObjFind(tempo->x,tempo->y,OF_ACTIVE,OF_ACTIVE,,1<<(tempo->player^1),&d))) {
tempo->target_x=tempo1->x;
tempo->target_y=tempo1->y;
if (tempo1->flags&OF_SHIP) {
if (tempo->torpedos && d<tempo->torpedos_range && Rand<125*period) {
tempo->torpedos--;
tempt=CAlloc(sizeof(Torpedo));
tempt->x=tempo->x;
tempt->y=tempo->y;
tempt->speed=100;
d/=tempt->speed*(GAME_SPEED_SCALE*game_speed);
tempo1->death_time=tempt->timeout=tP(main_task)+d;
tempt->target=tempo1;
tempt->é=Arg(tempo1->x-tempo->x,tempo1->y-tempo->y);
QueIns(tempt,torpedo_root.last);
Sweep(2000,2000,300);
} else if (tempo->ship_guns>0 && d<tempo->ship_guns_range) {
tempo->flags|=OF_SHOOTING;
if (Rand<125.0*period) {
tempo1->life_percent-=tempo->ship_guns*Rand*period;
if (Rand<10.0*period)
tempo1->fuel*=0.75*Rand+0.25;
}
Noise(100,75,200);
}
} else {
if (tempo->air_guns>0 && d<tempo->air_guns_range) {
tempo->flags|=OF_SHOOTING;
if (Rand<125.0*period) {
tempo1->life_percent-=tempo->air_guns*Rand*period;
if (Rand<10.0*period)
tempo1->fuel*=0.75*Rand+0.25;
}
Noise(25,500,2000);
}
}
}
tempo=tempo->next;
}
tempo=obj_root.next;
while (tempo!=&obj_root) {
tempo1=tempo->next;
if (tempo->type==OT_FIGHTER &&
(tempo->life_percent<=0.0 || tempo->flags&OF_ACTIVE && tempo->fuel<=0.0 ||
tempo->host && !(tempo->flags&OF_ACTIVE) && tempo->host->life_percent<=0.0))
ObjDel(tempo);
tempo=tempo1;
}
tempo=obj_root.next;
while (tempo!=&obj_root) {
tempo1=tempo->next;
if (tempo->life_percent<=0.0)
ObjDel(tempo);
tempo=tempo1;
}
}
#define ANIMATE_FREQ 50
U0 AnimateTask(I64)
{ //Preemption is off after Spawn
Obj *tempo;
Torpedo *tempt,*tempt1;
F64 d,period;
while (TRUE) {
period=GAME_SPEED_SCALE*game_speed/ANIMATE_FREQ;
SquadronActions;
tempo=obj_root.next;
while (tempo!=&obj_root) {
if (tempo->flags&OF_ACTIVE && tempo->fuel>0) {
if (tempo->dé) {
d=tempo->dé;
if (d> tempo->turn_rate*period) d= tempo->turn_rate*period;
if (d<-tempo->turn_rate*period) d=-tempo->turn_rate*period;
tempo->é +=d;
tempo->dé-=d;
}
tempo->x+=tempo->speed*Cos(tempo->é)*period*tempo->life_percent/100.0;
tempo->y+=tempo->speed*Sin(tempo->é)*period*tempo->life_percent/100.0;
tempo->fuel-=tempo->speed*tempo->fuel_burn_rate*period;
}
tempo=tempo->next;
}
tempt=torpedo_root.next;
while (tempt!=&torpedo_root) {
tempt1=tempt->next;
if (tP(main_task)>tempt->timeout) {
tempo=tempt->target;
if (Rand<0.333333) {
tempo->life_percent-=150*Rand*Rand;
if (Rand<0.333333)
tempo->fuel*=0.75*Rand+0.25;
}
QueRem(tempt);
Free(tempt);
} else {
tempt->x+=tempt->speed*Cos(tempt->é)*period;
tempt->y+=tempt->speed*Sin(tempt->é)*period;
}
tempt=tempt1;
}
tempo=obj_root.next;
while (tempo!=&obj_root) {
if (tempo->host && !(tempo->flags&OF_ACTIVE)) {
tempo->x=tempo->host->x;
tempo->y=tempo->host->y;
}
tempo=tempo->next;
}
tempo=obj_root.next;
while (tempo!=&obj_root) {
if (tempo->flags&OF_ACTIVE) {
if (tempo->host) {
d=Sqrt(Sqr(tempo->x-tempo->host->x)+Sqr(tempo->y-tempo->host->y));
if (d<8 && tempo->max_fuel-tempo->fuel>30) {
tempo->life_percent=100.0;
if (tempo->host->fuel>0) {
d=tempo->max_fuel-tempo->fuel;
if (d>tempo->host->fuel) d=tempo->host->fuel;
tempo->host->fuel-=d;
tempo->fuel+=d;
}
tempo->torpedos=tempo->max_torpedos;
tempo->x=tempo->host->x;
tempo->y=tempo->host->y;
tempo->flags&=~OF_ACTIVE;
} else if (d>tempo->fuel-250)
tempo->flags|=OF_RETURNING;
if (tempo->flags&OF_RETURNING)
tempo->dé+=Wrap(Arg(tempo->host->x-tempo->x,tempo->host->y-tempo->y)-(tempo->é+tempo->dé),-ã);
} else if (tempo->type==OT_CARRIER)
tempo->life_percent=Min(100.0,tempo->life_percent+2.5*period);
}
tempo=tempo->next;
}
AI(1,period);
Combat(period);
Sleep(1000/ANIMATE_FREQ);
}
}
U0 Navy()
{
I64 p1,p2;
SettingsPush; //See $LK,"SettingsPush","MN:SettingsPush"$
PopUpOk("$$FG,GREEN$${Left-Mouse}$$FG$$\t\tChange Course\n"
"$$FG,GREEN$${Right-Mouse}$$FG$$\t\tLaunch Squadron\n"
"$$FG,GREEN$${Right-Double-Mouse}$$FG$$\tReturn Squadron\n"
"$$FG,GREEN$${Ctrl-Left Grab}$$FG$$\tScroll Screen\n");
Preempt(OFF),
WinBorder;
WordStat;
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" Restart(,CH_NEW_LINE);"
" Faster(,'+');"
" Slower(,'-');"
"}"
);
WinMax;
Fs->win_inhibit|=WIF_IP_L|WIF_IP_R;
Init;
DocCursor;
DocClear;
Fs->draw_it=&DrawIt;
Fs->animate_task=Spawn(&AnimateTask,NULL,"Animate",Fs);
try {
while (TRUE)
switch(GetMsg(&p1,&p2,1<<MSG_KEY_DOWN|1<<MSG_IP_L_UP|1<<MSG_IP_R_UP|1<<MSG_IP_R_D_UP)) {
case MSG_KEY_DOWN:
switch (p1) {
case CH_NEW_LINE:
CleanUp;
Init;
break;
case CH_ESC:
case CH_SHIFT_ESC:
goto nv_done;
case '+':
game_speed*=1.5;
break;
case '-':
game_speed/=1.5;
break;
}
break;
case MSG_IP_L_UP:
SquadronSeté(0,p1,p2);
break;
case MSG_IP_R_UP:
SquadronLaunch(0,p1,p2);
break;
case MSG_IP_R_D_UP:
SquadronReturn(0,p1,p2);
break;
}
nv_done:
GetMsg(,,1<<MSG_KEY_UP);
} catch
CatchAll;
MenuPop;
SettingsPop;
CleanUp;
}
Navy;
r&úÿÿÿéÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ÿ ÿ ÿ ÿ ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿr&úÿÿÿéÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ␍␍␍ÿ␍␍ÿ␍␍ÿ␍␍ÿ␍␍ÿ␍ÿ␍ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿb %üÿÿÿìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿ ÿÿÿÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿb %üÿÿÿìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ␍␍ÿÿÿ␍␍ÿÿÿÿ␍␍␍␍ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0þÿÿÿÿÿÿÿ 0þÿÿÿÿÿÿÿ␍
+192
View File
@@ -0,0 +1,192 @@
I64 sc_1,sc_2;
#define NUM_DROPS 0x2000
class Drop
{
I32 x,y;
} drops[NUM_DROPS];
CDC *cur_dc;
U0 DrawFrame(CTask *task,CDC *dc)
{
I64 w=task->win_pixel_width,h=task->win_pixel_height,
cx=w>>1,cy=h>>1;
dc->color=LTRED;
GrLine(dc,cx-20,cy-50,cx,cy-150);
GrLine(dc,cx+20,cy-50,cx,cy-150);
dc->color=LTRED;
GrLine(dc,cx-100,cy-100,cx,cy);
GrLine(dc,cx+100,cy-100,cx,cy);
if (Bt(key_down_bitmap,sc_1)) {
dc->color=WHITE;
GrRect(dc,cx-2,cy-2,5,5);
}
dc->color=BLACK;
GrPutS(dc,cx+10,cy,"Press '1'");
dc->color=LTRED;
GrRect(dc,cx-20,cy+60,41,21);
dc->color=LTRED;
GrLine(dc,cx-200,cy,cx,cy+100);
GrLine(dc,cx+200,cy,cx,cy+100);
if (Bt(key_down_bitmap,sc_2)) {
dc->color=WHITE;
GrRect(dc,cx-2,cy+100-2,5,5);
}
dc->color=BLACK;
GrPutS(dc,cx+10,cy+100,"Press '2'");
dc->color=LTRED;
GrLine(dc,cx+400,cy+100,cx-250,cy+200);
}
U0 DrawDrops(CTask *,CDC *dc)
{
I64 i;
dc->color=BLUE;
for (i=0;i<NUM_DROPS;i++)
if (drops[i].y>=0 && GrPeek(dc,drops[i].x,drops[i].y)==WHITE)
GrPlot(dc,drops[i].x,drops[i].y);
}
U0 UpdateCurBase(CTask *task,CDC *dc)
{
Bool old_preempt=Preempt(OFF);
cur_dc->color=ROP_EQU;
dc->flags|=DCF_NO_TRANSPARENTS;
GrBlot(cur_dc,-task->win_pixel_left-task->win_scroll_x,-task->win_pixel_top-task->win_scroll_y,dc);
dc->flags&=~DCF_NO_TRANSPARENTS;
Preempt(old_preempt);
}
U0 DrawIt(CTask *task,CDC *dc)
{
DrawFrame(task,dc);
DrawDrops(task,dc);
UpdateCurBase(task,dc);
}
U0 AnimateTask(I64)
{
I64 i,j,cur_drop=0,c1,c2,x0,y0,x1,y1,w,h;
while (TRUE) {
w=Fs->parent_task->win_pixel_width;
h=Fs->parent_task->win_pixel_height;
for (i=0;i<2;i++) {
j=0;
do {
if (++cur_drop>=NUM_DROPS)
cur_drop=0;
if (drops[cur_drop].y<0)
break;
j++;
} while (j<=NUM_DROPS);
drops[cur_drop].x=RandU32%w;
drops[cur_drop].y=0;
}
for (i=0;i<NUM_DROPS;i++) {
if (drops[i].y>=0) {
if (drops[i].y>=h-1)
drops[i].y=-MAX_I32;
else {
x0=x1=drops[i].x;
y0=y1=drops[i].y;
if (GrPeek(cur_dc,x0,y0+1)==WHITE)
y1++;
else {
c1=GrPeek(cur_dc,x0+1,y0);
c2=GrPeek(cur_dc,x0-1,y0);
if (c1==WHITE && c2!=WHITE)
x1++;
else if (c2==WHITE && c1!=WHITE)
x1--;
else if (c1==WHITE && c2==WHITE) {
c1=GrPeek(cur_dc,x0+1,y0+1);
c2=GrPeek(cur_dc,x0-1,y0+1);
if (c1==WHITE && c2!=WHITE)
x1++;
else if (c2==WHITE && c1!=WHITE)
x1--;
else if (RandI16>=0)
x1++;
else
x1--;
}
if (GrPeek(cur_dc,x1,y1+1)==WHITE)
y1++;
}
if (GrPeek(cur_dc,x0,y0)==BLUE) {
cur_dc->color=WHITE;
GrPlot(cur_dc,x0,y0);
}
cur_dc->color=BLUE;
GrPlot(cur_dc,x1,y1);
drops[i].x=x1;
drops[i].y=y1;
}
}
}
Sleep(10);
}
}
U0 Init()
{
I64 i;
MemSet(drops,0,sizeof(drops));
for (i=0;i<NUM_DROPS;i++)
drops[i].y=-MAX_I32;
}
U0 RainDrops()
{
I64 ch,sc;
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" Restart(,CH_NEW_LINE);"
" OpenUpper(,'1');"
" OpenLower(,'2');"
"}"
);
SettingsPush; //See $LK,"SettingsPush","MN:SettingsPush"$
WinMax;
cur_dc=DCNew(DCT_COLOR8,GR_WIDTH,GR_HEIGHT);
sc_1=A2ScanCode('1');
sc_2=A2ScanCode('2');
Init;
Fs->animate_task=Spawn(&AnimateTask,NULL,"Animate",Fs);
DocCursor;
DocClear;
Fs->draw_it=&DrawIt;
WordStat;
try {
do {
ch=GetKey(&sc);
switch (ch) {
case CH_NEW_LINE:
Init;
break;
}
} while (ch!=CH_ESC && ch!=CH_SHIFT_ESC);
} catch
CatchAll;
SettingsPop;
MenuPop;
DCDel(cur_dc);
}
RainDrops;
+522
View File
@@ -0,0 +1,522 @@
//This uses $LK,"fixed-point","FI:::/SparrowOS/Demo/Lectures/FixedPoint.CPP.Z"$.
AcctRegSetDftEntry("SparrowOS/RawHide","F64 best_score=9999;\n");
AcctRegExecuteBranch("SparrowOS/RawHide");
F64 t0,tf;
#define MAP_WIDTH 1500
#define MAP_HEIGHT 1500
#define MAP_BORDER 3
CDC *dc2;
$BG,10$
#define GE_COW 0
$SP,"<1>",1$
#define GE_BULL 1
$SP,"<2>",2$
#define GE_HORSE 2
$SP,"<3>",3$
#define GE_NUM 3
$BG$
class RHCSprite
{
U8 *img;
I64 min_x,max_x,min_y,max_y;
} rh_sprite[GE_NUM];
#define NUM_ANIMALS 128
class Animal
{
I64 num,x,y,dx,dy;
RHCSprite *ge;
U32 buddy;
U8 type;
Bool dead,pad[2];
} *a;
// ************************************
#define COURSE_LEN (MAP_HEIGHT*2)
I32 *rx,*ry,*rw;
I64 river_lo,river_hi;
U0 RiverNew()
{
rx=MAlloc(COURSE_LEN*sizeof(I32));
ry=MAlloc(COURSE_LEN*sizeof(I32));
rw=MAlloc(COURSE_LEN*sizeof(I32));
river_lo=river_hi=COURSE_LEN/2;
}
U0 RiverMake()
{
I64 i,x,y,dx,dy,w,old_x,old_y;
//Plan lower course of river
old_x=-1;old_y=-1;
x=MAP_WIDTH<<32/2; y=MAP_HEIGHT<<32/2;
dx=0; dy=1<<32;
w=20<<32;
i=COURSE_LEN/2;
while (y.i32[1]<MAP_HEIGHT-MAP_BORDER && i<COURSE_LEN) {
if (old_x.i32[1]!=x.i32[1]||old_y.i32[1]!=y.i32[1]) {
rx[i]=x.i32[1]; ry[i]=y.i32[1]; rw[i]=w.i32[1];
river_hi=i++;
old_x=x; old_y=y;
}
dx=LimitI64(dx+RandI32/64,-MAX_I32,MAX_I32);
dy=LimitI64(dy+RandI32/64,0,MAX_I32);
x+=dx; y+=dy;
w=LimitI64(w+RandI32*2,10*MAX_U32,150*MAX_U32);
}
//Plan upper course of river
old_x=-1;old_y=-1;
x=MAP_WIDTH<<32/2; y=MAP_HEIGHT<<32/2;
dx=0; dy=-1<<32;
w=20<<32;
i=COURSE_LEN/2-1;
while (y.i32[1]>=MAP_BORDER && i>=0) {
if (old_x.i32[1]!=x.i32[1]||old_y.i32[1]!=y.i32[1]) {
rx[i]=x.i32[1]; ry[i]=y.i32[1]; rw[i]=w.i32[1];
river_lo=i--;
old_x=x; old_y=y;
}
dx=LimitI64(dx+RandI32/64,-MAX_I32,MAX_I32);
dy=LimitI64(dy+RandI32/64,-MAX_I32,0);
x+=dx; y+=dy;
w=LimitI64(w+RandI32*2,10*MAX_U32,150*MAX_U32);
}
//Plot sand bar
x=0; y=0;
for (i=river_lo;i<=river_hi;i++) {
dc2->color=YELLOW;
dc2->pen_width=rw[i]+5;
GrPlot3(dc2,rx[i]+x.i32[1],ry[i]+y.i32[1],0);
x=LimitI64(x+RandI32,-6*MAX_U32,6*MAX_U32);
y=LimitI64(y+RandI32,-6*MAX_U32,6*MAX_U32);
}
//Plot water
for (i=river_lo;i<=river_hi;i++) {
dc2->color=BLUE;
dc2->pen_width=rw[i];
GrPlot3(dc2,rx[i],ry[i],0);
}
}
U0 RiverDel()
{
Free(rx);
Free(ry);
Free(rw);
}
// ************************************
class RiverDrop
{
RiverDrop *next,*last;
I64 index,dx,dy;
} rd_root;
Bool rd_lock;
U0 RiverDropsDel()
{
while (LBts(&rd_lock,0))
Yield;
QueDel(&rd_root,TRUE);
QueInit(&rd_root);
LBtr(&rd_lock,0);
}
U0 RiverDropsNext(CTask *mem_task)
{
RiverDrop *tempr,*tempr1;
while (LBts(&rd_lock,0))
Yield;
tempr=rd_root.next;
while (tempr!=&rd_root) {
tempr1=tempr->next;
if (++tempr->index>river_hi) {
QueRem(tempr);
Free(tempr);
} else {
do {
if (RandU16&1 &&
GrPeek(dc2,rx[tempr->index]+tempr->dx,ry[tempr->index]+tempr->dy)==BLUE)
break;
tempr->dx=LimitI64(tempr->dx+RandU16%3-1,-rw[tempr->index]/2,rw[tempr->index]/2);
tempr->dy=LimitI64(tempr->dy+RandU16%3-1,-rw[tempr->index]/2,rw[tempr->index]/2);
} while (GrPeek(dc2,rx[tempr->index]+tempr->dx,ry[tempr->index]+tempr->dy)!=BLUE &&
GrPeek(dc2,rx[tempr->index] ,ry[tempr->index]) ==BLUE); //Might be reinitializing
}
tempr=tempr1;
}
tempr=MAlloc(sizeof(RiverDrop),mem_task);
tempr->index=river_lo;
tempr->dx=0;
tempr->dy=0;
QueIns(tempr,rd_root.last);
LBtr(&rd_lock,0);
}
U0 RiverDropsDraw(CDC *dc,I64 cx,I64 cy)
{
RiverDrop *tempr;
dc->color=LTBLUE;
while (LBts(&rd_lock,0))
Yield;
tempr=rd_root.next;
while (tempr!=&rd_root) {
GrPlot(dc,rx[tempr->index]+tempr->dx-cx,ry[tempr->index]+tempr->dy-cy);
tempr=tempr->next;
}
LBtr(&rd_lock,0);
}
// ************************************
U0 DrawIt(CTask *task,CDC *dc)
{
static I64 last_ipx=0;
static Bool left=TRUE;
F64 t;
I64 i,
cx=(MAP_WIDTH -task->win_pixel_width)/2,
cy=(MAP_HEIGHT-task->win_pixel_height)/2;
if (task->win_scroll_x+cx<0)
task->win_scroll_x=-cx;
if (task->win_scroll_x+cx>MAP_WIDTH-task->win_pixel_width)
task->win_scroll_x=MAP_WIDTH-task->win_pixel_width-cx;
if (task->win_scroll_y+cy<0)
task->win_scroll_y=-cy;
if (task->win_scroll_y+cy>MAP_HEIGHT-task->win_pixel_height)
task->win_scroll_y=MAP_HEIGHT-task->win_pixel_height-cy;
dc2->flags|=DCF_NO_TRANSPARENTS;
GrBlot(dc,-cx,-cy,dc2);
RiverDropsDraw(dc,cx,cy);
for (i=0;i<NUM_ANIMALS;i++)
if (!a[i].dead) {
if (a[i].dx<0) {
dc->flags|=DCF_JUST_MIRROR|DCF_SYMMETRY;
GrSetSymmetry(dc,a[i].x.i32[1]-cx,0,a[i].x.i32[1]-cx,1);
}
CSpritePlot3(dc,a[i].x.i32[1]-cx,a[i].y.i32[1]-cy,0,a[i].ge->img);
dc->flags&=~(DCF_JUST_MIRROR|DCF_SYMMETRY);
}
if (ipx-last_ipx>0)
left=FALSE;
else if (ipx-last_ipx<0)
left=TRUE;
if (left) {
dc->flags|=DCF_JUST_MIRROR|DCF_SYMMETRY;
GrSetSymmetry(dc,ipx-task->win_pixel_left-task->win_scroll_x,0,ipx-task->win_pixel_left-task->win_scroll_x,1);
}
CSpritePlot3(dc,
ipx-task->win_pixel_left-task->win_scroll_x,
ipy-task->win_pixel_top -task->win_scroll_y,0,rh_sprite[GE_HORSE].img);
dc->flags&=~(DCF_JUST_MIRROR|DCF_SYMMETRY);
last_ipx=ipx;
if (tf) {
dc->color=RED;
t=tf-t0;
if (Blink(,tP(task)))
GrPutS(dc,(task->win_pixel_width-FONT_WIDTH*9)>>1-task->win_scroll_x,
(task->win_pixel_height-FONT_HEIGHT)>>1-task->win_scroll_y,
"Game Over");
} else {
dc->color=BLACK;
t=tP(task)-t0;
}
GrPrintF(dc,-task->win_scroll_x,-task->win_scroll_y,"Time:%7.2fs Best:%7.2fs",t,best_score);
}
U0 BuddySelect(I64 i)
{
I64 b,best_b=i,score,best_score=MAX_I64;
for (b=0;b<NUM_ANIMALS;b++) {
if (b!=i && !a[b].dead) {
score=RandU32%(512*512)+
SqrI64(a[b].x.i32[1]-a[i].x.i32[1])+
SqrI64(a[b].y.i32[1]-a[i].y.i32[1]);
if (score<best_score) {
best_score=score;
best_b=b;
}
}
}
a[i].buddy=best_b;
}
U0 AnimateTask(CTask *parent)
{
I64 i,cx,cy,cursor_x,cursor_y,dd,ddx,ddy,cnt,max_speed=MAX_I64,
min_x,max_x,min_y,max_y,updates=0;
F64 f,d,dx,dy,s,stress;
Animal *tempa,*tempa1;
while (TRUE) {
max_speed=LimitU64(max_speed,MAX_U32/3,200*MAX_U32);
cx=(MAP_WIDTH -parent->win_pixel_width)/2,
cy=(MAP_HEIGHT-parent->win_pixel_height)/2;
cursor_x=ipx+cx-parent->win_pixel_left-parent->win_scroll_x;
cursor_y=ipy+cy-parent->win_pixel_top -parent->win_scroll_y;
min_x=max_x=min_y=max_y=cnt=0;
stress=0;
for (i=0;i<NUM_ANIMALS;i++) {
tempa=&a[i];
if (!tempa->dead) {
//Move away from horse
ddx=tempa->x.i32[1]-cursor_x;
ddy=tempa->y.i32[1]-cursor_y;
if (dd=SqrI64(ddx)+SqrI64(ddy)) {
d=Sqrt(dd);
dx=ddx/d;
dy=ddy/d;
f=2.0e2*MAX_U32/dd;
tempa->dx+=f*dx;
tempa->dy+=f*dy;
}
//Reselect buddy about every NUM_ANIMALS*10ms=5.12 seconds
tempa1=&a[tempa->buddy];
if (tempa1->dead || i==updates%NUM_ANIMALS) {
BuddySelect(i);
tempa1=&a[tempa->buddy];
}
//Move toward buddy
ddx=tempa->x.i32[1]-tempa1->x.i32[1];
ddy=tempa->y.i32[1]-tempa1->y.i32[1];
if (dd=SqrI64(ddx)+SqrI64(ddy)) {
d=Sqrt(dd);
s=d`1.25-80;
stress+=Abs(s);
dx=ddx/d;
dy=ddy/d;
f=-0.001*s*MAX_U32;
tempa->dx+=f*dx;
tempa->dy+=f*dy;
}
//Make velocity similar to buddy
tempa->dx+=0.1*(tempa1->dx-tempa->dx);
tempa->dy+=0.1*(tempa1->dy-tempa->dy);
//Add random movement, limit speed and dampen speed
tempa->dx=0.995*LimitI64(tempa->dx+RandI32/32,-max_speed,max_speed);
tempa->dy=0.995*LimitI64(tempa->dy+RandI32/32,-max_speed,max_speed);
//Slow in river
if (GrPeek(dc2,tempa->x.i32[1],tempa->y.i32[1])!=LTGREEN) {
tempa->dx/=4;
tempa->dy/=4;
}
tempa->x+=tempa->dx;
tempa->y+=tempa->dy;
//Keep on map
if (!(MAP_BORDER-tempa->ge->min_x<=tempa->x.i32[1]<MAP_WIDTH-MAP_BORDER-tempa->ge->max_x)) {
tempa->x -=tempa->dx;
tempa->dx=-tempa->dx;
}
if (!(MAP_BORDER-tempa->ge->min_y<=tempa->y.i32[1]<MAP_HEIGHT-MAP_BORDER-tempa->ge->max_y)) {
tempa->y -=tempa->dy;
tempa->dy=-tempa->dy;
}
if (cnt) {
min_x=MinI64(min_x,tempa->x);
max_x=MaxI64(max_x,tempa->x);
min_y=MinI64(min_y,tempa->y);
max_y=MaxI64(max_y,tempa->y);
} else {
min_x=max_x=tempa->x;
min_y=max_y=tempa->y;
}
cnt++;
}
}
if (!(updates&15))
RiverDropsNext(parent);
if (!tf && (max_x-min_x)>>32<GR_WIDTH && (max_y-min_y)>>32<GR_HEIGHT) {
tf=tP(parent);
music_mute=TRUE;
Snd(2000);Sleep(200);Snd(0);Sleep(100);
if (tf-t0<best_score) {
best_score=tf-t0;
Snd(2000);Sleep(200);Snd(0);Sleep(100);
}
music_mute=FALSE;
}
updates++;
if (cnt)
stress/=cnt;
else
stress=0;
if (stress>100.0) {
Yield;
max_speed=stress/5.0*MAX_U32; //Converge faster at start-up
} else {
Sleep(10);
max_speed=0; //Will be set to normal max speed
}
}
}
U0 SongTask(I64)
{ //Randomly generated (by God :-)
Fs->task_end_cb=&SndTaskEndCB;
MusicSettingsRst;
while (TRUE) {
Play("W13qC2etG!3DCBDC!!ECFqFC!sADAD!qB");
Play("C2etG!3DCBDC!!ECFqFC!sADAD!qB");
Play("!2sG3A!2G3A!qG2etG3GDeBBqBFeBAqE");
Play("!2sG3A!2G3A!qG2etG3GDeBBqBFeBAqE");
}
}
U0 ReInit()
{
I64 i;
RiverDropsDel;
dc2->color=LTGREEN;
GrRect(dc2,2,2,MAP_WIDTH-4,MAP_HEIGHT-4);
RiverMake;
dc2->pen_width=MAP_BORDER;
dc2->color=RED;
GrLineRect4(dc2,MAP_BORDER/2,MAP_BORDER/2,MAP_WIDTH-(MAP_BORDER+1)/2,MAP_HEIGHT-(MAP_BORDER+1)/2);
for (i=river_lo;i<=river_hi;i++)
RiverDropsNext(Fs);
MemSet(a,0,NUM_ANIMALS*sizeof(Animal));
for (i=0;i<NUM_ANIMALS;i++) {
a[i].num=i;
a[i].x=(64+RandU32%(MAP_WIDTH-128))<<32;
a[i].y=(64+RandU32%(MAP_WIDTH-128))<<32;
if (i&1)
a[i].ge=&rh_sprite[GE_COW];
else
a[i].ge=&rh_sprite[GE_BULL];
BuddySelect(i);
}
t0=tP;
tf=0;
}
U0 Init()
{
I64 i;
RHCSprite *ge;
rh_sprite[0].img=$IB,"<1>",1$;
rh_sprite[1].img=$IB,"<2>",2$;
rh_sprite[2].img=$IB,"<3>",3$;
for (i=0;i<GE_NUM;i++) {
ge=&rh_sprite[i];
CSpriteExtents(ge->img,&ge->min_x,&ge->max_x,&ge->min_y,&ge->max_y);
}
RiverNew;
rd_lock=0;
QueInit(&rd_root);
dc2=DCNew(DCT_COLOR8,MAP_WIDTH,MAP_HEIGHT);
a=MAlloc(NUM_ANIMALS*sizeof(Animal));
ReInit;
}
U0 CleanUp()
{
DCDel(dc2);
Free(a);
RiverDropsDel;
RiverDel;
}
U0 RawHide()
{
I64 msg_code,p1,p2;
SettingsPush; //See $LK,"SettingsPush","MN:SettingsPush"$
PopUpOk(
"Coral the cattle into an area\n"
"the size of a screen.\n\n"
"Scroll with {CTRL-Left Grab}.\n"
"Center with {CTRL-Right}.");
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" Restart(,CH_NEW_LINE);"
"}"
);
Fs->song_task=Spawn(&SongTask,NULL,"Song",Fs);
Fs->win_inhibit=WIF_ALL-WIF_BORDER-WIF_GRAB_SCROLL-WIF_MENU;
WinMax;
WordStat;
Preempt(OFF);
Init;
Fs->animate_task=Spawn(&AnimateTask,Fs,"Animate",Fs);
DocCursor;
DocClear;
Fs->draw_it=&DrawIt;
try {
while (TRUE) {
msg_code=GetMsg(&p1,&p2,1<<MSG_KEY_DOWN+1<<MSG_IP_L_DOWN+1<<MSG_IP_R_DOWN);
switch (msg_code) {
case MSG_IP_L_DOWN: //Doesn't do anything, yet.
break;
case MSG_IP_R_DOWN: //Doesn't do anything, yet.
break;
case MSG_KEY_DOWN:
switch (p1) {
case CH_NEW_LINE:
ReInit;
break;
case CH_SHIFT_ESC:
case CH_ESC:
goto rh_done;
}
break;
}
}
rh_done:
} catch
CatchAll;
MenuPop;
SettingsPop;
CleanUp;
AcctRegWriteBranch("SparrowOS/RawHide","F64 best_score=%5.4f;\n",best_score);
}
RawHide;
òöÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿböÿÿÿôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÂöÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Binary file not shown.
Binary file not shown.
+708
View File
@@ -0,0 +1,708 @@
$BG,0$
$SP,"<ship_null>",1$
$SP,"<ship_thrust>",2$
$SP,"<ship_null2>",3$
$SP,"<ship_thrust2>",4$
$SP,"<tiny_rock>",5$
$SP,"<tiny_rock2>",6$
$SP,"<small_rock>",7$
$SP,"<small_rock2>",8$
$SP,"<medium_rock>",9$
$SP,"<medium_rock2>",10$
$SP,"<large_rock>",11$
$SP,"<large_rock2>",12$
$SP,"<Bullet>",13$
$SP,"<Cargo>",14$
$BG$
#define CMD_NULL 0
#define CMD_SPIN_LEFT 1
#define CMD_SPIN_RIGHT 2
#define CMD_THRUST 3
#define CMD_FIRE 4
#define CMD_GAME_OVER 5
I64 cmd_code=CMD_NULL;
#define NUM_STARS 100
I64 stars_x[NUM_STARS],stars_y[NUM_STARS];
Bool bounce;
#define OT_SHIP 1
#define OT_CARGO 2
#define OT_BULLET 3
#define OT_TINY_ROCK 4
#define OT_SMALL_ROCK 5
#define OT_MEDIUM_ROCK 6
#define OT_LARGE_ROCK 7
#define A_TRANSITION -1
#define A_INACTIVE 0
#define A_ACTIVE 1
class Order2D2é
{
F64 x,y,é;
F64 DxDt,DyDt,DéDt;
};
class Obj
{
I32 active;
I32 type;
U8 *img;
F64 mass,radius;
F64 timeout;
};
#define NUM_OBJECTS 256
CMathODE *ode;
Order2D2é *o_state;
Obj *objs;
U0 ObjInit(I64 i, I64 type)
{
objs[i].active=A_ACTIVE;
objs[i].timeout=0;
objs[i].type=type;
switch (type) {
case OT_SHIP:
if (bounce)
objs[i].img=$IB,"<ship_null>",1$;
else
objs[i].img=$IB,"<ship_null>",3$;
objs[i].radius=15;
break;
case OT_CARGO:
objs[i].img=$IB,"<cargo>",14$;
objs[i].radius=30;
break;
case OT_BULLET:
objs[i].img=$IB,"<bullet>",15$;
objs[i].radius=7;
break;
case OT_TINY_ROCK:
if (i&1)
objs[i].img=$IB,"<tiny_rock>",5$;
else
objs[i].img=$IB,"<tiny_rock2>",6$;
objs[i].radius=5;
break;
case OT_SMALL_ROCK:
if (i&1)
objs[i].img=$IB,"<small_rock>",16$;
else
objs[i].img=$IB,"<small_rock2>",8$;
objs[i].radius=11;
break;
case OT_MEDIUM_ROCK:
if (i&1)
objs[i].img=$IB,"<medium_rock>",17$;
else
objs[i].img=$IB,"<medium_rock2>",10$;
objs[i].radius=20;
break;
case OT_LARGE_ROCK:
if (i&1)
objs[i].img=$IB,"<large_rock>",18$;
else
objs[i].img=$IB,"<large_rock2>",12$;
objs[i].radius=26;
break;
}
objs[i].mass=objs[i].radius*objs[i].radius*objs[i].radius;
}
I64 ObjAlloc(I64 type)
{
I64 i;
for (i=0;i<NUM_OBJECTS-1;i++)
if (objs[i].active==A_INACTIVE)
break;
ObjInit(i,type);
return i;
}
U0 DrawIt(CTask *task,CDC *dc)
{
I64 i,x,y;
task->text_attr=BLACK<<4+WHITE;
dc->color=WHITE;
for (i=0;i<NUM_STARS;i++)
GrPlot(dc,stars_x[i],stars_y[i]);
for (i=0;i<NUM_OBJECTS;i++) {
if (objs[i].active==A_ACTIVE) {
if (objs[i].timeout && objs[i].timeout<tP(task))
objs[i].active=A_INACTIVE;
else {
x=o_state[i].x;
y=o_state[i].y;
if (x<0) {
x=GR_WIDTH-AbsI64(x)%GR_WIDTH;
o_state[i].x=x;
} else if (x>GR_WIDTH) {
x%=GR_WIDTH;
o_state[i].x=x;
}
if (y<0) {
y=GR_HEIGHT-AbsI64(y)%GR_HEIGHT;
o_state[i].y=y;
} else if (y>GR_HEIGHT) {
y%=GR_HEIGHT;
o_state[i].y=y;
}
switch (objs[i].type) {
case OT_SHIP:
if (bounce) {
if (cmd_code==CMD_THRUST && RandU16&0x8000)
CSpritePlotRotZ3b(dc,x,y,0,$IB,"<ship_thrust>",2$,o_state[i].é);
else
CSpritePlotRotZ3b(dc,x,y,0,$IB,"<ship_null>",1$,o_state[i].é);
} else {
if (cmd_code==CMD_THRUST && RandU16&0x8000)
CSpritePlotRotZ3b(dc,x,y,0,$IB,"<ship_thrust>",4$,o_state[i].é);
else
CSpritePlotRotZ3b(dc,x,y,0,$IB,"<ship_null>",3$,o_state[i].é);
}
break;
case OT_BULLET:
case OT_TINY_ROCK:
case OT_SMALL_ROCK:
case OT_MEDIUM_ROCK:
case OT_LARGE_ROCK:
case OT_CARGO:
CSpritePlotRotZ3b(dc,x,y,0,objs[i].img,o_state[i].é);
break;
}
}
}
}
dc->color=WHITE;
GrPutS(dc,0,0,"Escort the cargo ship.");
}
U0 Init()
{
I64 i,j;
cmd_code=CMD_NULL;
for (i=0;i<NUM_STARS;i++) {
stars_x[i]=RandU16%GR_WIDTH;
stars_y[i]=RandU16%GR_HEIGHT;
}
MemSet(objs,0,sizeof(Obj)*NUM_OBJECTS);
MemSet(o_state,0,sizeof(Order2D2é)*NUM_OBJECTS);
i=ObjAlloc(OT_SHIP); //always #0
objs[i].mass=2.0*objs[i].radius*objs[i].radius*objs[i].radius;
o_state[i].x=GR_WIDTH/2;
o_state[i].y=GR_HEIGHT/2;
i=ObjAlloc(OT_CARGO); //always #1
objs[i].mass=0.5*objs[i].radius*objs[i].radius*objs[i].radius;
o_state[i].x=0;
o_state[i].DxDt=16.0;
o_state[i].y=GR_HEIGHT/2;
o_state[i].é=ã/2;
for (j=0;j<4;j++) {
i=ObjAlloc(OT_LARGE_ROCK);
o_state[i].x=RandU32%GR_WIDTH;
o_state[i].y=RandU32%GR_HEIGHT;
o_state[i].DxDt=RandI16/2000.0;
o_state[i].DyDt=RandI16/2000.0;
o_state[i].DéDt=RandI16/25000.0;
o_state[i].é=2*ã*RandI16/16384.0;
}
}
U0 MyDerivative(CMathODE *,F64,Order2D2é *state,Order2D2é *DstateDt)
{
I64 i,j;
F64 f,d,d1,dd,dx,dy;
MemSet(DstateDt,0,sizeof(Order2D2é)*NUM_OBJECTS);
for (i=0;i<NUM_OBJECTS;i++) {
if (objs[i].active==A_ACTIVE) {
DstateDt[i].x=state[i].DxDt;
DstateDt[i].y=state[i].DyDt;
DstateDt[i].é=state[i].DéDt;
for (j=0;j<NUM_OBJECTS;j++) {
if (i!=j && objs[j].active==A_ACTIVE) {
dx=state[i].x-state[j].x;
dy=state[i].y-state[j].y;
dd=Sqr(dx)+Sqr(dy);
d=Sqrt(dd);
if (d) {
dx/=d;
dy/=d;
} else {
dx=0;
dy=0;
}
d1=objs[i].radius+objs[j].radius;
f=0;
if (dd<Sqr(d1)) {
if (bounce && objs[i].type!=OT_CARGO && objs[j].type!=OT_CARGO) {
f=Sqr(Sqr(Sqr(d1-Abs(d)+0.1))); //spring force
if (f>1000000.0) f=1000000.0;
}
} else
f=-2.5*objs[i].mass*objs[j].mass/(dd+1.0);
DstateDt[i].DxDt+=f*dx/objs[i].mass;
DstateDt[i].DyDt+=f*dy/objs[i].mass;
}
}
}
}
switch (cmd_code) {
case CMD_SPIN_LEFT:
DstateDt[0].DéDt-=10.0;
break;
case CMD_SPIN_RIGHT:
DstateDt[0].DéDt+=10.0;
break;
case CMD_THRUST:
DstateDt[0].DxDt+=100.0*Cos(state[0].é-ã/2.0);
DstateDt[0].DyDt+=100.0*Sin(state[0].é-ã/2.0);
break;
}
DstateDt[1].DxDt+=2.0*Cos(state[1].é-ã/2.0);
DstateDt[1].DyDt+=2.0*Sin(state[1].é-ã/2.0);
}
U0 Collision(I64 i,I64 j)
{
I64 i2;
switch (objs[i].type) {
case OT_SHIP:
if (!bounce) {
cmd_code=CMD_GAME_OVER;
objs[i].active=A_INACTIVE;
}
break;
case OT_CARGO:
cmd_code=CMD_GAME_OVER;
objs[i].active=A_INACTIVE;
break;
case OT_TINY_ROCK:
if (objs[j].type==OT_BULLET && !bounce)
objs[i].active=A_INACTIVE;
break;
case OT_BULLET:
if (!bounce)
objs[i].active=A_INACTIVE;
break;
case OT_SMALL_ROCK:
case OT_MEDIUM_ROCK:
i2=ObjAlloc(objs[i].type-1);
objs[i2].active=A_TRANSITION;
o_state[i2].x=o_state[i].x+objs[i2].radius+2.0;
o_state[i2].y=o_state[i].y;
o_state[i2].é=o_state[i].é;
o_state[i2].DxDt=o_state[i].DxDt;
o_state[i2].DyDt=o_state[i].DyDt;
o_state[i2].DéDt=o_state[i].DéDt;
i2=ObjAlloc(objs[i].type-1);
objs[i2].active=A_TRANSITION;
o_state[i2].x=o_state[i].x-objs[i2].radius-2.0;
o_state[i2].y=o_state[i].y;
o_state[i2].é=o_state[i].é;
o_state[i2].DxDt=o_state[i].DxDt;
o_state[i2].DyDt=o_state[i].DyDt;
o_state[i2].DéDt=o_state[i].DéDt;
objs[i].active=A_INACTIVE;
break;
case OT_LARGE_ROCK:
i2=ObjAlloc(objs[i].type-1);
objs[i2].active=A_TRANSITION;
o_state[i2].x=o_state[i].x+objs[i2].radius+4.0;
o_state[i2].y=o_state[i].y+objs[i2].radius+4.0;
o_state[i2].é=o_state[i].é;
o_state[i2].DxDt=o_state[i].DxDt;
o_state[i2].DyDt=o_state[i].DyDt;
o_state[i2].DéDt=o_state[i].DéDt;
i2=ObjAlloc(objs[i].type-1);
objs[i2].active=A_TRANSITION;
o_state[i2].x=o_state[i].x-objs[i2].radius-4.0;
o_state[i2].y=o_state[i].y-objs[i2].radius-4.0;
o_state[i2].é=o_state[i].é;
o_state[i2].DxDt=o_state[i].DxDt;
o_state[i2].DyDt=o_state[i].DyDt;
o_state[i2].DéDt=o_state[i].DéDt;
i2=ObjAlloc(objs[i].type-1);
objs[i2].active=A_TRANSITION;
o_state[i2].x=o_state[i].x-objs[i2].radius-4.0;
o_state[i2].y=o_state[i].y+objs[i2].radius+4.0;
o_state[i2].é=o_state[i].é;
o_state[i2].DxDt=o_state[i].DxDt;
o_state[i2].DyDt=o_state[i].DyDt;
o_state[i2].DéDt=o_state[i].DéDt;
i2=ObjAlloc(objs[i].type-1);
objs[i2].active=A_TRANSITION;
o_state[i2].x=o_state[i].x+objs[i2].radius+4.0;
o_state[i2].y=o_state[i].y-objs[i2].radius-4.0;
o_state[i2].é=o_state[i].é;
o_state[i2].DxDt=o_state[i].DxDt;
o_state[i2].DyDt=o_state[i].DyDt;
o_state[i2].DéDt=o_state[i].DéDt;
objs[i].active=A_INACTIVE;
break;
}
switch (objs[j].type) {
case OT_SHIP:
if (!bounce) {
cmd_code=CMD_GAME_OVER;
objs[j].active=A_INACTIVE;
}
break;
case OT_CARGO:
cmd_code=CMD_GAME_OVER;
objs[j].active=A_INACTIVE;
break;
case OT_TINY_ROCK:
if (objs[i].type==OT_BULLET && !bounce)
objs[j].active=A_INACTIVE;
break;
case OT_BULLET:
if (!bounce)
objs[j].active=A_INACTIVE;
break;
case OT_SMALL_ROCK:
case OT_MEDIUM_ROCK:
i2=ObjAlloc(objs[j].type-1);
objs[i2].active=A_TRANSITION;
o_state[i2].x=o_state[j].x+objs[i2].radius+2.0;
o_state[i2].y=o_state[j].y;
o_state[i2].é=o_state[j].é;
o_state[i2].DxDt=o_state[j].DxDt;
o_state[i2].DyDt=o_state[j].DyDt;
o_state[i2].DéDt=o_state[j].DéDt;
i2=ObjAlloc(objs[j].type-1);
objs[i2].active=A_TRANSITION;
o_state[i2].x=o_state[j].x-objs[i2].radius-2.0;
o_state[i2].y=o_state[j].y;
o_state[i2].é=o_state[j].é;
o_state[i2].DxDt=o_state[j].DxDt;
o_state[i2].DyDt=o_state[j].DyDt;
o_state[i2].DéDt=o_state[j].DéDt;
objs[j].active=A_INACTIVE;
break;
case OT_LARGE_ROCK:
i2=ObjAlloc(objs[j].type-1);
objs[i2].active=A_TRANSITION;
o_state[i2].x=o_state[j].x+objs[i2].radius+4.0;
o_state[i2].y=o_state[j].y+objs[i2].radius+4.0;
o_state[i2].é=o_state[j].é;
o_state[i2].DxDt=o_state[j].DxDt;
o_state[i2].DyDt=o_state[j].DyDt;
o_state[i2].DéDt=o_state[j].DéDt;
i2=ObjAlloc(objs[j].type-1);
objs[i2].active=A_TRANSITION;
o_state[i2].x=o_state[j].x-objs[i2].radius-4.0;
o_state[i2].y=o_state[j].y-objs[i2].radius-4.0;
o_state[i2].é=o_state[j].é;
o_state[i2].DxDt=o_state[j].DxDt;
o_state[i2].DyDt=o_state[j].DyDt;
o_state[i2].DéDt=o_state[j].DéDt;
i2=ObjAlloc(objs[j].type-1);
objs[i2].active=A_TRANSITION;
o_state[i2].x=o_state[j].x-objs[i2].radius-4.0;
o_state[i2].y=o_state[j].y+objs[i2].radius+4.0;
o_state[i2].é=o_state[j].é;
o_state[i2].DxDt=o_state[j].DxDt;
o_state[i2].DyDt=o_state[j].DyDt;
o_state[i2].DéDt=o_state[j].DéDt;
i2=ObjAlloc(objs[j].type-1);
objs[i2].active=A_TRANSITION;
o_state[i2].x=o_state[j].x+objs[i2].radius+4.0;
o_state[i2].y=o_state[j].y-objs[i2].radius-4.0;
o_state[i2].é=o_state[j].é;
o_state[i2].DxDt=o_state[j].DxDt;
o_state[i2].DyDt=o_state[j].DyDt;
o_state[i2].DéDt=o_state[j].DéDt;
objs[j].active=A_INACTIVE;
break;
}
}
U0 CheckCollisions()
{
I64 i,j;
F64 d,d1,dd,dx,dy;
CDC *dc;
for (i=0;i<NUM_OBJECTS;i++) {
if (objs[i].active==A_ACTIVE) {
for (j=i+1;j<NUM_OBJECTS;j++) {
if (objs[j].active==A_ACTIVE) {
dx=o_state[i].x-o_state[j].x;
dy=o_state[i].y-o_state[j].y;
dd=Sqr(dx)+Sqr(dy);
d=Sqrt(dd);
if (d) {
dx/=d;
dy/=d;
} else {
dx=0;
dy=0;
}
d1=objs[i].radius+objs[j].radius;
if (dd<Sqr(d1)) {
dc=DCNew(DCT_COLOR8,64,64,Fs);
CSpritePlotRotZ3b(dc,32,32,0,objs[i].img,o_state[i].é);
dc->color=ROP_COLLISION;
dc->bkcolor=BLACK;
CSpritePlotRotZ3b(dc,o_state[j].x-o_state[i].x+32,
o_state[j].y-o_state[i].y+32,0,
objs[j].img,o_state[j].é);
if (dc->collision_cnt>0)
Collision(i,j);
DCDel(dc);
}
}
}
}
}
for (i=0;i<NUM_OBJECTS;i++)
if (objs[i].active==A_TRANSITION)
objs[i].active=A_ACTIVE;
}
#define MUZZLE_VELOCITY 500.0
U0 Fire()
{
F64 é=o_state[0].é;
I64 i=ObjAlloc(OT_BULLET);
objs[i].timeout=tP+0.5;
objs[i].mass*=10.0;
o_state[i].x=o_state[0].x+(objs[0].radius+objs[i].radius+1.0)*Cos(é-ã/2.0);
o_state[i].y=o_state[0].y+(objs[0].radius+objs[i].radius+1.0)*Sin(é-ã/2.0);
o_state[i].DxDt=o_state[0].DxDt+MUZZLE_VELOCITY*Cos(é-ã/2.0);
o_state[i].DyDt=o_state[0].DyDt+MUZZLE_VELOCITY*Sin(é-ã/2.0);
o_state[i].DéDt=RandI16/3000.0;
//not real physics with the 0.005 factor
o_state[0].DxDt-=0.005*MUZZLE_VELOCITY*Cos(é-ã/2.0)*objs[i].mass/objs[0].mass;
o_state[0].DyDt-=0.005*MUZZLE_VELOCITY*Sin(é-ã/2.0)*objs[i].mass/objs[0].mass;
}
U0 CheckCrazy()
{
I64 i;
F64 d;
for (i=0;i<NUM_OBJECTS;i++)
if (objs[i].active==A_ACTIVE) {
d=Sqrt(Sqr(o_state[i].DxDt)+Sqr(o_state[i].DyDt));
if (d>MUZZLE_VELOCITY*5.0)
Auto(" ");
}
}
U0 SongTask(I64)
{ //Song by Terry A. Davis
Fs->task_end_cb=&SndTaskEndCB;
MusicSettingsRst;
while (TRUE) {
Play("W13eGGsGGeGGGe.GeCDsEDeCBAe.AeG");
Play("GsGGeGGGe.GeFEsDEeDCBe.AeFD");
Play("EDFDEDECDCECDCsGGeG");
Play("GG2hG3sGGeGGG2hG");
}
}
U0 Rocks()
{
I64 ch,sc,msg_code;
CMenuEntry *tempse;
PopUpOk(
"I refuse to rip-off the original\n"
"so this is intentionally unplayable\n"
"and included for demonstration\n"
"purposes.\n\n"
"Write games, don't play them.\n");
SettingsPush; //See $LK,"SettingsPush","MN:SettingsPush"$
Fs->song_task=Spawn(&SongTask,NULL,"Song",Fs);
Preempt(OFF),
WinBorder;
WordStat;
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" Restart(,CH_NEW_LINE);"
" Fire(,CH_SPACE);"
" Fwd(,,SC_CURSOR_UP);"
" Left(,,SC_CURSOR_LEFT);"
" Right(,,SC_CURSOR_RIGHT);"
" ToggleBounce(,'b');"
"}"
);
tempse=MenuEntryFind(Fs->cur_menu,"Play/ToggleBounce");
tempse->checked=bounce=TRUE;
ode=ODENew(NUM_OBJECTS*6,0.01);
ode->derivative=&MyDerivative;
ode->min_tolerance=0.001*ode->max_tolerance;
o_state=ode->state;
objs=MAlloc(NUM_OBJECTS*sizeof(Obj));
WinMax;
Init;
QueIns(ode,Fs->last_ode);
DocCursor;
DocClear;
Fs->draw_it=&DrawIt;
try {
while (TRUE) {
while (msg_code=ScanMsg(&ch,&sc,1<<MSG_KEY_DOWN|1<<MSG_KEY_UP)) {
if (msg_code==MSG_KEY_DOWN)
switch (ch) {
case 0:
switch (sc.u8[0]) {
case SC_CURSOR_RIGHT:
cmd_code=CMD_SPIN_RIGHT;
break;
case SC_CURSOR_LEFT:
cmd_code=CMD_SPIN_LEFT;
break;
case SC_CURSOR_UP:
cmd_code=CMD_THRUST;
break;
}
break;
case CH_SPACE:
Fire;
break;
case CH_NEW_LINE:
Init;
break;
case CH_ESC:
case CH_SHIFT_ESC:
goto rk_done;
case 'b':
tempse=MenuEntryFind(Fs->cur_menu,"Play/ToggleBounce");
tempse->checked=bounce=!bounce;
break;
}
else //MSG_KEY_UP
cmd_code=CMD_NULL;
}
CheckCollisions;
CheckCrazy;
if (cmd_code==CMD_GAME_OVER) {
Sleep(1000);
Init;
}
WinMgrSync; //msgs are only qued by winmngr
}
rk_done:
GetMsg(,,1<<MSG_KEY_UP);
} catch
CatchAll;
QueRem(ode);
ODEDel(ode);
Free(objs);
MenuPop;
SettingsPop;
}
Rocks;
®ùÿÿÿüÿÿÿüÿÿÿúÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿýÿÿÿýÿÿÿ÷ÿÿÿ÷ÿÿÿûÿÿÿûÿÿÿÿÿÿÿøÿÿÿøÿÿÿ   
 ôÿÿÿôÿÿÿôÿÿÿôÿÿÿùÿÿÿùÿÿÿùÿÿÿùÿÿÿþÿÿÿ þÿÿÿ   ùÿÿÿüÿÿÿüÿÿÿúÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿýÿÿÿýÿÿÿ÷ÿÿÿ÷ÿÿÿûÿÿÿûÿÿÿÿÿÿÿøÿÿÿøÿÿÿÿÿÿÿþÿÿÿ
þÿÿÿ

 ␍  ýÿÿÿ



óÿÿÿóÿÿÿøÿÿÿøÿÿÿûÿÿÿ ûÿÿÿ 3þÿÿÿýÿÿÿólß$† n[½þÿÿÿd¨ Šgþÿÿÿûÿÿÿn[Ïm’$C’$É$QeÛ¼„ar–ͳíÙžW’"Cš¶½mÛ²úÿÿÿ¶m’6MÛ+üÿÿÿ¤m
þÿÿÿþÿÿÿ¤iÛ
I² Grüÿÿÿôÿÿÿóæy^ÝÚ³m“$íÛmÛ³g’¡F CQŒ¢d["‰©( ³lÁ°lž×n$I’T¤$à ÷ÿÿÿž=Û$Íúÿÿÿ«]»¶m“¦IFI’$I’„IrY–ms×zõÖm¶kÛ&MÛ¶m“¤%‘’l¶e[’$‰HÒ·m›<I“$I’$I’ ³mÛ¶mÛ¶m[DŠŒüÿÿÿøÿÿÿ¶Mß§m{ þÿÿÿI�ɶm›·yÛùÿÿÿv]×£’,K€$ÉW $¥�Q‘ IŠK°Ù2Û´MoK’dɶm›=Ï3O“¦=␍øÿÿÿúÿÿÿ«ëu¦␍ó ÿÿÿÿþÿÿÿþÿÿÿþÿÿÿýÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿýÿÿÿÿÿÿÿÿÿÿÿýÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿÿ
þÿÿÿýÿÿÿþÿÿÿó ÿÿÿÿþÿÿÿþÿÿÿþÿÿÿýÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿýÿÿÿÿÿÿÿÿÿÿÿýÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿÿ
þÿÿÿýÿÿÿþÿÿÿ3þÿÿÿýÿÿÿólß$† n[½þÿÿÿd¨Šgþÿÿÿûÿÿÿn[Ïm’$C’$É$QeÛ¼„ar–ͳíÙžW’"Cš¶½mÛ²úÿÿÿ¶m’6MÛ+üÿÿÿ¤m
þÿÿÿþÿÿÿ¤iÛ
I²Grüÿÿÿôÿÿÿóæy^ÝÚ³m“$íÛmÛ³g’¡F CQŒ¢d["‰©( ³lÁ°lž×n$I’T¤$à ÷ÿÿÿž=Û$Íúÿÿÿ«]»¶m“¦IFI’$I’„IrY–ms×zõÖm¶kÛ&MÛ¶m“¤%‘’l¶e[’$‰HÒ·m›<I“$I’$I’ ³mÛ¶mÛ¶m[DŠŒüÿÿÿøÿÿÿ¶Mß§m{ þÿÿÿI�ɶm›·yÛùÿÿÿv]×£’,K€$ÉW $¥�Q‘ IŠK°Ù2Û´MoK’dɶm›=Ï3O“¦=␍øÿÿÿúÿÿÿ«ëu¦6(ÿÿÿÿûÿÿÿÛlÛ¤m“dÂ�$·m ²dþÿÿÿþÿÿÿöiÚ
kMøÿÿÿصkۦϓ$Û$‰$ ’ A’$$m»Þ6ÏófGÿÿÿÿûÿÿÿuëÚöH† EQdlÛö-Q$Æë Á²lmýÿÿÿúÿÿÿ ÙöÿÿÿsÛÖmëÖ­ÏŸmû$¥$”"mY�%‰¢( #I’ÚömÛ®k»@’,˶mö¼$a…‰Â�$mÛ¾i’¾ùÛÁ¶mÛ¶m›çºvm[I¤„‰ÂDGøÿÿÿ®ëÚöì%›mÛ¶Iš´ízÛšˆÜþoI&IGA’$I’$II”m“¤ïmÛ¶Õž·$
’!É␍+øÿÿÿþÿÿÿk»éÿ´mÓ$™0L�e[ ýÿÿÿI– Éúÿÿÿ]Û" ýÿÿÿ›·Í¶m& ¥�¦í­¾ðÿÿÿþÿÿÿÿÿÿÿ ␍ûÿÿÿúÿÿÿûÿÿÿúÿÿÿùÿÿÿöÿÿÿöÿÿÿúÿÿÿþÿÿÿüÿÿÿüÿÿÿýÿÿÿýÿÿÿ␍␍␍ýÿÿÿ

þÿÿÿûÿÿÿþÿÿÿûÿÿÿ␍   ÿÿÿÿúÿÿÿüÿÿÿ ûÿÿÿþÿÿÿùÿÿÿüÿÿÿüÿÿÿúÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿýÿÿÿýÿÿÿ÷ÿÿÿ÷ÿÿÿûÿÿÿûÿÿÿÿÿÿÿøÿÿÿøÿÿÿŸùÿÿÿüÿÿÿüÿÿÿúÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿýÿÿÿýÿÿÿ÷ÿÿÿ÷ÿÿÿûÿÿÿûÿÿÿÿÿÿÿøÿÿÿøÿÿÿÿÿÿÿþÿÿÿ
þÿÿÿ

 ␍ 'þÿÿÿþÿÿÿ4In]Kjÿÿÿÿ (þÿÿÿ6™%Ifýÿÿÿ$I
Binary file not shown.
+408
View File
@@ -0,0 +1,408 @@
#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>",1$
$SP,"<2>",2$
$SP,"<3>",3$
$BG$
#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 *task,CDC *dc)
{
Bool old_suspend,first;
F64 dx,dy,d;
I64 x1b,y1b,x2b,y2b,
x1a,y1a,x2a,y2a;
MyMass *tempm,*tempm1;
MySpring *temps;
CD3I32 poly[4];
if (start_up_timeout>tNP) {
ode->drag_v2=0.01; //Let hose settle during start-up
ode->drag_v3=0.0001;
dc->color=RED;
GrPutS(dc,(GR_WIDTH-FONT_WIDTH*6)>>1,GR_HEIGHT>>1,"Squirt");
return;
} else {
ode->drag_v2=0.0005;
ode->drag_v3=0.0000025;
}
old_suspend=Suspend(task);
tempm=faucet;
dc->color=BLACK;
GrRect(dc,tempm->x+8,tempm->y,8,GROUND_Y-FAUCET_Y);
CSpritePlot3(dc,tempm->x,tempm->y,0,$IB,"<1>",1$);
dc->color=BLACK;
GrCircle(dc,tempm->x,tempm->y,tempm->radius);
dc->color=GREEN;
GrFloodFill(dc,tempm->x,tempm->y);
tempm=nozzle;
tempm1=nozzle->last;
dx=tempm->x-tempm1->x;
dy=tempm->y-tempm1->y;
nozzle_é=Wrap(Arg(dx,dy));
CSpritePlotRotZ3b(dc,tempm->x,tempm->y,0,$IB,"<2>",2$,nozzle_é);
dc->color=BLACK;
GrCircle(dc,tempm->x,tempm->y,tempm->radius);
dc->color=GREEN;
GrFloodFill(dc,tempm->x,tempm->y);
first=TRUE;
tempm=ode->next_mass;
while (tempm!=&ode->next_mass) {
if (tempm->type==MT_HOSE) {
tempm1=tempm->last;
dx=tempm->x-tempm1->x;
dy=tempm->y-tempm1->y;
d=HOSE_RADIUS/Max(Sqrt(dx*dx+dy*dy),0.001);
dx*=d;
dy*=d;
x2a=tempm->x-dy;
y2a=tempm->y+dx;
x2b=tempm->x+dy;
y2b=tempm->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 (tempm->type==MT_DROPLET)
CSpritePlot3(dc,tempm->x,tempm->y,0,$IB,"<3>",3$);
tempm=tempm->next;
}
temps=ode->next_spring;
while (temps!=&ode->next_spring) {
if (temps->type==ST_HOSE) {
dx=temps->end1->x-temps->end2->x;
dy=temps->end1->y-temps->end2->y;
d=HOSE_RADIUS/Max(Sqrt(dx*dx+dy*dy),0.001);
dx*=d;
dy*=d;
dc->color=BLACK;
GrLine(dc,temps->end1->x-dy,temps->end1->y+dx,
temps->end2->x-dy,temps->end2->y+dx);
GrLine(dc,temps->end1->x+dy,temps->end1->y-dx,
temps->end2->x+dy,temps->end2->y-dx);
}
temps=temps->next;
}
Suspend(task,old_suspend);
}
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.
nounusedwarn t,state,DstateDt;
// F64 d,dd;
// CD3 p;
MyMass *tempm1,*tempm2;
nounusedwarn tempm2;
tempm1=ode->next_mass;
while (tempm1!=&ode->next_mass) {
if (tempm1->type==MT_HOSE) {
if (tempm1->state->y+tempm1->radius>GROUND_Y)
tempm1->DstateDt->DyDt-=Sqr(Sqr(tempm1->state->y+tempm1->radius-GROUND_Y))*tempm1->mass;
else
tempm1->DstateDt->DyDt+=500*tempm1->mass;
if (tempm1==nozzle || tempm1==faucet) {
tempm1->DstateDt->DxDt=0;
tempm1->DstateDt->DyDt=0;
}
} else if (tempm1->type==MT_DROPLET)
tempm1->DstateDt->DyDt=500*tempm1->mass;
tempm1=tempm1->next;
}
}
MyMass *PlaceMass(I64 type,I64 x, I64 y,F64 r,F64 dx,F64 dy,F64 mass,CTask *mem_task)
{
MyMass *tempm=CAlloc(sizeof(MyMass),mem_task);
tempm->type=type;
tempm->mass=mass;
tempm->drag_profile_factor=250.0;
tempm->x=x;
tempm->y=y;
tempm->DxDt=dx;
tempm->DyDt=dy;
tempm->radius=r;
QueIns(tempm,ode->last_mass);
return tempm;
}
MySpring PlaceSpring(MyMass *tempm1,MyMass *tempm2)
{
MySpring *temps=CAlloc(sizeof(MySpring));
temps->end1=tempm1;
temps->end2=tempm2;
temps->constant=20000;
QueIns(temps,ode->last_spring);
return temps;
}
U0 HoseNew()
{
I64 i;
MyMass *tempm1=NULL,*tempm;
MySpring *temps;
for (i=FAUCET_X;i<GR_WIDTH;i+=LINK_SIZE) {
tempm=PlaceMass(MT_HOSE,i/2,GROUND_Y-HOSE_RADIUS,HOSE_RADIUS,0,0,1.0,Fs);
if (tempm1) {
temps=PlaceSpring(tempm,tempm1);
temps->rest_len=LINK_SIZE;
temps->type=ST_HOSE;
nozzle=tempm;
} else
faucet=tempm;
tempm1=tempm;
}
faucet->y=FAUCET_Y;
nozzle->y=NOZZLE_START_Y;
nozzle_é=0;
}
U0 AnimateTask(I64)
{
//Preempt is off by default for new task
MyMass *tempm,*tempm1;
F64 dx,dy;
while (TRUE) {
//The WinMgr task suspends our parent when it
//updates the ODE's. We use this to know when
//the ODE's are being updated.
if (!IsSuspended(Fs->parent_task)) {
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);
tempm=ode->next_mass;
while (tempm!=&ode->next_mass) {
tempm1=tempm->next;
if (tempm->type==MT_DROPLET &&
tempm->y+tempm->radius>GROUND_Y) {
QueRem(tempm);
Free(tempm);
}
tempm=tempm1;
}
}
WinMgrSync;
}
}
#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=Limit(nozzle->x+
sign*NOZZLE_MOVE/NOZZLE_MOVE_STEPS,
HOSE_RADIUS*3,GR_WIDTH-HOSE_RADIUS*3);
WinMgrSync;
}
}
U0 MoveNozzleTaskY(I64 sign)
{
I64 i;
for (i=0;i<NOZZLE_MOVE_STEPS;i++) {
nozzle->y=Limit(nozzle->y+
sign*NOZZLE_MOVE/NOZZLE_MOVE_STEPS,
HOSE_RADIUS*3,GROUND_Y);
WinMgrSync;
}
}
U0 DrawBackGroundTextLayer()
{
DocClear;
"$$BG,LTCYAN$$";
NewLine(GROUND_Y/FONT_HEIGHT);
"$$BG,YELLOW$$";
}
U0 Init()
{
DrawBackGroundTextLayer;
//Allow hose to settle.
start_up_timeout=tNP+0.5;
ode=ODENew(0,5e-2,ODEF_HAS_MASSES);
ode->derivative=&MyDerivative;
ode->acceleration_limit=5e3;
HoseNew;
QueIns(ode,Fs->last_ode);
}
U0 CleanUp()
{
WinMgrSync(NOZZLE_MOVE_STEPS); //Let nozzle move tasks die
QueRem(ode);
QueDel(&ode->next_mass,TRUE);
QueDel(&ode->next_spring,TRUE);
ODEDel(ode);
DocClear;
"$$BG$$";
}
U0 SongTask(I64)
{
Fs->task_end_cb=&SndTaskEndCB;
MusicSettingsRst;
while (TRUE) {
Play("W13eAM4/4");
Play("2qGeGqG3eAq.BqBeBqA2eG3qA");
Play("eB2hG3q.BqBeCq.DD");
Play("qCeBqCeDhB");
}
}
U0 Squirt()
{
I64 sc;
SettingsPush; //See $LK,"SettingsPush","MN:SettingsPush"$
Fs->song_task=Spawn(&SongTask,NULL,"Song",Fs);
WinMax;
WinBorder;
Preempt(OFF);
DocCursor;
Fs->win_inhibit|=WIF_DBL_CLICK;
WordStat;
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" Restart(,CH_NEW_LINE);"
" 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 CH_NEW_LINE:
CleanUp;
Init;
break;
case CH_SHIFT_ESC:
case CH_ESC:
goto sq_done;
}
}
sq_done: //Don't goto out of try
} catch
CatchAll;
SettingsPop;
CleanUp;
MenuPop;
}
Squirt;
R÷ÿÿÿìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ2 ÿÿÿÿûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿJýÿÿÿýÿÿÿÿÿÿ ÿÿ ÿ ÿÿ  ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,30 @@
//Generate "Stadium.GRA.Z" from "Stadium.TXT.Z"
U0 StadiumGen()
{
U0 (*fp_old_update)(CDC *dc);
CDC *dc;
WinMax;
WinBorder;
DocClear;
Type("::/SparrowOS/Demo/GameStarters/Stadium/Stadium.TXT.Z");
"$$CM,0,%d$$",TEXT_ROWS-2;
DocCursor(OFF);
fp_old_update=fp_final_screen_update; //hide mouse cursor
fp_final_screen_update=NULL;
WinMgrSync(2,TRUE);
dc=DCExtract(gr_screen_image,0,FONT_HEIGHT,GR_WIDTH,GR_HEIGHT);
GRAWrite("::/SparrowOS/Demo/GameStarters/Stadium/Stadium",dc);
DCDel(dc);
DocCursor(ON);
fp_final_screen_update=fp_old_update;
DocClear;
}
StadiumGen;
Binary file not shown.
+124
View File
@@ -0,0 +1,124 @@
I8 board [9];
I64 board_x[9]={150,250,350,150,250,350,150,250,350};
I64 board_y[9]={150,150,150,250,250,250,350,350,350};
U0 DrawX(CDC *dc,I64 x,I64 y)
{
dc->pen_width=5;
GrLine3(dc,x-20,y-20,0,x+20,y+20,0);
GrLine3(dc,x+20,y-20,0,x-20,y+20,0);
}
U0 DrawO(CDC *dc,I64 x,I64 y)
{
dc->pen_width=5;
GrCircle3(dc,x,y,0,25);
}
U0 DrawBoard(I64 player)
{
I64 i;
CDC *dc=DCAlias;
DCFill;
dc->pen_width=5;
GrLine3(dc,200,100,0,200,400,0);
GrLine3(dc,300,100,0,300,400,0);
GrLine3(dc,100,200,0,400,200,0);
GrLine3(dc,100,300,0,400,300,0);
for (i=0;i<9;i++)
switch (board[i]) {
case 1:
DrawX(dc,board_x[i],board_y[i]);
break;
case 2:
DrawO(dc,board_x[i],board_y[i]);
break;
}
if (player==1)
DrawX(dc,ipx-Fs->win_pixel_left,ipy-Fs->win_pixel_top);
else
DrawO(dc,ipx-Fs->win_pixel_left,ipy-Fs->win_pixel_top);
DCDel(dc);
}
U0 TakeTurn(I64 player)
{
I64 i,x=0,y=0;
while (!(100<=x<400) || !(100<=y<400) || board[i]) {
if (player==1)
Beep(500);
else
Beep(1000);
while (!ip_lb) {
DrawBoard(player);
WinMgrSync;
}
while (ip_lb) {
DrawBoard(player);
WinMgrSync;
}
x=ipx-Fs->win_pixel_left;
y=ipy-Fs->win_pixel_top;
i=(x-100)/100+(y-100)/100*3;
}
board[i]=player;
}
Bool CheckWinner(I64 player)
{
if ( player==board[0]==board[1]==board[2] ||
player==board[3]==board[4]==board[5] ||
player==board[6]==board[7]==board[8] ||
player==board[0]==board[3]==board[6] ||
player==board[1]==board[4]==board[7] ||
player==board[2]==board[5]==board[8] ||
player==board[0]==board[4]==board[8] ||
player==board[2]==board[4]==board[6] )
return TRUE;
else
return FALSE;
}
U0 DoGame()
{
I64 moves=0;
MemSet(board,0,sizeof(board));
while (TRUE) {
TakeTurn(1);
if (CheckWinner(1)) {
Beep(500);
Beep(500);
Beep(500);
break;
}
if (++moves==9) break;
TakeTurn(2);
if (CheckWinner(2)) {
Beep(1000);
Beep(1000);
Beep(1000);
break;
}
if (++moves==9) break;
}
}
U0 TicTacToe()
{
WinMax; //Maximize window
DocClear; //Clear window text.
"$$FG,GREEN$$CTRL-ALT-C$$FG$$ to exit.\n";
try
while (TRUE)
DoGame;
catch
CatchAll;
DCFill;
}
TicTacToe;
Binary file not shown.
Binary file not shown.
+540
View File
@@ -0,0 +1,540 @@
AcctRegSetDftEntry("SparrowOS/Wenceslas","F64 best_score=9999;\n");
AcctRegExecuteBranch("SparrowOS/Wenceslas");
#define BORDER 5
#define KING_STEP 4
$SP,"<1>",1$
$SP,"<2>",2$
$SP,"<3>",3$
$SP,"<4>",4$
$SP,"<5>",5$
$SP,"<6>",6$
$SP,"<7>",7$
#define NUM_FLAKES 0x8000
class Flake
{
U16 x,y;
} flakes[NUM_FLAKES];
#define NUM_TREES 8
class Tree
{
U16 x,y;
I64 fire_frame_index;
} trees[NUM_TREES];
I64 snow_x,snow_y;
I64 king_x,king_y,not_stopped_cnt;
F64 king_é,t0,tf,door_open_t0;
#define NUM_PEASANTS 16
class Peasant
{
Peasant *next,*last;
F64 x,y,é,door_opened_t0;
Bool stopped;
} peasant_root;
class Step
{
Step *next,*last;
U16 x,y;
F64 t0;
} step_root,king_step_root;
U0 DrawIt(CTask *task,CDC *dc)
{
I64 r[16],i,w=task->win_pixel_width,h=task->win_pixel_height;
U8 *img;
Step *temps;
Peasant *tempp;
F64 tt;
Bool old_preempt=Preempt(OFF);
dc->pen_width=1;
for (i=0;i<NUM_TREES;i++) {
if (trees[i].y<=h/2) { //Draw trees behind house
if (trees[i].fire_frame_index) {
if (trees[i].fire_frame_index++&1)
img=$IB,"<4>",4$;
else
img=$IB,"<5>",5$;
} else
img=$IB,"<3>",3$;
CSpritePlot3(dc,trees[i].x,trees[i].y,0,img);
}
}
CSpritePlot3(dc,w/2,h/2,0,$IB,"<6>",6$);
if (tP(task)<door_open_t0+1.0)
CSpritePlot3(dc,w/2,h/2,0,$IB,"<7>",7$);
for (i=0;i<NUM_TREES;i++) {
if (trees[i].y>h/2) { //Draw trees in front of house
if (trees[i].fire_frame_index) {
if (trees[i].fire_frame_index++&1)
img=$IB,"<4>",4$;
else
img=$IB,"<5>",5$;
} else
img=$IB,"<3>",3$;
CSpritePlot3(dc,trees[i].x,trees[i].y,0,img);
}
}
temps=step_root.next;
while (temps!=&step_root) {
if (tP(task)-temps->t0<2.0)
dc->color=DKGRAY;
else
dc->color=LTGRAY;
dc->pen_width=2;
GrPlot3(dc,temps->x,temps->y,0);
temps=temps->next;
}
dc->pen_width=1;
tempp=peasant_root.next;
while (tempp!=&peasant_root) {
GrIdentEqu(r);
GrRotYEqu(r,tempp->é+ã/2);
GrRotXEqu(r,ã/6);
if (tempp->stopped)
dc->color=LTCYAN;
else
dc->color=CYAN;
CSpritePlotRotMat3b(dc,tempp->x,tempp->y,0,$IB,"<2>",2$,r);
tempp=tempp->next;
}
dc->pen_width=1;
GrIdentEqu(r);
GrRotYEqu(r,king_é+ã/2);
GrRotXEqu(r,ã/6);
CSpritePlotRotMat3b(dc,king_x,king_y,0,$IB,"<1>",1$,r);
dc->pen_width=1;
dc->color=WHITE;
for (i=0;i<NUM_FLAKES;i++)
GrPlot(dc,(flakes[i].x+snow_x)%task->win_pixel_width,
(flakes[i].y+snow_y)%task->win_pixel_height);
if (tf) {
dc->color=LTRED;
if (Blink(,tP(task)))
GrPutS(dc,w/2-(FONT_WIDTH*14)/2,h/2+FONT_HEIGHT,"Game Completed");
tt=tf;
} else {
tt=tP(task);
}
dc->color=LTBLUE;
GrPrintF(dc,0,0,"Freezing Peasants:%d Time:%3.2f Best:%3.2f",
not_stopped_cnt,tt-t0,best_score);
Preempt(old_preempt);
}
U0 StepNew(CTask *task,I64 x,I64 y,F64 é,Bool king)
{
Step *temps;
if (king) {
temps=MAlloc(sizeof(Step),task);
temps->x=x;
temps->y=y;
temps->t0=tP(task);
QueIns(temps,king_step_root.last);
}
temps=MAlloc(sizeof(Step),task);
temps->x=x-3.5*Sin(é)+1.0*Cos(é);
temps->y=y+3.5*Cos(é)+1.0*Sin(é);
temps->t0=tP(task);
QueIns(temps,step_root.last);
temps=MAlloc(sizeof(Step),task);
temps->x=x+3.5*Sin(é)-1.0*Cos(é);
temps->y=y-3.5*Cos(é)-1.0*Sin(é);
temps->t0=tP(task);
QueIns(temps,step_root.last);
}
U0 Init()
{
I64 i,min_x,max_x,min_y,max_y,
w=Fs->win_pixel_width,h=Fs->win_pixel_height;
Peasant *tempp;
snow_x=0;
snow_y=0;
for (i=0;i<NUM_FLAKES;i++) {
flakes[i].x=RandU16;
flakes[i].y=RandU16;
}
CSpriteExtents($IB,"<3>",3$,&min_x,&max_x,&min_y,&max_y);
for (i=0;i<NUM_TREES;i++) {
trees[i].x=RandU16%(w-2*BORDER-(max_x-min_x+1))+BORDER-min_x;
trees[i].y=RandU16%(h-2*BORDER-(max_y-min_y+1))+BORDER-min_y;
trees[i].fire_frame_index=0;
}
QueInit(&step_root);
QueInit(&king_step_root);
CSpriteExtents($IB,"<1>",1$,&min_x,&max_x,&min_y,&max_y);
QueInit(&peasant_root);
for (i=0;i<NUM_PEASANTS;i++) {
tempp=MAlloc(sizeof(Peasant));
tempp->x=RandU16%(w-2*BORDER-(max_x-min_x+1))+BORDER-min_x;
tempp->y=RandU16%(h-2*BORDER-(max_y-min_y+1))+BORDER-min_y;
tempp->é=ã*2*Rand;
tempp->door_opened_t0=0;
tempp->stopped=FALSE;
QueIns(tempp,peasant_root.last);
}
king_x=w/2;
king_y=h/2;
king_é=-ã/2;
door_open_t0=0;
t0=tP;
tf=0;
}
U0 CleanUp()
{
QueDel(&peasant_root,TRUE);
QueDel(&step_root,TRUE);
QueDel(&king_step_root,TRUE);
}
U0 Follow(CTask *task,Peasant *tempp)
{
Step *temps=king_step_root.next;
F64 d,best_d=MAX_F64;
while (temps!=&king_step_root) {
if ((d=Sqr(temps->x-tempp->x)+Sqr(temps->y-tempp->y)) &&
d<15*15) {
d+=1000*Sqr(tP(task)-temps->t0);
if (d<best_d) {
best_d=d;
tempp->é=Arg(temps->x-tempp->x,temps->y-tempp->y);
}
}
temps=temps->next;
}
}
U0 AnimateTask(I64)
{//preempt off by default after Spawned
Step *temps,*temps1;
Peasant *tempp;
I64 i,animate_cnt=0,w,h;
while (TRUE) {
w=Fs->parent_task->win_pixel_width;
h=Fs->parent_task->win_pixel_height;
temps=step_root.next;
while (temps!=&step_root) {
temps1=temps->next;
if (tP(Fs->parent_task)-temps->t0>4.0) {
QueRem(temps);
Free(temps);
}
temps=temps1;
}
temps=king_step_root.next;
while (temps!=&king_step_root) {
temps1=temps->next;
if (tP(Fs->parent_task)-temps->t0>4.0) {
QueRem(temps);
Free(temps);
}
temps=temps1;
}
not_stopped_cnt=0;
tempp=peasant_root.next;
while (tempp!=&peasant_root) {
if (tempp->stopped) {
if (tempp->door_opened_t0 && tP(Fs->parent_task)>tempp->door_opened_t0+1.0) {
tempp->door_opened_t0=0;
tempp->y=tempp->x=-9999;
}
} else {
if (Sqr(tempp->x-w/2)+Sqr(tempp->y-h/2)<20*20) {
tempp->stopped=TRUE;
tempp->door_opened_t0=door_open_t0=tP(Fs->parent_task);
}
for (i=0;i<NUM_TREES;i++) //Hang-out by fire
if (trees[i].fire_frame_index && Sqr(tempp->x-trees[i].x)+Sqr(tempp->y-trees[i].y)<20*20) {
tempp->stopped=TRUE;
break;
}
if (!tempp->stopped) {
Follow(Fs->parent_task,tempp);
tempp->x+=Cos(tempp->é)/100;
tempp->y+=Sin(tempp->é)/100;
if (!(BORDER/2<=tempp->x<w-BORDER/2) || !(BORDER/2<=tempp->y<h-BORDER/2)) {
tempp->é+=ã;
tempp->x+=3*Cos(tempp->é)/100;
tempp->y+=3*Sin(tempp->é)/100;
}
if (!(animate_cnt&511))
StepNew(Fs->parent_task,tempp->x,tempp->y,tempp->é,FALSE);
not_stopped_cnt++;
}
}
tempp=tempp->next;
}
if (!not_stopped_cnt && !tf) {
tf=tP(Fs->parent_task);
music_mute=TRUE;
Snd(2000);Sleep(200);Snd(0);Sleep(100);
if (tf-t0<best_score) {
best_score=tf-t0;
Snd(2000);Sleep(200);Snd(0);Sleep(100);
}
music_mute=FALSE;
}
snow_x+=RandU16%3-1;
snow_y+=1-SignI64(RandU16&3);
Sleep(1);
animate_cnt++;
}
}
U0 BurnTrees()
{
I64 i;
for (i=0;i<NUM_TREES;i++)
if (Sqr(king_x-trees[i].x)+Sqr(king_y-trees[i].y)<10*10)
trees[i].fire_frame_index=1;
}
U0 SongTask(I64)
{
Fs->task_end_cb=&SndTaskEndCB;
MusicSettingsRst;
music_tempo= 2.480;
music_stacatto_factor= 0.902;
while (TRUE) {
Play("W13eCCCDCC2qG3eA2G3ABqCC");
Play("eCCCDCC2qG3eA2G3ABqCC");
Play("eGFEDEDqCeA2G3ABqCC");
}
}
U0 Wenceslas()
{
I64 sc;
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" Restart(,CH_NEW_LINE);"
" BurnTree(,CH_SPACE);"
" Up(,,SC_CURSOR_UP);"
" Down(,,SC_CURSOR_DOWN);"
" Left(,,SC_CURSOR_LEFT);"
" Right(,,SC_CURSOR_RIGHT);"
"}"
);
SettingsPush; //See $LK,"SettingsPush","MN:SettingsPush"$
WinMax;
Preempt(OFF);
Fs->song_task=Spawn(&SongTask,NULL,"Song",Fs);
PopUpOk("
Good King Wenceslas looked out
On the feast of Stephen
When the snow lay round about
Deep and crisp and even
Brightly shone the moon that night
Though the frost was cruel
When a poor man came in sight
Gath'ring winter fuel
\"Hither, page, and stand by me
If thou know'st it, telling
Yonder peasant, who is he?
Where and what his dwelling?\"
\"Sire, he lives a good league hence
Underneath the mountain
Right against the forest fence
By Saint Agnes' fountain.\"
\"Bring me flesh and bring me wine
Bring me pine logs hither
Thou and I will see him dine
When we bear him thither.\"
Page and monarch forth they went
Forth they went together
Through the rude wind's wild lament
And the bitter weather
");
PopUpOk("
\"Sire, the night is darker now
And the wind blows stronger
Fails my heart, I know not how,
I can go no longer.\"
\"Mark my footsteps, my good page
Tread thou in them boldly
Thou shalt find the winter's rage
Freeze thy blood less coldly.\"
In his master's steps he trod
Where the snow lay dinted
Heat was in the very sod
Which the Saint had printed
Therefore, Christian men, be sure
Wealth or rank possessing
Ye who now will bless the poor
Shall yourselves find blessing
");
PopUpOk("
$$FG,PURPLE$$$$TX+CX,\"Winceslas Game\"$$$$FG$$
Start fires by pressing $$FG,GREEN$$<SPACE BAR>$$FG$$
on trees. (Yule logs)
Lead peasants to fires.
");
Init;
Fs->animate_task=Spawn(&AnimateTask,NULL,"Animate",Fs);
WordStat;
DocCursor;
DocClear;
Fs->draw_it=&DrawIt;
try {
while (TRUE) {
switch (GetKey(&sc)) {
case CH_NEW_LINE:
CleanUp;
Init;
break;
case CH_ESC:
case CH_SHIFT_ESC:
goto ws_done;
case CH_SPACE:
BurnTrees;
break;
case 0:
switch (sc.u8[0]) {
case SC_CURSOR_RIGHT:
if (king_x+KING_STEP<Fs->win_pixel_width-BORDER)
king_x+=KING_STEP;
king_é=0;
StepNew(Fs,king_x,king_y,king_é,TRUE);
break;
case SC_CURSOR_LEFT:
if (king_x-KING_STEP>=BORDER)
king_x-=KING_STEP;
king_é=ã;
StepNew(Fs,king_x,king_y,king_é,TRUE);
break;
case SC_CURSOR_DOWN:
if (king_y+KING_STEP<Fs->win_pixel_height-BORDER)
king_y+=KING_STEP;
king_é=-ã/2;
StepNew(Fs,king_x,king_y,king_é,TRUE);
break;
case SC_CURSOR_UP:
if (king_y-KING_STEP>=BORDER)
king_y-=KING_STEP;
king_é=ã/2;
StepNew(Fs,king_x,king_y,king_é,TRUE);
break;
}
}
}
ws_done:
} catch
CatchAll;
SettingsPop;
MenuPop;
CleanUp;
AcctRegWriteBranch("SparrowOS/Wenceslas","F64 best_score=%5.4f;\n",best_score);
}
Wenceslas;
yþÿÿÿÚÿÿÿÊÿÿÿþÿÿÿÚÿÿÿ äÿÿÿÖÿÿÿ
ÐÿÿÿúÿÿÿÖÿÿÿôÿÿÿìÿÿÿüÿÿÿØÿÿÿúÿÿÿðÿÿÿüÿÿÿðÿÿÿÖÿÿÿüÿÿÿÔÿÿÿòÿÿÿæÿÿÿÒÿÿÿöÿÿÿÂÿÿÿþÿÿÿÔÿÿÿòÿÿÿ¼ÿÿÿþÿÿÿÎÿÿÿ ¼ÿÿÿþÿÿÿÔÿÿÿÊÿÿÿþÿÿÿØÿÿÿäÿÿÿÚÿÿÿÀÿÿÿþÿÿÿÎÿÿÿ´ÿÿÿÊÿÿÿªÿÿÿÿÿÿøÿÿÿÈÿÿÿ²ÿÿÿ¬ÿÿÿÆÿÿÿ
ÿÿÿÌÿÿÿ ÌÿÿÿüÿÿÿÔÿÿÿèÿÿÿÚÿÿÿÖÿÿÿ* ðÿÿÿüÿÿÿðÿÿÿðÿÿÿèÿÿÿþÿÿÿòÿÿÿüÿÿÿæÿÿÿþÿÿÿæÿÿÿàÿÿÿþÿÿÿèÿÿÿüÿÿÿòÿÿÿæÿÿÿðÿÿÿþÿÿÿâÿÿÿàÿÿÿàÿÿÿÞÿÿÿÞÿÿÿâÿÿÿÞÿÿÿÞÿÿÿýÿÿÿäÿÿÿâÿÿÿþÿÿÿäÿÿÿüÿÿÿèÿÿÿüÿÿÿèÿÿÿüÿÿÿòÿÿÿäÿÿÿêÿÿÿæÿÿÿþÿÿÿîÿÿÿìÿÿÿòÿÿÿxþÿÿÿèÿÿÿüÿÿÿòÿÿÿðÿÿÿèÿÿÿðÿÿÿüÿÿÿðÿÿÿþÿÿÿòÿÿÿüÿÿÿæÿÿÿþÿÿÿæÿÿÿàÿÿÿæÿÿÿðÿÿÿãöÿÿÿðÿÿÿøÿÿÿ
ôÿÿÿðÿÿÿòÿÿÿîÿÿÿêÿÿÿ öÿÿÿæÿÿÿúÿÿÿæÿÿÿöÿÿÿèÿÿÿøÿÿÿæÿÿÿæÿÿÿøÿÿÿîÿÿÿþÿÿÿòÿÿÿ  þÿÿÿöÿÿÿôÿÿÿîÿÿÿðÿÿÿðÿÿÿþÿÿÿ üÿÿÿþÿÿÿäÿÿÿþÿÿÿäÿÿÿîÿÿÿäÿÿÿöÿÿÿöÿÿÿöÿÿÿðÿÿÿøÿÿÿüÿÿÿüÿÿÿðÿÿÿ
ðÿÿÿøÿÿÿúÿÿÿþÿÿÿúÿÿÿúÿÿÿðÿÿÿüÿÿÿúÿÿÿ
üÿÿÿüÿÿÿøÿÿÿúÿÿÿøÿÿÿúÿÿÿðÿÿÿòÿÿÿìÿÿÿôöÿÿÿðÿÿÿøÿÿÿ
ôÿÿÿðÿÿÿòÿÿÿîÿÿÿêÿÿÿ öÿÿÿæÿÿÿúÿÿÿæÿÿÿöÿÿÿèÿÿÿøÿÿÿæÿÿÿæÿÿÿøÿÿÿîÿÿÿþÿÿÿòÿÿÿ  þÿÿÿöÿÿÿôÿÿÿîÿÿÿäÿÿÿúÿÿÿâÿÿÿúÿÿÿèÿÿÿúÿÿÿöÿÿÿòÿÿÿîÿÿÿöÿÿÿúÿÿÿöÿÿÿøÿÿÿðÿÿÿöÿÿÿäÿÿÿôÿÿÿôÿÿÿüÿÿÿêÿÿÿþÿÿÿþÿÿÿüÿÿÿôÿÿÿ ôÿÿÿöÿÿÿòÿÿÿâÿÿÿþÿÿÿúÿÿÿöÿÿÿòÿÿÿüÿÿÿøÿÿÿðÿÿÿøÿÿÿ
ôÿÿÿ
üÿÿÿJ³±»ÿÿÿfÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿLine truncated
+173
View File
@@ -0,0 +1,173 @@
#define NUM_BALLS 7
#define NUM_SPRINGS 3
#define STRETCH 500.0
#define GRAVITY 50.0 //not really gravity
#define BALL_RADIUS 5
#define BASE_SIZE 10
CMass balls[NUM_BALLS];
CSpring springs[NUM_SPRINGS];
F64 collision_t;
U0 DrawIt(CTask *task,CDC *dc)
{
I64 i,
cx=task->win_pixel_width>>1,
cy=task->win_pixel_height>>1;
Bool snd_on=FALSE;
dc->color=BLACK;
GrPutS(dc,0,0,"Protect your base.");
GrRect(dc,cx-BASE_SIZE,cy-BASE_SIZE,BASE_SIZE*2,BASE_SIZE*2);
dc->color=CYAN;
GrRect(dc,cx-BASE_SIZE+2,cy-BASE_SIZE+2,BASE_SIZE*2-4,BASE_SIZE*2-4);
dc->color=YELLOW;
GrLine(dc,balls[0].x,balls[0].y,
ipx-task->win_pixel_left-task->win_scroll_x,
ipy-task->win_pixel_top-task->win_scroll_y);
for (i=0;i<NUM_SPRINGS;i++)
GrLine(dc,springs[i].end1->x,springs[i].end1->y,
springs[i].end2->x,springs[i].end2->y);
dc->color=LTCYAN;
GrCircle(dc,balls[0].x,balls[0].y,BALL_RADIUS);
GrFloodFill(dc,balls[0].x,balls[0].y,TRUE);
dc->color=BLACK;
GrCircle(dc,balls[0].x,balls[0].y,BALL_RADIUS);
for (i=1;i<NUM_BALLS;i++) {
dc->color=LTPURPLE;
GrCircle(dc,balls[i].x,balls[i].y,BALL_RADIUS);
GrFloodFill(dc,balls[i].x,balls[i].y,TRUE);
if (cx-BASE_SIZE-BALL_RADIUS<=balls[i].x<=cx+BASE_SIZE+BALL_RADIUS &&
cy-BASE_SIZE-BALL_RADIUS<=balls[i].y<=cy+BASE_SIZE+BALL_RADIUS)
snd_on=TRUE;
dc->color=BLACK;
GrCircle(dc,balls[i].x,balls[i].y,BALL_RADIUS);
}
if (snd_on)
Snd(1000);
else
Snd(0);
}
U0 MyDerivative(CMathODE *ode,F64 t,COrder2D3 *,COrder2D3 *)
{
I64 i,j;
F64 d,dd;
CD3 p,p2;
CTask *task=ode->win_task;
D3SubEqu(D3Equ(&p2,ipx-task->win_pixel_left-task->win_scroll_x,ipy-task->win_pixel_top-task->win_scroll_y,0),
&balls[0].state->x);
D3AddEqu(&balls[0].DstateDt->DxDt,D3MulEqu(&p2,STRETCH));
D3Equ(&p2,task->win_pixel_width>>1,task->win_pixel_height>>1,0);
for (i=1;i<NUM_BALLS;i++) {
D3Sub(&p2,&balls[i].state->x,&p);
if (d=D3Norm(&p)) {
//Gravity would be /(d*d*d), but that's too exponential.
D3MulEqu(&p,GRAVITY/d);
D3AddEqu(&balls[i].DstateDt->DxDt,&p);
}
}
for (i=0;i<NUM_BALLS;i++)
for (j=i+1;j<NUM_BALLS;j++) {
D3Sub(&balls[j].state->x,&balls[i].state->x,&p);
dd=D3SqrNorm(&p);
if (dd<=(2*BALL_RADIUS)*(2*BALL_RADIUS)) {
if (t-collision_t>0.05) {
Noise(50,5000,6000);
collision_t=t;
}
d=Sqrt(dd)+0.0001;
dd=10.0*Sqr(Sqr((2*BALL_RADIUS)*(2*BALL_RADIUS)-dd));
D3MulEqu(&p,dd/d);
D3AddEqu(&balls[j].DstateDt->DxDt,&p);
D3SubEqu(&balls[i].DstateDt->DxDt,&p);
}
}
d=balls[0].state->x;
if (d-BALL_RADIUS<0)
balls[0].DstateDt->DxDt+=Sqr(Sqr(Sqr(d-BALL_RADIUS)));
if (d+BALL_RADIUS>task->win_pixel_width)
balls[0].DstateDt->DxDt-=Sqr(Sqr(Sqr((d+BALL_RADIUS)-task->win_pixel_width)));
d=balls[0].state->y;
if (d-BALL_RADIUS<0)
balls[0].DstateDt->DyDt+=Sqr(Sqr(Sqr(d-BALL_RADIUS)));
if (d+BALL_RADIUS>task->win_pixel_height)
balls[0].DstateDt->DyDt-=Sqr(Sqr(Sqr((d+BALL_RADIUS)-task->win_pixel_height)));
}
U0 Whap()
{
I64 i;
CMathODE *ode=ODENew(0,1e-2,ODEF_HAS_MASSES);
SettingsPush; //See $LK,"SettingsPush","MN:SettingsPush"$
WinMax;
WordStat;
Preempt(OFF);
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
);
ode->derivative=&MyDerivative;
ode->drag_v2=0.002;
ode->drag_v3=0.00001;
ode->acceleration_limit=5e3;
MemSet(balls,0,NUM_BALLS*sizeof(CMass));
D3Equ(&balls[0].x,100,100,0);
for (i=1;i<NUM_BALLS;i++)
D3Equ(&balls[i].x,
RandI16%500+Fs->win_pixel_width>>1,RandI16%500+Fs->win_pixel_height>>1,0);
balls[0].x=ipx-Fs->win_pixel_left-Fs->win_scroll_x;
balls[0].y=ipy-Fs->win_pixel_top-Fs->win_scroll_y;
for (i=0;i<NUM_BALLS;i++) {
balls[i].mass=1.0;
balls[i].drag_profile_factor=1.0;
QueIns(&balls[i],ode->last_mass);
}
balls[2].x=balls[1].x+15;
balls[2].y=balls[1].y;
balls[3].x=balls[1].x;
balls[3].y=balls[1].y+15;
MemSet(springs,0,NUM_SPRINGS*sizeof(CSpring));
springs[0].end1=&balls[1];
springs[0].end2=&balls[2];
springs[0].rest_len=15;
springs[0].constant=10000;
QueIns(&springs[0],ode->last_spring);
springs[1].end1=&balls[1];
springs[1].end2=&balls[3];
springs[1].rest_len=15;
springs[1].constant=10000;
QueIns(&springs[1],ode->last_spring);
springs[2].end1=&balls[2];
springs[2].end2=&balls[3];
springs[2].rest_len=sqrt2*15;
springs[2].constant=10000;
QueIns(&springs[2],ode->last_spring);
collision_t=0;
QueIns(ode,Fs->last_ode);
DocCursor;
DocClear;
Fs->draw_it=&DrawIt;
GetChar;
SettingsPop;
QueRem(ode);
ODEDel(ode);
MenuPop;
}
Whap;
Binary file not shown.
Binary file not shown.