hschumann2/TempleOS-Source-Code
0838
1 2#define XMSGF_ANTISPIN 03#define XMSGF_SOLAR_STORM 14RegDft("TempleOS/XCaliber",5 "I64 best_score=0;\n"6 "I64 msg_flags=0;\n"7 );8RegExe("TempleOS/XCaliber");9 10#define MT_HUMAN_SHIP 011#define MT_ENEMY_SHIP 112#define MT_SOLAR_FLARE 213#define MT_ION 314#define MT_ANTIMATTER_BALL 415#define MT_ANTIMATTER_SPLAT 516#define MT_MISSILE 617 18class MyMass:CMass19{20 F64 temperature,radius,die_timeout;21 I64 type;22 Bool no_overlap;23};24 25class MySpring:CSpring26{27 F64 strength;28 I64 color;29};30 31#define SPIN_GAIN 0.2532#define MASSES_NUM 833#define SPRINGS_NUM 1634#define MISSILES_NUM 235#define ST_HUMAN1 036#define ST_ENEMY1 137#define ST_ENEMY2 238extern class Ship;39 40#define MISSILE_LEN 541class Missile42{43 Missile *next,*last;44 F64 tons,fuse_time,die_timeout;45 MyMass p_front,p_back;46 MySpring s[5];47 U8 *img;48 Ship *owner,*target;49 Bool active,launched,exploding;50 U8 label[5];51} missile_head;52 53class Ship54{55 Ship *next,*last;56 I64 type,masses,springs;57 MyMass p[MASSES_NUM];58 MySpring s[SPRINGS_NUM];59 F64 fire_rate;60 F64 reload_timeout,spacewalk_timeout;61 F64 die_time,die_timeout;62 I64 spacewalk_side;63 F64 laser_temperature;64 Missile missiles[MISSILES_NUM];65 Bool lasering,exploding,laser_overheat;66} ship_head,*human;67 68F64 human_t_left,human_t_right,human_antispin;69 70class Shot71{72 Shot *next,*last;73 F64 radius,fuse_time;74 I64 splats;75 MyMass p;76} shot_head;77 78F64 t_solar_storm;79Bool alarm;80 81#define THRUST_MAX 200.082#define ANTISPIN_MAX 25.083#define SPACEWALK_TIME 7.584 85#define CMD_NULL 086#define CMD_SPIN_LEFT 187#define CMD_SPIN_RIGHT 288#define CMD_THRUST 389#define CMD_FIRE 490#define CMD_EXIT 591Bool game_over,show_level_msg;92 93#define STARS_NUM 10094I64 stars_x[STARS_NUM],stars_y[STARS_NUM];95 96CMathODE *ode=NULL;97I64 level,score,remaining;98 99 100<1>/* Graphics Not Rendered in HTML */101 102<2>/* Graphics Not Rendered in HTML */103 104<3>/* Graphics Not Rendered in HTML */105 106<4>/* Graphics Not Rendered in HTML */107 108 109<5>/* Graphics Not Rendered in HTML */110 111<6>/* Graphics Not Rendered in HTML */112 113<7>/* Graphics Not Rendered in HTML */114 115<8>/* Graphics Not Rendered in HTML */116 117 118//********************************** Ship119Bool CheckOverlap()120{121 CD3 p;122 MyMass *tmpm,*tmpm1;123 tmpm=ode->next_mass;124 while (tmpm!=&ode->next_mass) {125 tmpm1=ode->next_mass;126 while (tmpm1!=&ode->next_mass) {127 if (tmpm!=tmpm1 && !tmpm->no_overlap && !tmpm1->no_overlap) {128 D3Sub(&p,&tmpm->x,&tmpm1->x);129 if (D3NormSqr(&p)<=Sqr(tmpm->radius+tmpm1->radius))130 return TRUE;131 }132 tmpm1=tmpm1->next;133 }134 tmpm=tmpm->next;135 }136 return FALSE;137}138 139U0 MissileNew(Ship *tmpsp,I64 n)140{141 I64 i;142 CD3 p,p1,p2;143 Missile *tmpmi=&tmpsp->missiles[n];144 MemSet(tmpmi,0,sizeof(Missile));145 146 D3Equ(&tmpmi->p_front.x,147 (tmpsp->p[n+1].x+tmpsp->p[n+3].x)/2,148 (tmpsp->p[n+1].y+tmpsp->p[n+3].y)/2,0);149 D3Copy(&tmpmi->p_back.x,&tmpmi->p_front.x);150 151 if (n&1)152 StrCpy(tmpmi->label,"L");153 else154 StrCpy(tmpmi->label,"R");155 tmpmi->owner=tmpsp;156 tmpmi->tons=0.5;157 tmpmi->p_front.mass=0.1;158 tmpmi->p_front.type=MT_MISSILE;159 tmpmi->p_back.mass =0.1;160 tmpmi->p_back.type =MT_MISSILE;161 tmpmi->p_front.radius=2;162 tmpmi->p_back.radius =2;163 tmpmi->p_front.no_overlap=TRUE;164 tmpmi->p_back.no_overlap =TRUE;165 D3Sub(&p1,&tmpsp->p[0].x,&tmpsp->p[1].x);166 D3Sub(&p2,&tmpsp->p[0].x,&tmpsp->p[2].x);167 D3Unit(D3Add(&p,&p1,&p2));168 D3AddEqu(&tmpmi->p_front.x,D3MulEqu(D3Copy(&p1,&p),MISSILE_LEN/2+1));169 D3SubEqu(&tmpmi->p_back.x ,D3MulEqu(D3Copy(&p1,&p),MISSILE_LEN/2-1));170 D3Copy(&tmpmi->p_front.DxDt,&tmpsp->p[n].DxDt);171 D3Copy(&tmpmi->p_back.DxDt,&tmpsp->p[n].DxDt);172 QueIns(&tmpmi->p_front,ode->last_mass);173 QueIns(&tmpmi->p_back, ode->last_mass);174 175 tmpmi->s[0].end1=&tmpmi->p_front;176 tmpmi->s[0].end2=&tmpmi->p_back;177 tmpmi->s[1].end1=&tmpmi->p_front;178 tmpmi->s[1].end2=&tmpsp->p[n+1];179 tmpmi->s[2].end1=&tmpmi->p_back;180 tmpmi->s[2].end2=&tmpsp->p[n+1];181 tmpmi->s[3].end1=&tmpmi->p_front;182 tmpmi->s[3].end2=&tmpsp->p[n+3];183 tmpmi->s[4].end1=&tmpmi->p_back;184 tmpmi->s[4].end2=&tmpsp->p[n+3];185 186 for (i=0;i<5;i++) {187 tmpmi->s[i].const=10000;188 tmpmi->s[i].strength =20000;189 tmpmi->s[i].color=BLACK;190 tmpmi->s[i].rest_len=D3Dist(&tmpmi->s[i].end1->x,&tmpmi->s[i].end2->x);191 QueIns(&tmpmi->s[i],ode->last_spring);192 }193 tmpmi->img=<7>;194 tmpmi->active=TRUE;195 QueIns(tmpmi,missile_head.last);196}197 198Ship *ShipNew(I64 x,I64 y,I64 type)199{200 I64 i;201 Ship *tmpsp=CAlloc(sizeof(Ship));202 203 switch (tmpsp->type=type) {204 case ST_HUMAN1:205 tmpsp->fire_rate=25;206 tmpsp->masses=5;207 tmpsp->p[0].x=x;208 tmpsp->p[0].y=y;209 tmpsp->p[1].x=x+3;210 tmpsp->p[1].y=y+10;211 tmpsp->p[2].x=x-3;212 tmpsp->p[2].y=y+10;213 tmpsp->p[3].x=x+20;214 tmpsp->p[3].y=y+20;215 tmpsp->p[4].x=x-20;216 tmpsp->p[4].y=y+20;217 218 for (i=0;i<tmpsp->masses;i++) {219 tmpsp->p[i].mass=1;220 tmpsp->p[i].type=MT_HUMAN_SHIP;221 if (i<3)222 tmpsp->p[i].radius=2.5;223 else224 tmpsp->p[i].radius=4;225 tmpsp->p[i].drag_profile_factor=3;226 QueIns(&tmpsp->p[i],ode->last_mass);227 }228 tmpsp->p[3].mass/=10.0;229 tmpsp->p[4].mass/=10.0;230 231 tmpsp->springs=7;232 tmpsp->s[0].end1=&tmpsp->p[0];233 tmpsp->s[0].end2=&tmpsp->p[1];234 tmpsp->s[1].end1=&tmpsp->p[2];235 tmpsp->s[1].end2=&tmpsp->p[0];236 tmpsp->s[2].end1=&tmpsp->p[1];237 tmpsp->s[2].end2=&tmpsp->p[2];238 tmpsp->s[3].end1=&tmpsp->p[1];239 tmpsp->s[3].end2=&tmpsp->p[3];240 tmpsp->s[4].end1=&tmpsp->p[0];241 tmpsp->s[4].end2=&tmpsp->p[3];242 tmpsp->s[5].end1=&tmpsp->p[2];243 tmpsp->s[5].end2=&tmpsp->p[4];244 tmpsp->s[6].end1=&tmpsp->p[0];245 tmpsp->s[6].end2=&tmpsp->p[4];246 247 for (i=0;i<tmpsp->springs;i++) {248 tmpsp->s[i].rest_len=249 D3Dist(&tmpsp->s[i].end1->x,&tmpsp->s[i].end2->x);250 tmpsp->s[i].const=10000;251 tmpsp->s[i].strength =30000;252 if (i<=2)253 tmpsp->s[i].color=LTCYAN;254 else255 tmpsp->s[i].color=LTGRAY;256 QueIns(&tmpsp->s[i],ode->last_spring);257 }258 MissileNew(tmpsp,0);259 MissileNew(tmpsp,1);260 remaining=0;261 262 break;263 case ST_ENEMY1:264 tmpsp->fire_rate=2.5;265 tmpsp->masses=3;266 tmpsp->p[0].x=x;267 tmpsp->p[0].y=y;268 tmpsp->p[1].x=x+15;269 tmpsp->p[1].y=y;270 tmpsp->p[2].x=x;271 tmpsp->p[2].y=y+15;272 273 for (i=0;i<tmpsp->masses;i++) {274 tmpsp->p[i].mass=1;275 tmpsp->p[i].type=MT_ENEMY_SHIP;276 tmpsp->p[i].radius=7;277 tmpsp->p[i].drag_profile_factor=3;278 QueIns(&tmpsp->p[i],ode->last_mass);279 }280 281 tmpsp->springs=3;282 tmpsp->s[0].end1=&tmpsp->p[0];283 tmpsp->s[0].end2=&tmpsp->p[1];284 tmpsp->s[1].end1=&tmpsp->p[1];285 tmpsp->s[1].end2=&tmpsp->p[2];286 tmpsp->s[2].end1=&tmpsp->p[2];287 tmpsp->s[2].end2=&tmpsp->p[0];288 289 for (i=0;i<tmpsp->springs;i++) {290 tmpsp->s[i].rest_len=291 D3Dist(&tmpsp->s[i].end1->x,&tmpsp->s[i].end2->x);292 tmpsp->s[i].const=10000;293 tmpsp->s[i].strength =20000;294 tmpsp->s[i].color=BLACK;295 QueIns(&tmpsp->s[i],ode->last_spring);296 }297 remaining++;298 break;299 case ST_ENEMY2:300 tmpsp->fire_rate=5.0;301 tmpsp->masses=5;302 tmpsp->p[0].x=x;303 tmpsp->p[0].y=y;304 tmpsp->p[1].x=x-7;305 tmpsp->p[1].y=y+10;306 tmpsp->p[2].x=x+7;307 tmpsp->p[2].y=y+10;308 tmpsp->p[3].x=x-14;309 tmpsp->p[3].y=y+20;310 tmpsp->p[4].x=x+14;311 tmpsp->p[4].y=y+20;312 313 for (i=0;i<tmpsp->masses;i++) {314 tmpsp->p[i].mass=1;315 tmpsp->p[i].type=MT_ENEMY_SHIP;316 tmpsp->p[i].radius=6;317 tmpsp->p[i].drag_profile_factor=5;318 QueIns(&tmpsp->p[i],ode->last_mass);319 }320 321 tmpsp->springs=7;322 tmpsp->s[0].end1=&tmpsp->p[0];323 tmpsp->s[0].end2=&tmpsp->p[1];324 tmpsp->s[1].end1=&tmpsp->p[0];325 tmpsp->s[1].end2=&tmpsp->p[2];326 tmpsp->s[2].end1=&tmpsp->p[1];327 tmpsp->s[2].end2=&tmpsp->p[2];328 tmpsp->s[3].end1=&tmpsp->p[1];329 tmpsp->s[3].end2=&tmpsp->p[3];330 tmpsp->s[4].end1=&tmpsp->p[2];331 tmpsp->s[4].end2=&tmpsp->p[4];332 tmpsp->s[5].end1=&tmpsp->p[2];333 tmpsp->s[5].end2=&tmpsp->p[3];334 tmpsp->s[6].end1=&tmpsp->p[1];335 tmpsp->s[6].end2=&tmpsp->p[4];336 337 for (i=0;i<tmpsp->springs;i++) {338 tmpsp->s[i].rest_len=339 D3Dist(&tmpsp->s[i].end1->x,&tmpsp->s[i].end2->x);340 tmpsp->s[i].const= 40000;341 tmpsp->s[i].strength =75000;342 if (i>=3)343 tmpsp->s[i].color=LTPURPLE;344 else345 tmpsp->s[i].color=BLACK;346 QueIns(&tmpsp->s[i],ode->last_spring);347 }348 remaining++;349 break;350 }351 QueIns(tmpsp,ship_head.last);352 return tmpsp;353}354 355U0 MissileDel(Missile *tmpmi)356{357 I64 i;358 if (tmpmi->active) {359 QueRem(tmpmi);360 for(i=0;i<5;i++)361 QueRem(&tmpmi->s[i]);362 QueRem(&tmpmi->p_front);363 QueRem(&tmpmi->p_back);364 tmpmi->active=FALSE;365 }366}367 368U0 ShipDel(Ship *tmpsp)369{370 I64 i;371 if (!tmpsp) return;372 for (i=0;i<tmpsp->masses;i++)373 QueRem(&tmpsp->p[i]);374 for (i=0;i<tmpsp->springs;i++)375 QueRem(&tmpsp->s[i]);376 for (i=0;i<2;i++)377 MissileDel(&tmpsp->missiles[i]);378 QueRem(tmpsp);379 Free(tmpsp);380 remaining--;381}382 383U0 PlaceShip(I64 type)384{385 Ship *tmpsp;386 if (CheckOverlap)387 return;388 while (TRUE) {389 tmpsp=ShipNew(RandU16%(Fs->pix_width-20)+10,390 RandU16%(Fs->pix_height-20)+10,type);391 if (CheckOverlap)392 ShipDel(tmpsp);393 else394 break;395 }396}397 398//********************************** Human Ship399 400I64 Tweaked()401{402 CD3 p,p1,p2;403 if (human) {404 D3Sub(&p1,&human->p[0].x,&human->p[1].x);405 D3Sub(&p2,&human->p[0].x,&human->p[2].x);406 D3Unit(D3Add(&p,&p1,&p2));407 D3Sub(&p1,&human->p[0].x,&human->p[3].x);408 D3Sub(&p2,&human->p[0].x,&human->p[4].x);409 D3Unit(&p1);410 D3Unit(&p2);411 if (!(human->s[3].flags&SSF_INACTIVE) && D3Dot(&p,&p1)>Cos(20*pi/180))412 return 3;413 if (!(human->s[5].flags&SSF_INACTIVE) && D3Dot(&p,&p2)>Cos(20*pi/180))414 return 4;415 return 0;416 }417}418 419U0 AllDel(CMathODE *ode)420{421 Ship *tmpsp,*tmpsp1;422 QueRem(ode);423 tmpsp=ship_head.next;424 while (tmpsp!=&ship_head) {425 tmpsp1=tmpsp->next;426 ShipDel(tmpsp);427 tmpsp=tmpsp1;428 }429 human=NULL;430 QueDel(&shot_head,TRUE);431 ODEDel(ode);432}433 434Bool LaserPlot(CDC *dc,I64 x,I64 y,I64)435{436 I64 c;437 c=GrPeek(dc,x,y);438 if (c!=BLACK && c!=WHITE)439 return FALSE;440 else {441 GrPlot(dc,x,y);442 return TRUE;443 }444}445 446//**********************************447U0 DrawIt(CTask *task,CDC *dc)448{449 I64 i,j;450 F64 arg;451 Ship *tmpsp;452 Shot *tmps;453 Missile *tmpmi;454 CD3 p,p1,p2;455 F64 t_left,t_right,spin,d,x,y;456 MySpring *tmpsps;457 MyMass *tmpm;458 U8 *img;459 Bool draw_laser_line=FALSE;460 461 if (ode!=task->last_ode) return;462 463 dc->color=WHITE;464 GrPrint(dc,0,0,"Level:%d Score:%d High Score:%d",level,score,best_score);465 if (game_over) {466 if (Blink)467 GrPrint(dc,(task->pix_width-9*FONT_WIDTH)/2,468 (task->pix_height-FONT_HEIGHT)/2,"Game Over");469 } else if (show_level_msg) {470 if (Blink)471 GrPrint(dc,(task->pix_width-8*FONT_WIDTH)/2,472 (task->pix_height-FONT_HEIGHT)/2+50,"Level %d",level);473 }474 475 for (i=0;i<STARS_NUM;i++)476 GrPlot(dc,stars_x[i],stars_y[i]);477 478 tmpm=ode->next_mass;479 while (tmpm!=&ode->next_mass) {480 if (tmpm->type==MT_ANTIMATTER_SPLAT) {481 dc->color=LTGREEN;482 GrPlot(dc,tmpm->x,tmpm->y);483 } else if (tmpm->type==MT_ION) {484 dc->color=YELLOW;485 GrPlot(dc,tmpm->x,tmpm->y);486 }487 tmpm=tmpm->next;488 }489 490 tmpsps=ode->next_spring;491 while (tmpsps!=&ode->next_spring) {492 if (!(tmpsps->flags&SSF_INACTIVE) && tmpsps->color) {493 dc->color=tmpsps->color;494 GrLine(dc,tmpsps->end1->x,tmpsps->end1->y,495 tmpsps->end2->x,tmpsps->end2->y);496 }497 tmpsps=tmpsps->next;498 }499 500 tmpmi=missile_head.next;501 while (tmpmi!=&missile_head) {502 if (tmpmi->active) {503 if (tmpmi->launched && tmpmi->exploding) {504 d=(tS-tmpmi->fuse_time)/(tmpmi->die_timeout-tmpmi->fuse_time);505 d=70*Sin(pi*d)*tmpmi->tons+1;506 for (i=1;i<d;i++) {507 if (i&1)508 dc->color=YELLOW;509 else510 dc->color=LTRED;511 GrCircle(dc,tmpmi->p_front.x,tmpmi->p_front.y,i);512 }513 } else514 Sprite3ZB(dc,(tmpmi->p_front.x+tmpmi->p_back.x)/2,515 (tmpmi->p_front.y+tmpmi->p_back.y)/2,0,tmpmi->img,516 Arg(tmpmi->p_front.x-tmpmi->p_back.x,517 tmpmi->p_front.y-tmpmi->p_back.y));518 }519 tmpmi=tmpmi->next;520 }521 522 tmpsp=ship_head.next;523 while (tmpsp!=&ship_head) {524 if (!tmpsp->exploding) {525 switch (tmpsp->type) {526 case ST_HUMAN1:527 if (tmpsp->spacewalk_side) {528 t_left=0;529 t_right=0;530 } else {531 if (d=D3Norm(D3Sub(&p1,&tmpsp->p[0].x,&tmpsp->p[1].x))) {532 D3Sub(&p2,&tmpsp->p[0].DxDt,&tmpsp->p[1].DxDt);533 D3Cross(&p,&p1,&p2);534 spin=p.z/d;535 } else536 spin=0;537 t_left =Clamp(human_t_left+SPIN_GAIN*spin*human_antispin,538 0,THRUST_MAX);539 540 if (d=D3Norm(D3Sub(&p1,&tmpsp->p[0].x,&tmpsp->p[2].x))) {541 D3Sub(&p2,&tmpsp->p[0].DxDt,&tmpsp->p[2].DxDt);542 D3Cross(&p,&p1,&p2);543 spin=p.z/d;544 } else545 spin=0;546 t_right=Clamp(human_t_right-SPIN_GAIN*spin*human_antispin,547 0,THRUST_MAX);548 }549 550 D3Sub(&p1,&tmpsp->p[1].x,&tmpsp->p[0].x);551 D3Sub(&p2,&tmpsp->p[2].x,&tmpsp->p[0].x);552 D3Unit(D3Add(&p,&p1,&p2));553 554 if (!(tmpsp->s[3].flags&SSF_INACTIVE)) {555 dc->color=YELLOW;556 D3AddEqu(D3Mul(&p1,t_left/25,&p),&tmpsp->p[3].x);557 GrLine(dc,tmpsp->p[1].x,tmpsp->p[1].y,p1.x,p1.y);558 arg=Arg(p.x,p.y);559 Sprite3ZB(dc,tmpsp->p[3].x,tmpsp->p[3].y,0,<thruster>,arg);560 }561 562 if (!(tmpsp->s[5].flags&SSF_INACTIVE)) {563 dc->color=YELLOW;564 D3AddEqu(D3Mul(&p2,t_right/25,&p),&tmpsp->p[4].x);565 GrLine(dc,tmpsp->p[2].x,tmpsp->p[2].y,p2.x,p2.y);566 arg=Arg(p.x,p.y);567 Sprite3ZB(dc,tmpsp->p[4].x,tmpsp->p[4].y,0,<thruster>,arg);568 }569 570 if (tS>tmpsp->reload_timeout)571 img=<gun_ready>;572 else573 img=<gun_busy>;574 arg=Arg(p.x,p.y);575 switch (level) {576 case 3:577 if (!(tmpsp->s[3].flags&SSF_INACTIVE))578 Sprite3ZB(dc,tmpsp->p[3].x,tmpsp->p[3].y,0,img,arg);579 if (!(tmpsp->s[5].flags&SSF_INACTIVE))580 Sprite3ZB(dc,tmpsp->p[4].x,tmpsp->p[4].y,0,img,arg);581 case 2:582 if (!(tmpsp->s[1].flags&SSF_INACTIVE))583 Sprite3ZB(dc,tmpsp->p[1].x,tmpsp->p[1].y,0,img,arg);584 if (!(tmpsp->s[2].flags&SSF_INACTIVE))585 Sprite3ZB(dc,tmpsp->p[2].x,tmpsp->p[2].y,0,img,arg);586 case 1:587 Sprite3ZB(dc,tmpsp->p[0].x,tmpsp->p[0].y,0,img,arg);588 break;589 default:590 Sprite3ZB(dc,tmpsp->p[0].x,tmpsp->p[0].y,0,<Laser>,arg);591 if (tmpsp->lasering && !tmpsp->laser_overheat) {592 draw_laser_line=TRUE;593 Snd(74);594 }595 }596 597 ctrl_panel.laser_temperature=tmpsp->laser_temperature;598 599 if (tmpsp->spacewalk_side) {600 d=1.0-(tmpsp->spacewalk_timeout-tS)/SPACEWALK_TIME;601 if (d>1.0) {602 tmpsp->spacewalk_side=0;603 ctrl_panel.spacewalk=FALSE;604 } else {605 if (d<0.5) {606 d=d*2;607 x=tmpsp->p[0].x*(1.0-d)+608 tmpsp->p[tmpsp->spacewalk_side].x*(d);609 y=tmpsp->p[0].y*(1.0-d)+610 tmpsp->p[tmpsp->spacewalk_side].y*(d);611 } else {612 d=(d-0.5)*2;613 x=tmpsp->p[tmpsp->spacewalk_side].x*(1.0-d)+614 tmpsp->p[0].x*(d);615 y=tmpsp->p[tmpsp->spacewalk_side].y*(1.0-d)+616 tmpsp->p[0].y*(d);617 }618 Sprite3ZB(dc,x,y,0,<spacewalk>,arg+0.75*Sin(tS*2));619 }620 } else {621 if (ctrl_panel.spacewalk) {622 if (tmpsp->spacewalk_side=Tweaked)623 tmpsp->spacewalk_timeout=tS+SPACEWALK_TIME;624 else625 ctrl_panel.spacewalk=FALSE;626 }627 }628 break;629 case ST_ENEMY2:630 for (i=3;i<tmpsp->masses;i++) {631 dc->color=PURPLE;632 GrCircle(dc,tmpsp->p[i].x,tmpsp->p[i].y,tmpsp->p[i].radius);633 GrFloodFill(dc,tmpsp->p[i].x,tmpsp->p[i].y+2,TRUE);634 dc->color=WHITE;635 GrCircle(dc,tmpsp->p[i].x,tmpsp->p[i].y,tmpsp->p[i].radius);636 }637 case ST_ENEMY1:638 D3DivEqu(D3Sub(&p1,&tmpsp->p[1].x,&tmpsp->p[0].x),2.0);639 D3DivEqu(D3Sub(&p2,&tmpsp->p[2].x,&tmpsp->p[0].x),2.0);640 D3Unit(D3Add(&p,&p1,&p2));641 if (tS>tmpsp->reload_timeout)642 img=<gun_ready>;643 else644 img=<gun_busy>;645 arg=Arg(p.x,p.y);646 Sprite3ZB(dc,tmpsp->p[0].x,tmpsp->p[0].y,0,img,arg);647 arg=Arg(p1.x,p1.y);648 Sprite3ZB(dc,tmpsp->p[0].x+p1.x,tmpsp->p[0].y+p1.y,0,649 <EnemySide>,arg);650 arg=Arg(p2.x,p2.y);651 Sprite3ZB(dc,tmpsp->p[0].x+p2.x,tmpsp->p[0].y+p2.y,0,652 <EnemySide>,arg);653 break;654 }655 for (i=0;i<tmpsp->masses;i++) {656 dc->color=YELLOW;657 if (tmpsp->p[i].temperature>=1.0)658 GrCircle(dc,tmpsp->p[i].x,tmpsp->p[i].y,659 tmpsp->p[i].temperature);660 }661 }662 else if (tmpsp->die_time<=tS<=tmpsp->die_timeout)663 for (j=0;j<tmpsp->masses;j++) {664 d=(tS-tmpsp->die_time)/(tmpsp->die_timeout-tmpsp->die_time);665 d=7*Sin(pi*d)*(6+j)+1;666 for (i=1;i<d;i++) {667 if (i&1)668 dc->color=YELLOW;669 else670 dc->color=LTRED;671 GrCircle(dc,tmpsp->p[j].x,tmpsp->p[j].y,i);672 }673 }674 tmpsp=tmpsp->next;675 }676 677 tmps=shot_head.next;678 while (tmps!=&shot_head) {679 if (tmps->radius<1.0) {680 dc->color=LTGREEN;681 GrPlot(dc,tmps->p.x,tmps->p.y);682 } else {683 dc->color=YELLOW;684 GrCircle(dc,tmps->p.x,tmps->p.y,tmps->radius);685 if (tmps->radius>=2.0)686 GrFloodFill(dc,tmps->p.x,tmps->p.y,TRUE);687 dc->color=LTGREEN;688 GrCircle(dc,tmps->p.x,tmps->p.y,tmps->radius);689 }690 tmps=tmps->next;691 }692 693 if (human && draw_laser_line) {694 D3Sub(&p1,&human->p[1].x,&human->p[0].x);695 D3Sub(&p2,&human->p[2].x,&human->p[0].x);696 D3Unit(D3Add(&p,&p1,&p2));697 dc->color=LTBLUE;698 Line(dc,human->p[0].x-10*p.x,human->p[0].y-10*p.y,0,699 human->p[0].x-800*p.x,human->p[0].y-800*p.y,0,&LaserPlot);700 }701 702 tmpmi=missile_head.next;703 while (tmpmi!=&missile_head) {704 if (tmpsp=tmpmi->target) {705 dc->color=LTRED;706 GrCircle(dc,tmpsp->p[0].x,tmpsp->p[0].y,10);707 GrPrint(dc,tmpsp->p[0].x+12,tmpsp->p[0].y-4,tmpmi->label);708 }709 tmpmi=tmpmi->next;710 }711}712 713U0 Explosion(MyMass *tmpm1,MyMass *tmpm2,F64 tons)714{715 MyMass *tmpm;716 CD3 p1;717 F64 d;718 719 tmpm=ode->next_mass;720 while (tmpm!=&ode->next_mass) {721 if (tmpm!=tmpm1 && tmpm!=tmpm2) {722 D3Sub(&p1,&tmpm->state->x,&tmpm1->state->x);723 d=D3NormSqr(&p1)-tmpm->radius*tmpm->radius;724 if (d<100.0*100.0) {725 if (d<1)726 d=1;727 else728 d=Sqrt(d);729 d=250000*tons/d`2;730 D3MulEqu(&p1,d);731 D3AddEqu(&tmpm->DstateDt->DxDt,&p1);732 }733 }734 tmpm=tmpm->next;735 }736}737 738Ship TargetGet(Missile *tmpmi)739{740 Ship *tmpsp,*res=NULL;741 F64 dd,best_dd=F64_MAX;742 I64 i;743 CD3 p,p1,p2;744 D3Unit(D3Sub(&p,&tmpmi->p_front.state->x,&tmpmi->p_back.state->x));745 tmpsp=ship_head.next;746 while (tmpsp!=&ship_head) {747 if (!tmpsp->exploding && tmpsp!=tmpmi->owner)748 for (i=0;i<tmpsp->masses;i++) {749 D3Sub(&p1,&tmpsp->p[i].state->x,&tmpmi->p_front.state->x);750 D3Unit(D3Copy(&p2,&p1));751 D3Cross(&p1,&p,&p2);752 if (D3Dot(&p,&p2)>0 && D3Norm(&p1)<=pi/16) {753 dd=D3NormSqr(&p1);754 if (dd<best_dd) {755 best_dd=dd;756 res=tmpsp;757 }758 }759 }760 tmpsp=tmpsp->next;761 }762 return res;763}764 765U0 MyDerivative(CMathODE *ode,F64,COrder2D3 *,COrder2D3 *)766{767 I64 i;768 F64 d,dd,dd2,spin,t_left,t_right,theta_err,theta_thrust,DthetaDt;769 CTask *task=ode->win_task;770 CD3 p,p1,p2;771 Ship *tmpsp;772 Missile *tmpmi;773 MyMass *tmpm,*tmpm1;774 775 tmpm=ode->next_mass;776 while (tmpm!=&ode->next_mass) {777 if (tmpm->type!=MT_SOLAR_FLARE && tmpm->type!=MT_ION) {778 d=tmpm->state->x;779 if (d-tmpm->radius<0)780 tmpm->DstateDt->DxDt+=Sqr(Sqr(Sqr(d-tmpm->radius)));781 if (d+tmpm->radius>task->pix_width)782 tmpm->DstateDt->DxDt-=Sqr(Sqr(Sqr((d+tmpm->radius)-task->pix_width)));783 d=tmpm->state->y;784 if (d-tmpm->radius<0)785 tmpm->DstateDt->DyDt+=Sqr(Sqr(Sqr(d-tmpm->radius)));786 if (d+tmpm->radius>task->pix_height)787 tmpm->DstateDt->DyDt-=Sqr(Sqr(Sqr((d+tmpm->radius)-task->pix_height)));788 }789 if (tmpm->type!=MT_ION && tmpm->type!=MT_ANTIMATTER_SPLAT) {790 tmpm1=ode->next_mass;791 while (tmpm1!=&ode->next_mass) {792 if (tmpm!=tmpm1) {793 if (tmpm1->type==MT_ANTIMATTER_SPLAT) {794 if (tmpm->type==MT_HUMAN_SHIP || tmpm->type==MT_ENEMY_SHIP) {795 D3Sub(&p,&tmpm->state->x,&tmpm1->state->x);796 dd=D3NormSqr(&p)+1;797 if (dd<100000) {798 D3MulEqu(&p,100000/dd);799 D3AddEqu(&tmpm1->DstateDt->DxDt,&p);800 }801 }802 } else if (tmpm1->type!=MT_ION) {803 D3Sub(&p,&tmpm->state->x,&tmpm1->state->x);804 dd=D3NormSqr(&p);805 dd2=Sqr(tmpm->radius+tmpm1->radius);806 if (dd<=dd2) {807 d=Sqrt(dd)+0.0001;808 D3MulEqu(&p,Sqr(Sqr(dd2-dd))/d);809 D3AddEqu(&tmpm ->DstateDt->DxDt,&p);810 D3SubEqu(&tmpm1->DstateDt->DxDt,&p);811 }812 }813 }814 tmpm1=tmpm1->next;815 }816 }817 tmpm=tmpm->next;818 }819 820 tmpsp=ship_head.next;821 while (tmpsp!=&ship_head) {822 if (tmpsp->exploding && tmpsp->die_time<=tS<=tmpsp->die_timeout)823 for (i=0;i<tmpsp->masses;i++)824 Explosion(&tmpsp->p[i],NULL,tmpsp->p[i].radius/250.0);825 switch (tmpsp->type) {826 case ST_HUMAN1:827 if (!tmpsp->exploding) {828 if (tmpsp->spacewalk_side) {829 t_left=0;830 t_right=0;831 d=1.0-(tmpsp->spacewalk_timeout-tS)/SPACEWALK_TIME;832 if (0.485<d<0.515) {833 D3Unit(D3Sub(&p,&tmpsp->p[2].state->x,&tmpsp->p[1].state->x));834 if (tmpsp->spacewalk_side==3) {835 tmpsp->p[3].DstateDt->DxDt-=10*THRUST_MAX*p.x;836 tmpsp->p[3].DstateDt->DyDt-=10*THRUST_MAX*p.y;837 tmpsp->p[1].DstateDt->DxDt+=10*THRUST_MAX*p.x;838 tmpsp->p[1].DstateDt->DyDt+=10*THRUST_MAX*p.y;839 } else {840 tmpsp->p[4].DstateDt->DxDt+=10*THRUST_MAX*p.x;841 tmpsp->p[4].DstateDt->DyDt+=10*THRUST_MAX*p.y;842 tmpsp->p[2].DstateDt->DxDt-=10*THRUST_MAX*p.x;843 tmpsp->p[2].DstateDt->DyDt-=10*THRUST_MAX*p.y;844 }845 }846 } else {847 if (d=D3Norm(D3Sub(&p1,&tmpsp->p[0].state->x,848 &tmpsp->p[1].state->x))) {849 D3Sub(&p2,&tmpsp->p[0].state->DxDt,&tmpsp->p[1].state->DxDt);850 D3Cross(&p,&p1,&p2);851 spin=p.z/d;852 } else853 spin=0;854 t_left =Clamp(human_t_left+SPIN_GAIN*spin*human_antispin,855 0,THRUST_MAX);856 857 if (d=D3Norm(D3Sub(&p1,&tmpsp->p[0].state->x,858 &tmpsp->p[2].state->x))) {859 D3Sub(&p2,&tmpsp->p[0].state->DxDt,&tmpsp->p[2].state->DxDt);860 D3Cross(&p,&p1,&p2);861 spin=p.z/d;862 } else863 spin=0;864 t_right=Clamp(human_t_right-SPIN_GAIN*spin*human_antispin,865 0,THRUST_MAX);866 867 D3Sub(&p1,&tmpsp->p[0].state->x,&tmpsp->p[1].state->x);868 D3Sub(&p2,&tmpsp->p[0].state->x,&tmpsp->p[2].state->x);869 D3Unit(D3Add(&p,&p1,&p2));870 if (!(tmpsp->s[3].flags&SSF_INACTIVE)) {871 D3Mul(&p1,t_left,&p);872 D3AddEqu(&tmpsp->p[3].DstateDt->DxDt,&p1);873 }874 if (!(tmpsp->s[5].flags&SSF_INACTIVE)) {875 D3Mul(&p2,t_right,&p);876 D3AddEqu(&tmpsp->p[4].DstateDt->DxDt,&p2);877 }878 }879 }880 break;881 }882 tmpsp=tmpsp->next;883 }884 885 tmpmi=missile_head.next;886 while (tmpmi!=&missile_head) {887 if (tmpmi->active) {888 if (tmpmi->launched) {889 if (tmpmi->exploding)890 Explosion(&tmpmi->p_front,&tmpmi->p_back,tmpmi->tons);891 else {892//Guide missile893 if (tmpsp=tmpmi->target) {894 D3Unit(D3Sub(&p,&tmpmi->p_front.state->x,895 &tmpmi->p_back.state->x));896 D3Sub(&p1,&tmpsp->p[0].state->x,&tmpmi->p_front.state->x);897 d=D3Norm(&p1);898 D3Unit(&p1);899 theta_err=D3Dot(&p,&p1);900 D3Sub(&p1,&tmpmi->p_front.state->DxDt,&tmpmi->p_back.state->DxDt);901 D3Cross(&p2,&p,&p1);902 DthetaDt=D3Norm(&p2);903 if (p2.z<0)904 DthetaDt=-DthetaDt;905 theta_thrust=Clamp(200*(theta_err+2*DthetaDt)/(d+200),-pi/8,pi/8);906 p2.x=p.x*Cos(theta_thrust)-p.y*Sin(theta_thrust);907 p2.y=p.y*Cos(theta_thrust)+p.x*Sin(theta_thrust);908 p2.z=0;909 D3AddEqu(&tmpmi->p_back.DstateDt->DxDt,D3MulEqu(&p2,THRUST_MAX));910 }911 }912 } else913 tmpmi->target=TargetGet(tmpmi);914 } else915 tmpmi->target=NULL;916 tmpmi=tmpmi->next;917 }918}919 920U0 CheckDamage()921{922 I64 i,j,death_score;923 Ship *tmpsp,*tmpsp1;924 MyMass *tmpm,*tmpm1,*best_mass;925 CD3 p,p1,p2;926 F64 d,best_distance;927 Bool facing_sun=FALSE;928 929 if (human) {930 D3Sub(&p1,&human->p[1].x,&human->p[0].x);931 D3Sub(&p2,&human->p[2].x,&human->p[0].x);932 D3Add(&p,&p1,&p2);933 if (p.x>0)934 facing_sun=TRUE;935 }936 937 tmpm=ode->next_mass;938 while (tmpm!=&ode->next_mass) {939 if (tmpm->type==MT_ION) {940 if (facing_sun) {941 tmpm1=ode->next_mass;942 while (tmpm1!=&ode->next_mass) {943 if (tmpm1->type==MT_HUMAN_SHIP) {944 D3Sub(&p,&tmpm1->x,&tmpm->x);945 if (D3NormSqr(&p)<Sqr(tmpm1->radius))946 tmpm1->temperature+=3.0;947 }948 tmpm1=tmpm1->next;949 }950 }951 } else if (tmpm->type==MT_ANTIMATTER_SPLAT) {952 tmpm1=ode->next_mass;953 while (tmpm1!=&ode->next_mass) {954 if (tmpm1->type!=MT_ION && tmpm1->type!=MT_ANTIMATTER_SPLAT) {955 D3Sub(&p,&tmpm1->x,&tmpm->x);956 if (D3NormSqr(&p)<Sqr(tmpm1->radius))957 tmpm1->temperature+=0.4;958 }959 tmpm1=tmpm1->next;960 }961 } else962 tmpm->temperature*=0.9;963 tmpm=tmpm->next;964 }965 966 if (human) {967 human->laser_temperature*=0.975;968 969 if (human->laser_overheat) {970 if (human->laser_temperature<LASER_THRESHOLD_TEMP)971 human->laser_overheat=FALSE;972 }973 if (!human->laser_overheat && human->lasering) {974 if (human->laser_temperature>=LASER_TEMP_MAX) {975 human->laser_overheat=TRUE;976 Snd;977 } else {978 human->laser_temperature+=1.0;979 D3Sub(&p1,&human->p[0].x,&human->p[1].x);980 D3Sub(&p2,&human->p[0].x,&human->p[2].x);981 D3Unit(D3Add(&p,&p1,&p2));982 p2.x=p.y;983 p2.y=-p.x;984 p2.z=0;985 best_mass=NULL;986 best_distance=F64_MAX;987 tmpm=ode->next_mass;988 while (tmpm!=&ode->next_mass) {989 D3Sub(&p1,&human->p[0].x,&tmpm->x);990 if (Abs(D3Dot(&p1,&p2))<tmpm->radius &&991 D3Dot(&p1,&p)<0.0) {992 d=D3NormSqr(&p1);993 if (d<best_distance) {994 best_distance=d;995 best_mass=tmpm;996 }997 }998 tmpm=tmpm->next;999 }1000 if (best_mass)1001 best_mass->temperature+=1.0;1002 }1003 }1004 }1005 1006 tmpsp=ship_head.next;1007 while (tmpsp!=&ship_head) {1008 tmpsp1=tmpsp->next;1009 death_score=0;1010 switch (tmpsp->type) {1011 case ST_HUMAN1:1012 if (tmpsp->exploding) {1013 if (tS>tmpsp->die_timeout) {1014 ShipDel(tmpsp);1015 human=NULL;1016 }1017 } else1018 for (i=0;i<tmpsp->springs;i++) {1019 if (Abs(tmpsp->s[i].f)>tmpsp->s[i].strength) {1020 tmpsp->s[i].flags|=SSF_INACTIVE;1021 if (i==4)1022 MissileDel(&tmpsp->missiles[0]);1023 else if (i==5)1024 MissileDel(&tmpsp->missiles[1]);1025 }1026 if (tmpsp->s[i].flags&SSF_INACTIVE && i<3)1027 death_score++;1028 }1029 break;1030 default:1031 if (tmpsp->exploding) {1032 if (tS>tmpsp->die_timeout) {1033 ShipDel(tmpsp);1034 score+=level;1035 if (score>best_score)1036 best_score=score;1037 }1038 } else {1039 j=0;1040 for (i=0;i<tmpsp->springs;i++) {1041 if (tmpsp->s[i].flags&SSF_INACTIVE)1042 j++;1043 else if (Abs(tmpsp->s[i].f)>tmpsp->s[i].strength) {1044 tmpsp->s[i].flags|=SSF_INACTIVE;1045 j++;1046 }1047 }1048 if (j>1)1049 death_score++;1050 }1051 }1052 if (!tmpsp->exploding) {1053 for (i=0;i<tmpsp->masses;i++)1054 if (tmpsp->p[i].temperature>MASS_TEMP_MAX)1055 death_score++;1056 if (death_score) {1057 tmpsp->exploding=TRUE;1058 tmpsp->die_time=tS;1059 tmpsp->die_timeout=tS+0.75;1060 Noise(750,74,93);1061 if (tmpsp->type==ST_HUMAN1)1062 game_over=TRUE;1063 }1064 }1065 tmpsp=tmpsp1;1066 }1067}1068 1069//********************************** Shots1070 1071Shot *ShotNew(I64 type,CD3 *_p,CD3 *_v,F64 r,F64 fuse_time,1072 CD3 *_p_gun_offset=NULL)1073{1074 Shot *tmps=CAlloc(sizeof(Shot));1075 D3Copy(&tmps->p.x,_p);1076 tmps->radius=r;1077 tmps->splats=20*r;1078 tmps->fuse_time=tS+fuse_time;1079 tmps->p.mass=0.3*r*r*r;1080 tmps->p.type=type;1081 if (_p_gun_offset)1082 D3AddEqu(&tmps->p.x,_p_gun_offset);1083 D3Copy(&tmps->p.DxDt,_v);1084 QueIns(&tmps->p,ode->last_mass);1085 QueIns(tmps,shot_head.last);1086}1087 1088U0 SolarFlares()1089{1090 CD3 p,v,p1,p2;1091 CTask *task=ode->win_task;1092 if (!alarm && t_solar_storm-2.0<tS<t_solar_storm+1.0) {1093 Sweep(2000,74,93);1094 alarm=TRUE;1095 }1096 if (t_solar_storm<tS) { //If solar storm has arrived1097 if (tS<t_solar_storm+5.0) { //If solar storm not over1098 if (Rand<.1) {1099 D3Equ(&p,-300,Rand*task->pix_height,0);1100 D3Equ(&v,200.0,0,0);1101 ShotNew(MT_SOLAR_FLARE,&p,&v,25,0.1);1102 }1103 } else {1104 t_solar_storm=tS+25*Rand; //Schedule next solar storm1105 alarm=FALSE;1106 }1107 }1108}1109 1110U0 FireOneGun(Ship *tmpsp,I64 n,F64 r,F64 fuse_time)1111{1112 I64 ona;1113 CD3 p,v,p1,p2;1114 Shot *tmps;1115 D3Sub(&p1,&tmpsp->p[0].x,&tmpsp->p[1].x);1116 D3Sub(&p2,&tmpsp->p[0].x,&tmpsp->p[2].x);1117 D3Unit(D3Add(&p,&p1,&p2));1118 D3MulEqu(D3Copy(&p1,&p),r+tmpsp->p[0].radius+5);1119 D3AddEqu(D3MulEqu(D3Copy(&v,&p),1000/(r+1)),&tmpsp->p[n].DxDt);1120 tmps=ShotNew(MT_ANTIMATTER_BALL,&tmpsp->p[n].x,&v,r,fuse_time,&p1);1121 D3MulEqu(&p,tmps->p.mass/tmpsp->p[n].mass/100.0);1122 D3SubEqu(&tmpsp->p[n].DxDt,&p);1123 tmpsp->reload_timeout=tS+r/tmpsp->fire_rate;1124 ona=Freq2Ona(500/r);1125 Noise(100,ona,ona+12);1126}1127 1128U0 FireOneMissile(Ship *tmpsp,I64 n)1129{1130 I64 i;1131 Missile *tmpmi=&tmpsp->missiles[n];1132 if (!tmpmi->launched && tmpmi->target) {1133 tmpmi->fuse_time=tS+1.0;1134 tmpmi->die_timeout=tmpmi->fuse_time+0.125;1135 tmpmi->img=<8>;1136 for (i=1;i<5;i++)1137 tmpmi->s[i].flags|=SSF_INACTIVE;1138 tmpmi->launched=TRUE;1139 Sweep(250,53,56);1140 }1141}1142 1143U0 HumanFireGunBegin()1144{1145 F64 r=3.0*ctrl_panel.shot_radius/CTRL_PANEL_RANGE+0.5,1146 fuse_time=ToF64(ctrl_panel.fuse_time+1)/CTRL_PANEL_RANGE;1147 if (human) {1148 if (!human->exploding && !human->spacewalk_side && tS>human->reload_timeout)1149 switch (level) {1150 case 3:1151 if (!(human->s[3].flags&SSF_INACTIVE))1152 FireOneGun(human,3,r,fuse_time);1153 if (!(human->s[5].flags&SSF_INACTIVE))1154 FireOneGun(human,4,r,fuse_time);1155 case 2:1156 if (!(human->s[1].flags&SSF_INACTIVE))1157 FireOneGun(human,1,r,fuse_time);1158 if (!(human->s[2].flags&SSF_INACTIVE))1159 FireOneGun(human,2,r,fuse_time);1160 case 1:1161 FireOneGun(human,0,r,fuse_time);1162 break;1163 }1164 }1165}1166 1167U0 HumanFireMissileBegin(I64 n)1168{1169 if (human && !human->exploding &&1170 !human->spacewalk_side && tS>human->reload_timeout)1171 FireOneMissile(human,n);1172}1173 1174U0 HumanFireLaserBegin()1175{1176 if (human && !human->exploding &&1177 !human->spacewalk_side && tS>human->reload_timeout)1178 human->lasering=TRUE;1179}1180U0 HumanFireLaserEnd()1181{1182 if (human && !human->exploding) {1183 human->lasering=FALSE;1184 Snd;1185 }1186}1187 1188U0 SplatNew(Shot *tmps,F64 die_time,F64 start,F64 end)1189{1190 MyMass *tmpm;1191 F64 theta=Arg(tmps->p.DxDt,tmps->p.DyDt);1192 I64 i;1193 for (i=0;i<tmps->splats;i++) {1194 tmpm=CAlloc(sizeof(MyMass));1195 D3Copy(&tmpm->x,&tmps->p.x);1196 tmpm->radius=1;1197 tmpm->mass=1;1198 tmpm->die_timeout=tS+die_time;1199 if (tmps->p.type==MT_SOLAR_FLARE)1200 tmpm->type=MT_ION;