Files
TempleOS-Rijn/LT/Demo/GameStarters/FlightSim.CPZ
T
2018-09-08 21:45:20 +02:00

349 lines
7.4 KiB
Plaintext

//$FG,4$You probably want to avoid
$FG$//$FG,4$three dimensional graphics because
$FG$//$FG,4$support is not very good. There
$FG$//$FG,4$is no support for hidden surface
$FG$//$FG,4$removal.$FG$
#define MAP_WIDTH 1024
#define MAP_HEIGHT 1024
#define MAP_SCALE 20
#define FORSHORTENING 100
#define CONTROLS_SCALE 0.05
#define COORDINATE_SCALE 256
#define COORDINATE_BITS 8
I2 elevations[MAP_HEIGHT][MAP_WIDTH];
double
phi =-45.0*pi/180.0,
theta1= 0.0*pi/180.0,
theta2= 0.0*pi/180.0,
speed = 0.2;
I8 x=MAP_WIDTH>>1 *COORDINATE_SCALE*MAP_SCALE,
y=MAP_HEIGHT>>1*COORDINATE_SCALE*MAP_SCALE,
z=64 *COORDINATE_SCALE*MAP_SCALE;
double grid_size=64.0;
class MPCtrl {
double phi,theta1,theta2,grid_size;
I8 x,y,z;
BoolU4 update,done;
TssStruct *win_tss;
};
MPCtrl *mp;
void InitMap()
{
I8 i,j,k1,k2,x,y,xx,yy;
MemSet(elevations,0,sizeof(elevations));
for (i=0;i<10000;i++) {
x=RandU4%MAP_WIDTH;
y=RandU4%MAP_HEIGHT;
j=1<<(RandU4%6);
for (k1=-j;k1<=j;k1++)
for (k2=-j;k2<=j;k2++) {
xx=x+k2; yy=y+k1;
if (xx>=0 && xx<MAP_WIDTH &&
yy>=0 && yy<MAP_HEIGHT)
elevations[yy][xx]+=AbsI8(j-k1)+AbsI8(j-k2);
}
}
xx=x/MAP_SCALE/COORDINATE_SCALE;
yy=y/MAP_SCALE/COORDINATE_SCALE;
z+=elevations[yy][xx]*COORDINATE_SCALE;
}
void DrawIt(TssStruct *tss)
{
I8 i,j,*r1,*r2,*r3,*r4,*r,x1,y1,z1,x2,y2,z2,xx,yy,grid_s,
cx=(tss->win_pixel_right-tss->win_pixel_left)>>1,
cy=(tss->win_pixel_bottom-tss->win_pixel_top)>>1,height;
double d;
GrBitMap *base=GrAlias(grbase2,tss);
I1 buf[128];
BoolU4 first;
//Adjust grid size to utilize whole CPU power
d=1.05*win_refresh/win_max_refresh;
if (d>1.5) d=1.5;
if (d<0.666666) d=0.666666;
grid_size*=0.975+0.025*d;
if (grid_size<10.0)
grid_size=10.0;
grid_s=grid_size;
//Pass stuff to other CPU
mp->phi=phi;
mp->theta1=theta1;
mp->theta2=theta2;
mp->x=x;
mp->y=y;
mp->z=z;
mp->update=TRUE;
mp->grid_size=grid_size;
xx=x/MAP_SCALE/COORDINATE_SCALE;
yy=y/MAP_SCALE/COORDINATE_SCALE;
height=z/COORDINATE_SCALE-elevations[yy][xx];
if (height<0)
Sound(1000); //Signal plane crashed
base->color=BLACK;
ClearWinText(tss);
SPrintF(buf,"Theta1:%5.1f Phi:%5.1f Theta2:%5.1f Box:%5.1f",
theta1*180/pi,phi*180/pi,theta2*180/pi,grid_size);
GrText(base,0,0,buf);
SPrintF(buf,"x:%5.1f y:%5.1f z:%5.1f height:%3d",
x*1.0/COORDINATE_SCALE,y*1.0/COORDINATE_SCALE,z*1.0/COORDINATE_SCALE,
height);
GrText(base,0,FONT_HEIGHT,buf);
//World to screen coordinates
r1=GrTheta(theta1);
r2=GrPhi(phi);
r3=GrTheta(theta2);
r4=GrMulMat(r1,r2);
r=GrMulMat(r4,r3);
Free(r1);
Free(r2);
Free(r3);
Free(r4);
base->pen_width=2;
base->color=BLACK;
GrLine3(base,cx+5,cy,0,cx-5,cy,0);
GrLine3(base,cx,cy+5,0,cx,cy-5,0);
base->color=GREEN;
x2=0;y2=0;z2=0;
for (i=yy-grid_s;i<yy+grid_s;i++) {
if (i>=0 && i<MAP_HEIGHT) {
first=TRUE;
for (j=xx-grid_s;j<xx+grid_s;j++) {
if (j>=0 && j<MAP_WIDTH) {
x1=j*MAP_SCALE-x>>COORDINATE_BITS;
y1=i*MAP_SCALE-y>>COORDINATE_BITS;
z1=elevations[i][j]-z>>COORDINATE_BITS;
GrRotate(r,&x1,&y1,&z1);
if (z1<0) {
z1=AbsI8(z1)+FORSHORTENING;
x1=x1*FORSHORTENING/z1;
y1=y1*FORSHORTENING/z1;
if (!first)
GrLine(base,x1+cx,cy-y1,x2+cx,cy-y2);
}
x2=x1;y2=y1;z2=z1;
first=FALSE;
}
}
}
}
Free(r);
GrDel(base);
}
void MPDrawIt(MPCtrl *mp)
{
TssStruct *tss=mp->win_tss;
I8 i,j,*r1,*r2,*r3,*r4,*r,x1,y1,z1,x2,y2,z2,xx,yy,
cx=(tss->win_pixel_right-tss->win_pixel_left)>>1,
cy=(tss->win_pixel_bottom-tss->win_pixel_top)>>1;
GrBitMap *base=GrAlias(Gs->grbase,Fs);
BoolU4 first;
I8 x=mp->x,y=mp->y,z=mp->z,grid_s=mp->grid_size;
base->win_tss=tss;
xx=x/MAP_SCALE/COORDINATE_SCALE;
yy=y/MAP_SCALE/COORDINATE_SCALE;
//World to screen coordinates
r1=GrTheta(mp->theta1);
r2=GrPhi(mp->phi);
r3=GrTheta(mp->theta2);
r4=GrMulMat(r1,r2);
r=GrMulMat(r4,r3);
Free(r1);
Free(r2);
Free(r3);
Free(r4);
GrClear(base);
base->color=GREEN^WHITE;
x2=0;y2=0;z2=0;
for (j=xx-grid_s;j<xx+grid_s;j++) {
if (j>=0 && j<MAP_WIDTH) {
first=TRUE;
for (i=yy-grid_s;i<yy+grid_s;i++) {
if (i>=0 && i<MAP_HEIGHT) {
x1=j*MAP_SCALE-x>>COORDINATE_BITS;
y1=i*MAP_SCALE-y>>COORDINATE_BITS;
z1=elevations[i][j]-z>>COORDINATE_BITS;
GrRotate(r,&x1,&y1,&z1);
if (z1<0) {
z1=AbsI8(z1)+FORSHORTENING;
x1=x1*FORSHORTENING/z1;
y1=y1*FORSHORTENING/z1;
if (!first)
GrLine(base,x1+cx,cy-y1,x2+cx,cy-y2);
}
x2=x1;y2=y1;z2=z1;
first=FALSE;
}
}
}
}
Free(r);
GrDel(base);
}
void MPFSim()
{
while (!mp->done) {
while (!mp->update && !mp->done)
SwapInNext;
MPDrawIt(mp);
mp->update=FALSE;
}
GrClear(Gs->grbase);
mp->done=FALSE;
}
void AnimateTsk()
{
I8 *r1,*r2,*r3,*r4,*r,x1,y1,z1;
while (TRUE) {
//Screen to world coordinates
r1=GrTheta(-theta2);
r2=GrPhi(-phi);
r3=GrTheta(-theta1);
r4=GrMulMat(r1,r2);
r=GrMulMat(r4,r3);
x1=0;y1=0;z1=-1.0*speed*COORDINATE_SCALE;
GrRotate(r,&x1,&y1,&z1);
x+=x1;
y+=y1;
z+=z1;
Free(r1);
Free(r2);
Free(r3);
Free(r4);
Free(r);
Sleep(1);
}
}
void SongEndTsk()
{
Sound(0);
Exit;
}
void SongTsk()
{
Fs->end_task_cb=&SongEndTsk;
ResetMusicSettings;
while (TRUE) {
Play("3etDCDqDetABFsFBFBqC2G3BeDF");
Play("etDCDqDetABFsFBFBqC2G3BeDF");
Play("qReFDqDeF2GqR3sABABqFetREA");
Play("qReFDqDeF2GqR3sABABqFetREA");
}
}
void EndFSim()
{
mp->done=TRUE;
while (mp->done)
SwapInNext;
FreeHC(mp,mp_heap);
}
void EndFSimCB()
{
//We need this to shut-down CPU#1 task
//in case of CPU0 task getting terminated
//irregularly.
EndFSim;
Exit;
}
void FlightSim()
{
I8 ch,sc;
double pp,tt1,tt2;
void *old_update=Fs->update_win;
TssStruct *animate_tss,song_tss;
BoolU4 old_border=WinBorder(OFF);
BoolU4 old_wordstat=WordStat(OFF);
//Set callback for irregular aborts
Fs->end_task_cb=&EndFSimCB;
WinMax;
InitMap;
Fs->update_win=&DrawIt;
animate_tss=Spawn(&AnimateTsk,"FlightSim Animate",Fs);
song_tss=Spawn(&SongTsk,"FlightSim Song",Fs);
//This heap is uncached
mp=MAllocHCZ(sizeof(MPCtrl),mp_heap);
WbInvd; //Write mp out of cache
mp->win_tss=Fs;
if (mp_cnt>1)
MPQueueJob(&MPFSim,NULL,1<<MPCf_FREE_ON_COMPLETE,TRUE);
try
do {
ch=GetKey(&sc);
pp=phi; tt1=theta1; tt2=theta2;
switch (ch) {
case 0:
switch (sc.u1[0]) {
case SC_CURSOR_DOWN:
phi +=-CONTROLS_SCALE*Cos(tt1);
theta2+=-CONTROLS_SCALE*Sin(tt1)*Sin(phi);
break;
case SC_CURSOR_UP:
phi -=-CONTROLS_SCALE*Cos(tt1);
theta2-=-CONTROLS_SCALE*Sin(tt1)*Sin(phi);
break;
case SC_CURSOR_RIGHT:
theta1+=CONTROLS_SCALE;
break;
case SC_CURSOR_LEFT:
theta1-=CONTROLS_SCALE;
break;
}
break;
}
theta1=Unwrap(theta1);
phi =Unwrap(phi);
theta2=Unwrap(theta2);
} while (ch!=CH_CTRLQ && ch!=CH_ESC);
catch
Fs->catch_except=TRUE;
Kill(animate_tss);
Kill(song_tss);
Fs->update_win=old_update;
Fs->end_task_cb=NULL;
WinBorder(old_border);
WordStat(old_wordstat);
EndFSim;
}
FlightSim;