hschumann2/TempleOS-Source-Code
0838
1 2 3<1>/* Graphics Not Rendered in HTML */4 5<2>/* Graphics Not Rendered in HTML */6 7 8<3>/* Graphics Not Rendered in HTML */9 10 11#define STARS_NUM 819212I64 stars_x[STARS_NUM],stars_y[STARS_NUM];13 14#define RADIUS 715 16class MyMass:CMass17{18 U8 *img;19};20 21class MySpring:CSpring22{23 I64 type,action_key;24};25 26//Main Modses27#define MMD_EDIT 028#define MMD_PLAY 129#define MMD_MODES_NUM 230CColorROPU32 main_mode_colors[MMD_MODES_NUM]={LTRED,LTGREEN};31DefineLstLoad("ST_MAIN_MODES","Edit\0Play\0");32CCtrlBttnState main_mode_bttn;33 34//Edit Modes35#define EMD_MASS 036#define EMD_SPRING 137#define EMD_CONNECTOR 238#define EMD_THRUSTER 339#define EMD_MOVE 440#define EMD_MODES_NUM 541CColorROPU32 edit_mode_colors[EMD_MODES_NUM]={LTGRAY,LTCYAN,CYAN,YELLOW,LTBLUE};42DefineLstLoad("ST_EDIT_MODES","Mass\0Spring\0Connector\0Thruster\0Move\0");43CCtrlBttnState edit_mode_bttn;44 45CTask *task;46F64 zoom;47I64 next_action_key,action_scan_codes[10];48CMathODE *ode=NULL;49 50U0 S2W(F64 sx,F64 sy,F64 *_wx,F64 *_wy)51{52 sx-=task->pix_left+task->scroll_x;53 sy-=task->pix_top +task->scroll_y;54 *_wx=sx/zoom;55 *_wy=sy/zoom;56}57 58U0 W2S(F64 wx,F64 wy,F64 *_sx,F64 *_sy)59{60 *_sx=wx*zoom; *_sy=wy*zoom;61}62 63#define ZOOM_STEPS 2064 65U0 Zoom(F64 d)66{67 F64 sx,sy,wx,wy;68 I64 i,x=ms.pos.x,y=ms.pos.y;69 d=Exp(Ln(d)/ZOOM_STEPS);70 for (i=0;i<ZOOM_STEPS;i++) {71 S2W(x,y,&wx,&wy);72 zoom=Clamp(zoom*d,0.02,50);73 W2S(wx,wy,&sx,&sy);74 task->scroll_x=ms.pos.x-sx-task->pix_left;75 task->scroll_y=ms.pos.y-sy-task->pix_top;76 Sleep(10);77 }78}79 80U0 DrawIt(CTask *,CDC *dc)81{82 I64 i;83 F64 theta,d,x1,y1,x2,y2;84 MyMass *tmpm;85 MySpring *tmps;86 87 tmpm=ode->next_mass;88 if (tmpm!=&ode->next_mass) {89 task->scroll_x=-tmpm->x*zoom+task->pix_width >>1;90 task->scroll_y=-tmpm->y*zoom+task->pix_height>>1;91 }92 93 dc->flags|=DCF_TRANSFORMATION;94 Mat4x4Scale(dc->r,zoom);95 96 switch (main_mode_bttn.state) {97 case MMD_EDIT:98 task->text_attr=DKGRAY<<4+WHITE;99 dc->color=BLACK;100 break;101 case MMD_PLAY:102 task->text_attr=BLACK<<4+WHITE;103 dc->color=WHITE;104 for (i=0;i<STARS_NUM;i++)105 GrPlot3(dc,stars_x[i],stars_y[i],0);106 break;107 }108 109 if (main_mode_bttn.state==MMD_EDIT) {110 if (edit_mode_bttn.state==EMD_CONNECTOR) {111 dc->color=CYAN;112 S2W(FONT_WIDTH*11,FONT_HEIGHT*7,&x1,&y1);113 GrPutChar3(dc,x1,y1,0,next_action_key);114 } else if (edit_mode_bttn.state==EMD_THRUSTER) {115 dc->color=YELLOW;116 S2W(FONT_WIDTH*11,FONT_HEIGHT*7,&x1,&y1);117 GrPutChar3(dc,x1,y1,0,next_action_key);118 }119 }120 121 tmps=ode->next_spring;122 while (tmps!=&ode->next_spring) {123 if (tmps->type==EMD_SPRING) {124 dc->color=LTCYAN;125 GrLine3(dc,tmps->end1->x,tmps->end1->y,0,126 tmps->end2->x,tmps->end2->y,0);127 } else if (tmps->type==EMD_CONNECTOR) {128 dc->color=CYAN;129 GrLine3(dc,tmps->end1->x,tmps->end1->y,0,130 tmps->end2->x,tmps->end2->y,0);131 }132 tmps=tmps->next;133 }134 135 dc->color=LTGRAY;136 tmpm=ode->next_mass;137 while (tmpm!=&ode->next_mass) {138 Sprite3(dc,tmpm->x,tmpm->y,0,tmpm->img);139 tmpm=tmpm->next;140 }141 142 tmps=ode->next_spring;143 while (tmps!=&ode->next_spring) {144 x1=tmps->end1->x; y1=tmps->end1->y;145 x2=tmps->end2->x; y2=tmps->end2->y;146 if (tmps->type==EMD_THRUSTER) {147 theta=Arg(x2-x1,y2-y1);148 if (Bt(kbd.down_bitmap,action_scan_codes[tmps->action_key-'0'])) {149 dc->flags|=DCF_SYMMETRY;150 DCSymmetry3Set(dc,x1,y1,256,x1,y1,0,x1-256*Cos(theta),y1-256*Sin(theta),0);151 for (i=0;i<8;i++) {152 d=20*Rand+6;153 if (d<10)154 dc->color=BLUE;155 else if (d<16)156 dc->color=LTBLUE;157 else158 dc->color=YELLOW;159 GrLine3(dc,x1-3*Cos(theta),y1-3*Sin(theta),0,160 x1-d*Cos(theta)+0.5*d*Sin(theta),161 y1-d*Sin(theta)-0.5*d*Cos(theta),0);162 GrLine3(dc,x1-2*d*Cos(theta),y1-2*d*Sin(theta),0,163 x1-d*Cos(theta)+0.5*d*Sin(theta),164 y1-d*Sin(theta)-0.5*d*Cos(theta),0);165 }166 dc->flags&=~DCF_SYMMETRY;167 }168 Sprite3ZB(dc,x1,y1,0,<3>,theta);169 if (zoom>0.5) {170 dc->color=YELLOW;171 GrPutChar3(dc,(x1*7+x2)/8,(y1*7+y2)/8,0,tmps->action_key);172 }173 } else if (tmps->type==EMD_CONNECTOR) {174 if (zoom>0.5) {175 dc->color=CYAN;176 GrPutChar3(dc,(x1*7+x2)/8,(y1*7+y2)/8,0,tmps->action_key);177 }178 }179 tmps=tmps->next;180 }181}182 183U0 MyDerivative(CMathODE *ode,F64,COrder2D3 *,COrder2D3 *)184{185//The forces due to springs and drag are186 //automatically handled by the187 //ode code. We can add new forces188 //here.189 F64 d,dd;190 CD3 p;191 MyMass *tmpm1,*tmpm2;192 MySpring *tmps;193 194 tmpm1=ode->next_mass;195 while (tmpm1!=&ode->next_mass) {196 tmpm2=tmpm1->next;197 while (tmpm2!=&ode->next_mass) {198 D3Sub(&p,&tmpm2->state->x,&tmpm1->state->x);199 dd=D3NormSqr(&p);200 if (dd<=Sqr(2*RADIUS)) {201 d=Sqrt(dd)+0.0001;202 dd=10.0*Sqr(Sqr(Sqr(2*RADIUS)-dd));203 D3MulEqu(&p,dd/d);204 D3AddEqu(&tmpm2->DstateDt->DxDt,&p);205 D3SubEqu(&tmpm1->DstateDt->DxDt,&p);206 }207 tmpm2=tmpm2->next;208 }209 tmpm1=tmpm1->next;210 }211 212 tmps=ode->next_spring;213 while (tmps!=&ode->next_spring) {214 if (main_mode_bttn.state==MMD_PLAY && tmps->type==EMD_THRUSTER &&215 Bt(kbd.down_bitmap,action_scan_codes[tmps->action_key-'0'])) {216 D3Sub(&p,&tmps->end2->state->x,&tmps->end1->state->x);217 D3Unit(&p);218 D3MulEqu(&p,2000);219 D3AddEqu(&tmps->end1->DstateDt->DxDt,&p);220 }221 tmps=tmps->next;222 }223}224 225MyMass *PlaceMass(I64 x, I64 y)226{227 MyMass *tmpm=CAlloc(sizeof(MyMass));228 tmpm->mass=1.0;229 tmpm->drag_profile_factor=100.0;230 tmpm->x=x;231 tmpm->y=y;232 QueIns(tmpm,ode->last_mass);233 return tmpm;234}235 236MySpring *PlaceSpring(MyMass *tmpm1,MyMass *tmpm2,I64 type)237{238 MySpring *tmps=CAlloc(sizeof(MySpring));239 F64 d=D3Dist(&tmpm1->x,&tmpm2->x);240 tmps->end1=tmpm1;241 tmps->end2=tmpm2;242 tmps->rest_len=d;243 tmps->type=type;244 if (type==EMD_THRUSTER)245 tmps->const=0;246 else247 tmps->const=2500000/Sqr(d);248 tmps->action_key=next_action_key;249 QueIns(tmps,ode->last_spring);250 return tmps;251}252 253U0 CenterMasses()254{255 CD3 p;256 MyMass *tmpm1,*tmpm2;257 tmpm1=ode->next_mass;258 if (tmpm1!=&ode->next_mass) {259 D3Copy(&p,&tmpm1->x);260 tmpm2=ode->next_mass;261 while (tmpm2!=&ode->next_mass) {262 D3SubEqu(&tmpm2->x,&p);263 tmpm2=tmpm2->next;264 }265 }266}267 268U0 NullSprings()269{270 MySpring *tmps=ode->next_spring;271 while (tmps!=&ode->next_spring) {272 tmps->rest_len=D3Dist(&tmps->end1->x,&tmps->end2->x);273 tmps=tmps->next;274 }275}276 277U0 BreakConnectors()278{279 MySpring *tmps=ode->next_spring,*tmps1;280 while (tmps!=&ode->next_spring) {281 tmps1=tmps->next;282 if (tmps->type==EMD_CONNECTOR &&283 Bt(kbd.down_bitmap,action_scan_codes[tmps->action_key-'0'])) {284 QueRem(tmps);285 Free(tmps);286 }287 tmps=tmps1;288 }289}290 291U0 Init()292{293 I64 i;294 task=Fs;295 for (i=0;i<=9;i++)296 action_scan_codes[i]=Char2ScanCode('0'+i);297 for (i=0;i<STARS_NUM;i++) {298 stars_x[i]=RandU32%8192-4096;299 stars_y[i]=RandU32%8192-4096;300 }301 next_action_key='1';302 zoom=1.0;303 ode=ODENew(0,1e-4,ODEF_HAS_MASSES);304 ode->derive=&MyDerivative;305 ode->acceleration_limit=5e3;306 ode->drag_v2=0.000002;307 ode->drag_v3=0.0000001;308 QueIns(ode,Fs->last_ode);309}310 311U0 CleanUp()312{313 if (ode) {314 QueRem(ode);315 QueDel(&ode->next_mass,TRUE);316 QueDel(&ode->next_spring,TRUE);317 ODEDel(ode);318 ode=NULL;319 }320}321 322U0 PlayShip()323{324 I64 arg1,arg2;325 F64 last_noise=0;326 Bool okay;327 ODEPause(ode,OFF);328 MenuPush(329 "File {"330 " Abort(,CH_SHIFT_ESC);"331 " Exit(,CH_ESC);"332 "}"333 "Edit {"334 " EditShip(,CH_SPACE);"335 "}"336 "Play {"337 " Center(,'c');"338 " Damp(,'d');"339 " Action0(,'0');"340 " Action1(,'1');"341 " Action2(,'2');"342 " Action3(,'3');"343 " Action4(,'4');"344 " Action5(,'5');"345 " Action6(,'6');"346 " Action7(,'7');"347 " Action8(,'8');"348 " Action9(,'9');"349 "}"350 "View {"351 " ZoomIn(,'z');"352 " ZoomOut(,'Z');"353 "}"354 );355 DocClear;356 try {357 while (main_mode_bttn.state==MMD_PLAY) {358 BreakConnectors;359 switch (ScanMsg(&arg1,&arg2,1<<MSG_KEY_DOWN|1<<MSG_KEY_UP)) {360 case MSG_KEY_DOWN:361 switch (arg1) {362 case '0'...'9':363 if (tS>last_noise+0.25) {364 Noise(250,18,46);365 last_noise=tS;366 }367 break;368 case 'z':369 Spawn(&Zoom,2.0(I64));370 break;371 case 'Z':372 Spawn(&Zoom,0.5(I64));373 break;374 case 'c':375 CenterMasses;376 break;377 case 'd':378 ode->drag_v2=0.002;379 ode->drag_v3=0.0001;380 break;381 case CH_SPACE:382 if (++main_mode_bttn.state==MMD_MODES_NUM)383 main_mode_bttn.state=0;384 GetMsg(,,1<<MSG_KEY_UP);385 goto ps_done;386 case CH_SHIFT_ESC:387 case CH_ESC:388 throw;389 }390 break;391 case MSG_KEY_UP:392 switch (arg1) {393 case 'd':394 ode->drag_v2=0.000002;395 ode->drag_v3=0.0000001;396 break;397 }398 break;399 }400 Refresh;401 }402ps_done: //Don't goto out of try403 okay=TRUE;404 } catch {405 Fs->catch_except=TRUE;406 okay=FALSE;407 }408 MenuPop;409 if (!okay)410 throw;411}412 413U0 EditShip()414{415 I64 arg1,arg2;416 F64 wx,wy;417 Bool okay;418 MyMass *tmpm1=NULL,*tmpm2=NULL;419 CCtrl *bt_edit_mode=CtrlBttnNew(0,5*FONT_HEIGHT+4,80,,EMD_MODES_NUM,420 Define("ST_EDIT_MODES"),edit_mode_colors,&edit_mode_bttn);421 ODEPause(ode);422 MenuPush(423 "File {"424 " Abort(,CH_SHIFT_ESC);"425 " Exit(,CH_ESC);"426 "}"427 "Play {"428 " PlayShip(,CH_SPACE);"429 " Center(,'c');"430 " Damp(,'d');"431 "}"432 "Edit {"433 " Move(,'v');"434 " Mass(,'m');"435 " Spring(,'s');"436 " Connector(,'n');"437 " Thruster(,'t');"438 " Restart(,'\n');"439 " Action0(,'0');"440 " Action1(,'1');"441 " Action2(,'2');"442 " Action3(,'3');"443 " Action4(,'4');"444 " Action5(,'5');"445 " Action6(,'6');"446 " Action7(,'7');"447 " Action8(,'8');"448 " Action9(,'9');"449 "}"450 "View {"451 " ZoomIn(,'z');"452 " ZoomOut(,'Z');"453 "}"454 );455 DocClear;456 try {457 while (main_mode_bttn.state==MMD_EDIT) {458 switch (ScanMsg(&arg1,&arg2,459 1<<MSG_MS_L_DOWN|1<<MSG_MS_L_UP|1<<MSG_MS_R_DOWN|460 1<<MSG_MS_MOVE|1<<MSG_KEY_DOWN|1<<MSG_KEY_UP)) {461 case MSG_MS_L_DOWN:462 switch (edit_mode_bttn.state) {463 case EMD_MASS:464 S2W(ms.pos.x,ms.pos.y,&wx,&wy);465 tmpm1=PlaceMass(wx,wy);466 if (ode->next_mass==tmpm1)467 tmpm1->img=<1>;468 else469 tmpm1->img=<2>;470 tmpm1=NULL;471 break;472 case EMD_SPRING:473 case EMD_CONNECTOR:474 case EMD_THRUSTER:475 case EMD_MOVE:476 S2W(ms.pos.x,ms.pos.y,&wx,&wy);477 tmpm1=MassFind(ode,wx,wy);478 tmpm2=NULL;479 break;480 }481 break;482 case MSG_MS_L_UP:483 switch (edit_mode_bttn.state) {484 case EMD_MASS:485 break;486 case EMD_SPRING:487 case EMD_CONNECTOR:488 case EMD_THRUSTER:489 S2W(ms.pos.x,ms.pos.y,&wx,&wy);490 if (tmpm1 && (tmpm2=MassFind(ode,wx,wy)) && tmpm1!=tmpm2)491 PlaceSpring(tmpm1,tmpm2,edit_mode_bttn.state);492 tmpm1=tmpm2=NULL;493 break;494 case EMD_MOVE:495 S2W(ms.pos.x,ms.pos.y,&wx,&wy);496 if (tmpm1) {497 tmpm1->x=wx;498 tmpm1->y=wy;499 tmpm1->z=0;500 NullSprings;501 }502 tmpm1=tmpm2=NULL;503 break;504 }505 break;506 case MSG_MS_MOVE:507 switch (edit_mode_bttn.state) {508 case EMD_MOVE:509 S2W(ms.pos.x,ms.pos.y,&wx,&wy);510 if (tmpm1) {511 tmpm1->x=wx;512 tmpm1->y=wy;513 tmpm1->z=0;514 NullSprings;515 }516 break;517 }518 break;519 case MSG_MS_R_DOWN:520 if (++edit_mode_bttn.state==EMD_MODES_NUM)521 edit_mode_bttn.state=0;522 break;523 case MSG_MS_R_UP:524 break;525 case MSG_KEY_DOWN:526 switch (arg1) {527 case '\n':528 CleanUp;529 Init;530 break;531 case '0'...'9':532 next_action_key=arg1;533 break;534 case 'c':535 CenterMasses;536 break;537 case 'd':538 ODEPause(ode,OFF);539 ode->drag_v2=0.002;540 ode->drag_v3=0.0001;541 break;542 case 'v':543 edit_mode_bttn.state=EMD_MOVE;544 break;545 case 'm':546 edit_mode_bttn.state=EMD_MASS;547 break;548 case 'n':549 edit_mode_bttn.state=EMD_CONNECTOR;550 break;551 case 's':552 edit_mode_bttn.state=EMD_SPRING;553 break;554 case 't':555 edit_mode_bttn.state=EMD_THRUSTER;556 break;557 case 'z':558 Spawn(&Zoom,2.0(I64));559 break;560 case 'Z':561 Spawn(&Zoom,0.5(I64));562 break;563 case CH_SPACE:564 if (++main_mode_bttn.state==MMD_MODES_NUM)565 main_mode_bttn.state=0;566 GetMsg(,,1<<MSG_KEY_UP);567 goto es_done;568 case CH_SHIFT_ESC:569 case CH_ESC:570 throw;571 }572 break;573 case MSG_KEY_UP:574 switch (arg1) {575 case 'd':576 ODEPause(ode);577 ode->drag_v2=0.000002;578 ode->drag_v3=0.0000001;579 break;580 }581 break;582 }583 Refresh;584 }585es_done: //Don't goto out of try586 okay=TRUE;587 } catch {588 Fs->catch_except=TRUE;589 okay=FALSE;590 }591 MenuPop;592 CtrlBttnDel(bt_edit_mode);593 if (!okay)594 throw;595}596 597U0 Strut()598{599 CCtrl *bt_main_mode;600 SettingsPush; //See SettingsPush601 Fs->win_inhibit|=WIF_SELF_MS_L|WIF_SELF_MS_R|WIG_DBL_CLICK;602 AutoComplete;603 WinBorder;604 WinMax;605 DocCursor;606 DocClear;607 "\n$WW,1$$PURPLE$$TX+CX,\"Build a ship.\"$$FG$\n\n"608 "Sel mass mode.\tLeft-click to place masses.\n"609 "Sel spring mode.\tLeft-drag to make members.\n"610 "Sel thruster mode.\tPress a digit, 0-9. Drag to make thruster.\n"611 "Sel connector mode.\tPress a digit, 0-9. "612 "Drag to make breakable connector.\n\n"613 "Press $GREEN$<SPACE>$FG$ to run the game. Press digits to operate "614 "thrusters and break connectors.\n\n"615 "Press $GREEN$<z>$FG$ or $GREEN$<SHIFT-Z>$FG$ to zoom in/out.\n\n";616 617 PressAKey;618 bt_main_mode=CtrlBttnNew(619 (GR_WIDTH-4*FONT_WIDTH-16)>>1,1*FONT_HEIGHT+4,80,,MMD_MODES_NUM,620 Define("ST_MAIN_MODES"),main_mode_colors,&main_mode_bttn);621 DocClear;622 Init;623 Fs->draw_it=&DrawIt;624 try {625 while (TRUE) {626 EditShip;627 PlayShip;628 }629 } catch {630 CleanUp;631 Fs->catch_except=TRUE;632 }633 SettingsPop;634 CtrlBttnDel(bt_main_mode);635}636 