hschumann2/TempleOS-Source-Code
0847
1 2 3 4 5 6 7 <1>/* Graphics Not Rendered in HTML */8 9 10 11 <2>/* Graphics Not Rendered in HTML */12 13 14 15 16 17 18 19 <3>/* Graphics Not Rendered in HTML */20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <4>/* Graphics Not Rendered in HTML */41 42 43 44 45 46 47 48 49 50 <5>/* Graphics Not Rendered in HTML */51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 <6>/* Graphics Not Rendered in HTML */79 80 81 82 83 84 85 86 87 88 89 90 91RegDft("TempleOS/Varoom","F64 best_score=9999;\n");92RegExe("TempleOS/Varoom");93 94F64 distance,t0,tf;95Bool game_over;96 97#define BORDER 750098#define RADIUS 1000099#define WIDTH 2000100#define SHOULDER 200101#define D_theta (2*pi/360) //Curve track slice is one degree.102#define D_S (2*pi*RADIUS/360) //Straight track is degree at 10000.103#define DIPS 5104#define DIP_DEPTH 50105class Track106{107 Track *next,*last;108 I32 num;109 CColorROPU16 c,pad;110 I64 x,z;111 F64 theta,d;112 CD3I32 left[4],center[4],right[4];113} track_head,114 *track_start[MP_PROCESSORS_NUM],*track_end[MP_PROCESSORS_NUM];115 116CDC *track_map;117#define MAP_BITS 9118I64 t_minx,t_maxx,t_minz,t_maxz;119 120#define BUSHES_NUM 512121class Bush122{123 CD3I32 p;124 Bool sym,pad[3];125 U8 *img;126} b[BUSHES_NUM];127 128#define CARS_NUM 8129class Car130{131 CD3I32 p;132 F64 theta,dtheta,speed;133 U8 *img;134 Track *t;135} c[CARS_NUM];136 137I64 DipY(I64 x,I64 z)138{139 F64 m,a;140 R2P(&m,&a,x,z);141 return DIP_DEPTH*m*Cos(DIPS*a)/RADIUS;142}143 144#define CAR_LENGTH 400145 146F64 Diptheta(I64 x,I64 z,F64 theta)147{148 F64 y_front,y_back;149 y_front=DipY(x-CAR_LENGTH/2*Cos(theta),z-CAR_LENGTH/2*Sin(theta));150 y_back =DipY(x+CAR_LENGTH/2*Cos(theta),z+CAR_LENGTH/2*Sin(theta));151 return ASin((y_front-y_back)/CAR_LENGTH);152}153 154Track *TrackFind(Track *_tmpt,I64 x,I64 z)155{156 Track *res=_tmpt,*tmpt;157 I64 dd,best=SqrI64(res->x-x)+SqrI64(res->z-z);158 159 tmpt=_tmpt;160 while (TRUE) {161 tmpt=tmpt->next;162 if (tmpt==&track_head)163 tmpt=tmpt->next;164 dd=SqrI64(tmpt->x-x)+SqrI64(tmpt->z-z);165 if (dd<best) {166 best=dd;167 res=tmpt;168 } else169 break;170 }171 tmpt=_tmpt;172 while (TRUE) {173 tmpt=tmpt->last;174 if (tmpt==&track_head)175 tmpt=tmpt->last;176 dd=SqrI64(tmpt->x-x)+SqrI64(tmpt->z-z);177 if (dd<best) {178 best=dd;179 res=tmpt;180 } else181 break;182 }183 return res;184}185 186U0 TrackSlice(F64 *_x,F64 *_z,F64 theta,F64 d)187{188 F64 x=*_x,z=*_z,c=Cos(theta),s=Sin(theta),dx=d*s,dz=-d*c;189 Track *tmpt,*last=track_head.last;190 if (last==&track_head)191 last=NULL;192 193 tmpt=CAlloc(sizeof(Track));194 if (last) {195 MemCpy(&tmpt->center[0],&last->center[3],sizeof(CD3I32));196 MemCpy(&tmpt->center[1],&last->center[2],sizeof(CD3I32));197 }198 tmpt->center[2].x=x+(WIDTH/2)*c+dx;199 tmpt->center[2].z=z+(WIDTH/2)*s+dz;200 tmpt->center[2].y=DipY(tmpt->center[2].x,tmpt->center[2].z);201 tmpt->center[3].x=x-(WIDTH/2)*c+dx;202 tmpt->center[3].z=z-(WIDTH/2)*s+dz;203 tmpt->center[3].y=DipY(tmpt->center[3].x,tmpt->center[3].z);204 205 if (last) {206 MemCpy(&tmpt->left[0],&last->left[3],sizeof(CD3I32));207 MemCpy(&tmpt->left[1],&last->left[2],sizeof(CD3I32));208 }209 tmpt->left[2].x=x-(WIDTH/2)*c+dx;210 tmpt->left[2].z=z-(WIDTH/2)*s+dz;211 tmpt->left[2].y=DipY(tmpt->left[2].x,tmpt->left[2].z);212 tmpt->left[3].x=x-(WIDTH/2+SHOULDER)*c+dx;213 tmpt->left[3].z=z-(WIDTH/2+SHOULDER)*s+dz;214 tmpt->left[3].y=DipY(tmpt->left[3].x,tmpt->left[3].z);215 216 if (last) {217 MemCpy(&tmpt->right[0],&last->right[3],sizeof(CD3I32));218 MemCpy(&tmpt->right[1],&last->right[2],sizeof(CD3I32));219 }220 tmpt->right[2].x=x+(WIDTH/2+SHOULDER)*c+dx;221 tmpt->right[2].z=z+(WIDTH/2+SHOULDER)*s+dz;222 tmpt->right[2].y=DipY(tmpt->right[2].x,tmpt->right[2].z);223 tmpt->right[3].x=x+(WIDTH/2)*c+dx;224 tmpt->right[3].z=z+(WIDTH/2)*s+dz;225 tmpt->right[3].y=DipY(tmpt->right[3].x,tmpt->right[3].z);226 227 tmpt->x=x;228 tmpt->z=z;229 tmpt->theta=theta;230 tmpt->num=track_head.last->num+1;231 tmpt->d =track_head.last->d+d;232 233 QueIns(tmpt,track_head.last);234 235 if (tmpt->num&1)236 tmpt->c=RED;237 else238 tmpt->c=WHITE;239 240 if (x<t_minx) t_minx=x;241 if (x>t_maxx) t_maxx=x;242 if (z<t_minz) t_minz=z;243 if (z>t_maxz) t_maxz=z;244 245 x+=dx;246 *_x=x;247 z+=dz;248 *_z=z;249 250 if (x<t_minx) t_minx=x;251 if (x>t_maxx) t_maxx=x;252 if (z<t_minz) t_minz=z;253 if (z>t_maxz) t_maxz=z;254}255 256U0 CoupleEnds()257{258 Track *first=track_head.next,*last=track_head.last;259 MemCpy(&first->center[0],&last->center[3],sizeof(CD3I32));260 MemCpy(&first->center[1],&last->center[2],sizeof(CD3I32));261 MemCpy(&first->left[0] ,&last->left[3] ,sizeof(CD3I32));262 MemCpy(&first->left[1] ,&last->left[2] ,sizeof(CD3I32));263 MemCpy(&first->right[0] ,&last->right[3] ,sizeof(CD3I32));264 MemCpy(&first->right[1] ,&last->right[2] ,sizeof(CD3I32));265}266 267U0 InitTrack()268{269 I64 i,j;270 Track *tmpt;271 F64 x,z,theta,d;272 273 MemSet(&track_head,0,sizeof(Track));274 QueInit(&track_head);275 276 t_minx=t_minz=I64_MAX;277 t_maxx=t_maxz=I64_MIN;278 279 x=0; z=0; theta=0;280 for (d=0;d<6*RADIUS;d+=D_S)281 TrackSlice(&x,&z,theta,D_S);282 for (i=0;i<180;i++,theta+=D_theta)283 TrackSlice(&x,&z,theta,D_theta*RADIUS);284 for (d=0;d<RADIUS;d+=D_S)285 TrackSlice(&x,&z,theta,D_S);286 for (i=0;i<90;i++,theta-=D_theta)287 TrackSlice(&x,&z,theta,D_theta*RADIUS);288 for (i=0;i<180;i++,theta+=D_theta)289 TrackSlice(&x,&z,theta,D_theta*RADIUS);290 for (i=0;i<90;i++,theta-=D_theta)291 TrackSlice(&x,&z,theta,D_theta*RADIUS);292 for (d=0;d<RADIUS;d+=D_S)293 TrackSlice(&x,&z,theta,D_S);294 for (i=0;i<180;i++,theta+=D_theta)295 TrackSlice(&x,&z,theta,D_theta*RADIUS);296 297 CoupleEnds;298 299 tmpt=track_head.next;300 for (i=0;i<mp_cnt;i++) {301 j=(i+1)*track_head.last->num/mp_cnt+1;302 track_start[i]=tmpt;303 while (tmpt!=&track_head && tmpt->num!=j)304 tmpt=tmpt->next;305 track_end[i]=tmpt;306 }307 308 t_minx-=BORDER; t_minz-=BORDER;309 t_maxx+=BORDER; t_maxz+=BORDER;310 track_map=DCNew((t_maxx-t_minx+1<<MAP_BITS-1)>>MAP_BITS,311 (t_maxz-t_minz+1<<MAP_BITS-1)>>MAP_BITS);312 313 track_map->color=LTGRAY;314 GrRect(track_map,0,0,track_map->width,track_map->height);315 tmpt=track_head.next;316 track_map->color=YELLOW;317 track_map->thick=3;318 while (tmpt!=&track_head) {319 GrPlot3(track_map,track_map->width-(tmpt->x-t_minx)>>MAP_BITS,320 (tmpt->z-t_minz)>>MAP_BITS,0);321 tmpt=tmpt->next;322 }323}324 325#define HORIZON_DIP 200326 327Bool PrepPoly(CD3I32 *p,I64 *r,I64 cx,I64 h,CD3I32 *poly)328{329 I64 x,y,z,i;330 F64 s;331 for (i=0;i<4;i++) {332 x=p[i].x-c[0].p.x;333 y=p[i].y-c[0].p.y;334 z=p[i].z-c[0].p.z;335 Mat4x4MulXYZ(r,&x,&y,&z);336 s=100.0/(AbsI64(z)+50);337 poly[i].y=s*y+h;338 if (z<-200 || !(-h<poly[i].y<2*h))339 return FALSE;340 poly[i].x=s*x+cx;341 poly[i].z=z+GR_Z_ALL;342 }343 return TRUE;344}345 346I64 mp_not_done_flags;347 348U0 MPUpdateWin(CDC *dc2)349{350 CTask *task=dc2->win_task;351 I64 i,x,y,z,352 w=task->pix_width,h=task->pix_height,r[16],cx=w>>1;353 F64 s,dip_theta=Diptheta(c[0].p.x,c[0].p.z,c[0].theta);354 Car *tmpc;355 CD3I32 poly[4];356 Track *tmpt,*tmpt1;357 CDC *dc=DCAlias(gr.dc2,task);358 359 Mat4x4IdentEqu(r);360 Mat4x4RotY(r,pi-c[0].theta);361 Mat4x4RotX(r,75*pi/180-dip_theta);362 363 dc->depth_buf=dc2->depth_buf;364 365 //Track366 tmpt =track_start[Gs->num];367 tmpt1=track_end [Gs->num];368 while (tmpt!=tmpt1) {369 dc->color=DKGRAY;370 if (PrepPoly(&tmpt->center,r,cx,h,poly)) {371 GrFillPoly3(dc,4,poly);372 dc->color=tmpt->c;373 if (PrepPoly(&tmpt->left,r,cx,h,poly))374 GrFillPoly3(dc,4,poly);375 if (PrepPoly(&tmpt->right,r,cx,h,poly))376 GrFillPoly3(dc,4,poly);377 }378 tmpt=tmpt->next;379 }380 381 dc->flags|=DCF_TRANSFORMATION;382 for (i=Gs->num;i<BUSHES_NUM;i+=mp_cnt) {383 x=b[i].p.x-c[0].p.x; y=b[i].p.y-c[0].p.y; z=b[i].p.z-c[0].p.z;384 Mat4x4MulXYZ(r,&x,&y,&z);385 if (z>0) {386 s=100.0/(AbsI64(z)+50);387 Mat4x4IdentEqu(dc->r);388 Mat4x4Scale(dc->r,s*2);389 DCMat4x4Set(dc,dc->r);390 if (b[i].sym) {391 dc->flags|=DCF_SYMMETRY|DCF_JUST_MIRROR;392 DCSymmetrySet(dc,s*x+cx,s*y+h,s*x+cx,s*y+h+10);393 }394 Sprite3B(dc,s*x+cx,s*y+h,z+GR_Z_ALL,b[i].img);395 dc->flags&=~(DCF_SYMMETRY|DCF_JUST_MIRROR);396 }397 }398 for (i=Gs->num+1;i<CARS_NUM;i+=mp_cnt) {399 tmpc=&c[i];400 x=tmpc->p.x-c[0].p.x; y=tmpc->p.y-c[0].p.y; z=tmpc->p.z-c[0].p.z;401 Mat4x4MulXYZ(r,&x,&y,&z);402 if (z>0) {403 s=100.0/(AbsI64(z)+50);404 Mat4x4IdentEqu(dc->r);405 Mat4x4Scale(dc->r,s*2);406 Mat4x4RotX(dc->r,Diptheta(tmpc->p.x,tmpc->p.z,-tmpc->theta));407 Mat4x4RotY(dc->r,tmpc->theta-c[0].theta);408 DCMat4x4Set(dc,dc->r);409 Sprite3B(dc,s*x+cx,s*y+h,z+GR_Z_ALL,tmpc->img);410 }411 }412 dc->depth_buf=NULL;413 DCDel(dc);414 LBtr(&mp_not_done_flags,Gs->num);415}416 417U0 VRTransform(CDC *dc,I64 *x,I64 *y,I64 *z)418{419 I64 zz;420 Mat4x4MulXYZ(dc->r,x,y,z);421 zz=400+*z;422 if (zz<1) zz=1;423 *x=400* *x/zz;424 *y=400* *y/zz;425 *x+=dc->x;426 *y+=dc->y;427 *z+=dc->z;428}429 430U0 DrawIt(CTask *task,CDC *dc)431{432 I64 i,x,y,z,433 w=task->pix_width,434 h=task->pix_height,r[16],435 cx=w>>1;436 F64 s,dip_theta=Diptheta(c[0].p.x,c[0].p.z,c[0].theta);437 Car *tmpc=&c[0];438 439 dc->color=LTCYAN;440 GrRect(dc,0,0,w,HORIZON_DIP*Sin(dip_theta)+FONT_HEIGHT*4.5);441 442 Mat4x4IdentEqu(r);443 Mat4x4RotY(r,pi-c[0].theta);444 Mat4x4RotX(r,75*pi/180-dip_theta);445 446 DCDepthBufAlloc(dc);447 448 //Sun449 x=c[0].p.x; y=0; z=1000000-c[0].p.z;450 Mat4x4MulXYZ(r,&x,&y,&z);451 s=100.0/(AbsI64(z)+50);452 if (y<0) {453 dc->color=BROWN;454 GrCircle(dc,s*x+cx,15+HORIZON_DIP*Sin(dip_theta),15);455 dc->color=YELLOW;456 GrFloodFill(dc,s*x+cx,15+HORIZON_DIP*Sin(dip_theta));457 }458 459 mp_not_done_flags=1<<mp_cnt-1;460 for (i=0;i<mp_cnt;i++)461 JobQue(&MPUpdateWin,dc,i);462 while (mp_not_done_flags)463 Yield;464 465 Mat4x4IdentEqu(r);466 Mat4x4RotY(r,tmpc->dtheta);467 Mat4x4RotX(r,0.4-8*dip_theta); //Made this up468 dc->transform=&VRTransform;469 dc->x=task->pix_width>>1;470 dc->y=task->pix_height-150;471 dc->z=GR_Z_ALL;472 Sprite3Mat4x4B(dc,0,0,-100,c[0].img,r);473 474 //Map475 GrBlot(dc,w-track_map->width,h-track_map->height,track_map);476 477 dc->thick=2;478 for (i=0;i<CARS_NUM;i++) {479 if (i)480 dc->color=LTPURPLE;481 else482 dc->color=LTCYAN;483 GrPlot3(dc,w-(c[i].p.x-t_minx)>>MAP_BITS,484 h-track_map->height+(c[i].p.z-t_minz)>>MAP_BITS,0);485 }486 487 if (game_over) {488 dc->color=LTRED;489 if (tf) {490 s=tf-t0;491 if (Blink)492 GrPrint(dc,(w-FONT_WIDTH*14)/2,(h-FONT_HEIGHT)/2,"Game Completed");493 } else {494 s=99.9;495 if (Blink)496 GrPrint(dc,(w-FONT_WIDTH*9)/2,(h-FONT_HEIGHT)/2,"Game Over");497 }498 } else499 s=tS-t0;500 dc->color=BLACK;501 GrPrint(dc,0,0,"%0.1f%% Time:%0.2f Best:%0.2f",502 100.0*distance/track_head.last->d,s,best_score);503}504 505U0 AnimateTask(I64)506{507 Car *tmpc;508 I64 i,x,z;509 Bool on_track;510 Track *tmpt,*tmpt2;511 while (TRUE) {512 if (!game_over)513 Snd(12.0*Log2(c[0].speed/500+0.7));514 else515 Snd;516 for (i=0;i<CARS_NUM;i++) {517 tmpc=&c[i];518 tmpc->p.x-=0.01*tmpc->speed*Cos(tmpc->theta-pi/2);519 tmpc->p.z+=0.01*tmpc->speed*Sin(tmpc->theta-pi/2);520 tmpt=TrackFind(tmpc->t,tmpc->p.x,tmpc->p.z);521 if (i) {522 if (tmpt!=tmpc->t) {523 tmpt2=tmpt->next;524 if (tmpt2==&track_head)525 tmpt2=tmpt2->next;526 tmpc->theta=Arg(-tmpt2->z+tmpc->p.z,-tmpt2->x+tmpc->p.x);527 }528 } else {529 tmpc->theta+=0.01*tmpc->dtheta;530 x=track_map->width-(tmpc->p.x-t_minx)>>MAP_BITS;531 z=(tmpc->p.z-t_minz)>>MAP_BITS;532 if (GrPeek(track_map,x,z)!=YELLOW) {533 on_track=FALSE;534 tmpc->speed-=0.01*tmpc->speed;535 if (tmpc->speed<0) tmpc->speed=0;536 } else537 on_track=TRUE;538 }539 tmpc->t=tmpt;540 tmpc->p.y=DipY(tmpc->p.x,tmpc->p.z);541 }542 if (!game_over && on_track) {543 for (i=1;i<CARS_NUM;i++)544 if (D3I32DistSqr(&c[i].p,&c[0].p)<CAR_LENGTH>>1*CAR_LENGTH>>1) {545 game_over=TRUE;546 Noise(500,22,34);547 Sleep(500);548 break;549 }550 if (!game_over) {551 distance+=0.01*c[0].speed;552 if (distance>track_head.last->d&& c[0].t->num<track_head.last->num>>1) {553 tf=tS;554 game_over=TRUE;555 Beep;556 if (tf-t0<best_score) {557 best_score=tf-t0;558 Beep;559 }560 }561 }562 }563 Sleep(10);564 }565}566 567U8 *imgs[8]={<1>,<1>,<2>,<2>,<3>,<4>,<4>,<4>};568 569 570U0 InitBushes()571{572 Bush *tmpb;573 I64 i,j,x,z;574 track_map->color=LTGREEN;575 track_map->thick=1;576 for (i=0;i<BUSHES_NUM;i++) {577 tmpb=&b[i];578 579ib_restart:580 tmpb->p.x=Rand*(t_maxx-t_minx)+t_minx;581 tmpb->p.z=Rand*(t_maxz-t_minz)+t_minz;582 x=track_map->width-(tmpb->p.x-t_minx)>>MAP_BITS;583 z=(tmpb->p.z-t_minz)>>MAP_BITS;584 for (j=0;j<8;j++)585 if (GrPeek(track_map,x+gr_x_offsets[j],z+gr_y_offsets[j])!=LTGRAY)586 goto ib_restart;587 588 GrPlot(track_map,x,z);589 tmpb->p.y=DipY(tmpb->p.x,tmpb->p.z);590 tmpb->sym=RandU16&1;591 tmpb->img=imgs[i&7];592 }593}594 595 596U0 Init()597{598 Car *tmpc;599 Track *tmpt;600 F64 d;601 I64 i;602 603 InitTrack;604 InitBushes;605 tmpt=track_head.next;606 for (i=0;i<CARS_NUM;i++) {607 tmpc=&c[i];608 tmpc->t=tmpt;609 tmpc->p.x=tmpt->x;610 tmpc->p.z=tmpt->z;611 tmpc->p.y=DipY(tmpc->p.x,tmpc->p.z);612 tmpc->theta =-tmpt->theta;613 tmpc->dtheta=0;614 if (!i) {615 tmpc->img=<5>;616 tmpc->speed=0;617 } else {618 tmpc->img=<6>;619 tmpc->speed=2500.0;620 }621 d=(i+1)*track_head.last->d/CARS_NUM;622 while (tmpt->next!=&track_head && tmpt->d<d)623 tmpt=tmpt->next;624 }625 distance=0;626 tf=0;627 t0=tS;628 game_over=FALSE;629}630 631U0 CleanUp()632{633 while (mp_not_done_flags)634 Yield;635 QueDel(&track_head,TRUE);636 DCDel(track_map);637}638 639U0 Varoom()640{641 I64 sc;642 MenuPush(643 "File {"644 " Abort(,CH_SHIFT_ESC);"645 " Exit(,CH_ESC);"646 "}"647 "Play {"648 " Restart(,'\n');"649 " Accelerator(,,SC_CURSOR_UP);"650 " Brake(,,SC_CURSOR_DOWN);"651 " Left(,,SC_CURSOR_LEFT);"652 " Right(,,SC_CURSOR_RIGHT);"653 "}"654 );655 SettingsPush; //See SettingsPush656 try {657 Fs->text_attr=YELLOW<<4+BLUE;658 Fs->win_inhibit=WIG_TASK_DFT-WIF_SELF_FOCUS659 -WIF_SELF_GRAB_SCROLL-WIF_FOCUS_TASK_MENU;660 AutoComplete;661 WinBorder;662 WinMax;663 DocCursor;664 DocClear;665 Init;666 Fs->draw_it=&DrawIt;667 Fs->animate_task=Spawn(&AnimateTask,NULL,"Animate",,Fs);668 while (TRUE)669 switch (GetKey(&sc)) {670 case 0:671 switch (sc.u8[0]) {672 case SC_CURSOR_LEFT:673 c[0].dtheta-=pi/60;674 break;675 case SC_CURSOR_RIGHT:676 c[0].dtheta+=pi/60;677 break;678 case SC_CURSOR_UP:679 c[0].speed+=300;680 break;681 case SC_CURSOR_DOWN:682 c[0].speed-=900;683 if (c[0].speed<0) c[0].speed=0;684 break;685 }686 break;687 case '\n':688 CleanUp;689 Init;690 break;691 case CH_SHIFT_ESC:692 case CH_ESC:693 goto vr_done;694 }695vr_done: //Don't goto out of try696 } catch697 PutExcept;698 SettingsPop;699 CleanUp;700 MenuPop;701 RegWrite("TempleOS/Varoom","F64 best_score=%5.4f;\n",best_score);702}703 704Varoom;705 