#define XMSGF_ANTISPIN 0 #define XMSGF_SOLAR_STORM 1 RegDft("TempleOS/XCaliber", "I64 best_score=0;\n" "I64 msg_flags=0;\n" ); RegExe("TempleOS/XCaliber"); #define MT_HUMAN_SHIP 0 #define MT_ENEMY_SHIP 1 #define MT_SOLAR_FLARE 2 #define MT_ION 3 #define MT_ANTIMATTER_BALL 4 #define MT_ANTIMATTER_SPLAT 5 #define MT_MISSILE 6 class MyMass:CMass { F64 temperature,radius,die_timeout; I64 type; Bool no_overlap; }; class MySpring:CSpring { F64 strength; I64 color; }; #define SPIN_GAIN 0.25 #define MASSES_NUM 8 #define SPRINGS_NUM 16 #define MISSILES_NUM 2 #define ST_HUMAN1 0 #define ST_ENEMY1 1 #define ST_ENEMY2 2 extern class Ship; #define MISSILE_LEN 5 class Missile { Missile *next,*last; F64 tons,fuse_time,die_timeout; MyMass p_front,p_back; MySpring s[5]; U8 *img; Ship *owner,*target; Bool active,launched,exploding; U8 label[5]; } missile_head; class Ship { Ship *next,*last; I64 type,masses,springs; MyMass p[MASSES_NUM]; MySpring s[SPRINGS_NUM]; F64 fire_rate; F64 reload_timeout,spacewalk_timeout; F64 die_time,die_timeout; I64 spacewalk_side; F64 laser_temperature; Missile missiles[MISSILES_NUM]; Bool lasering,exploding,laser_overheat; } ship_head,*human; F64 human_t_left,human_t_right,human_antispin; class Shot { Shot *next,*last; F64 radius,fuse_time; I64 splats; MyMass p; } shot_head; F64 t_solar_storm; Bool alarm; #define THRUST_MAX 200.0 #define ANTISPIN_MAX 25.0 #define SPACEWALK_TIME 7.5 #define CMD_NULL 0 #define CMD_SPIN_LEFT 1 #define CMD_SPIN_RIGHT 2 #define CMD_THRUST 3 #define CMD_FIRE 4 #define CMD_EXIT 5 Bool game_over,show_level_msg; #define STARS_NUM 100 I64 stars_x[STARS_NUM],stars_y[STARS_NUM]; CMathODE *ode=NULL; I64 level,score,remaining; <1>/* Graphics Not Rendered in HTML */ <2>/* Graphics Not Rendered in HTML */ <3>/* Graphics Not Rendered in HTML */ <4>/* Graphics Not Rendered in HTML */ <5>/* Graphics Not Rendered in HTML */ <6>/* Graphics Not Rendered in HTML */ <7>/* Graphics Not Rendered in HTML */ <8>/* Graphics Not Rendered in HTML */ //********************************** Ship Bool CheckOverlap() { CD3 p; MyMass *tmpm,*tmpm1; tmpm=ode->next_mass; while (tmpm!=&ode->next_mass) { tmpm1=ode->next_mass; while (tmpm1!=&ode->next_mass) { if (tmpm!=tmpm1 && !tmpm->no_overlap && !tmpm1->no_overlap) { D3Sub(&p,&tmpm->x,&tmpm1->x); if (D3NormSqr(&p)<=Sqr(tmpm->radius+tmpm1->radius)) return TRUE; } tmpm1=tmpm1->next; } tmpm=tmpm->next; } return FALSE; } U0 MissileNew(Ship *tmpsp,I64 n) { I64 i; CD3 p,p1,p2; Missile *tmpmi=&tmpsp->missiles[n]; MemSet(tmpmi,0,sizeof(Missile)); D3Equ(&tmpmi->p_front.x, (tmpsp->p[n+1].x+tmpsp->p[n+3].x)/2, (tmpsp->p[n+1].y+tmpsp->p[n+3].y)/2,0); D3Copy(&tmpmi->p_back.x,&tmpmi->p_front.x); if (n&1) StrCpy(tmpmi->label,"L"); else StrCpy(tmpmi->label,"R"); tmpmi->owner=tmpsp; tmpmi->tons=0.5; tmpmi->p_front.mass=0.1; tmpmi->p_front.type=MT_MISSILE; tmpmi->p_back.mass =0.1; tmpmi->p_back.type =MT_MISSILE; tmpmi->p_front.radius=2; tmpmi->p_back.radius =2; tmpmi->p_front.no_overlap=TRUE; tmpmi->p_back.no_overlap =TRUE; D3Sub(&p1,&tmpsp->p[0].x,&tmpsp->p[1].x); D3Sub(&p2,&tmpsp->p[0].x,&tmpsp->p[2].x); D3Unit(D3Add(&p,&p1,&p2)); D3AddEqu(&tmpmi->p_front.x,D3MulEqu(D3Copy(&p1,&p),MISSILE_LEN/2+1)); D3SubEqu(&tmpmi->p_back.x ,D3MulEqu(D3Copy(&p1,&p),MISSILE_LEN/2-1)); D3Copy(&tmpmi->p_front.DxDt,&tmpsp->p[n].DxDt); D3Copy(&tmpmi->p_back.DxDt,&tmpsp->p[n].DxDt); QueIns(&tmpmi->p_front,ode->last_mass); QueIns(&tmpmi->p_back, ode->last_mass); tmpmi->s[0].end1=&tmpmi->p_front; tmpmi->s[0].end2=&tmpmi->p_back; tmpmi->s[1].end1=&tmpmi->p_front; tmpmi->s[1].end2=&tmpsp->p[n+1]; tmpmi->s[2].end1=&tmpmi->p_back; tmpmi->s[2].end2=&tmpsp->p[n+1]; tmpmi->s[3].end1=&tmpmi->p_front; tmpmi->s[3].end2=&tmpsp->p[n+3]; tmpmi->s[4].end1=&tmpmi->p_back; tmpmi->s[4].end2=&tmpsp->p[n+3]; for (i=0;i<5;i++) { tmpmi->s[i].const=10000; tmpmi->s[i].strength =20000; tmpmi->s[i].color=BLACK; tmpmi->s[i].rest_len=D3Dist(&tmpmi->s[i].end1->x,&tmpmi->s[i].end2->x); QueIns(&tmpmi->s[i],ode->last_spring); } tmpmi->img=<7>; tmpmi->active=TRUE; QueIns(tmpmi,missile_head.last); } Ship *ShipNew(I64 x,I64 y,I64 type) { I64 i; Ship *tmpsp=CAlloc(sizeof(Ship)); switch (tmpsp->type=type) { case ST_HUMAN1: tmpsp->fire_rate=25; tmpsp->masses=5; tmpsp->p[0].x=x; tmpsp->p[0].y=y; tmpsp->p[1].x=x+3; tmpsp->p[1].y=y+10; tmpsp->p[2].x=x-3; tmpsp->p[2].y=y+10; tmpsp->p[3].x=x+20; tmpsp->p[3].y=y+20; tmpsp->p[4].x=x-20; tmpsp->p[4].y=y+20; for (i=0;i<tmpsp->masses;i++) { tmpsp->p[i].mass=1; tmpsp->p[i].type=MT_HUMAN_SHIP; if (i<3) tmpsp->p[i].radius=2.5; else tmpsp->p[i].radius=4; tmpsp->p[i].drag_profile_factor=3; QueIns(&tmpsp->p[i],ode->last_mass); } tmpsp->p[3].mass/=10.0; tmpsp->p[4].mass/=10.0; tmpsp->springs=7; tmpsp->s[0].end1=&tmpsp->p[0]; tmpsp->s[0].end2=&tmpsp->p[1]; tmpsp->s[1].end1=&tmpsp->p[2]; tmpsp->s[1].end2=&tmpsp->p[0]; tmpsp->s[2].end1=&tmpsp->p[1]; tmpsp->s[2].end2=&tmpsp->p[2]; tmpsp->s[3].end1=&tmpsp->p[1]; tmpsp->s[3].end2=&tmpsp->p[3]; tmpsp->s[4].end1=&tmpsp->p[0]; tmpsp->s[4].end2=&tmpsp->p[3]; tmpsp->s[5].end1=&tmpsp->p[2]; tmpsp->s[5].end2=&tmpsp->p[4]; tmpsp->s[6].end1=&tmpsp->p[0]; tmpsp->s[6].end2=&tmpsp->p[4]; for (i=0;i<tmpsp->springs;i++) { tmpsp->s[i].rest_len= D3Dist(&tmpsp->s[i].end1->x,&tmpsp->s[i].end2->x); tmpsp->s[i].const=10000; tmpsp->s[i].strength =30000; if (i<=2) tmpsp->s[i].color=LTCYAN; else tmpsp->s[i].color=LTGRAY; QueIns(&tmpsp->s[i],ode->last_spring); } MissileNew(tmpsp,0); MissileNew(tmpsp,1); remaining=0; break; case ST_ENEMY1: tmpsp->fire_rate=2.5; tmpsp->masses=3; tmpsp->p[0].x=x; tmpsp->p[0].y=y; tmpsp->p[1].x=x+15; tmpsp->p[1].y=y; tmpsp->p[2].x=x; tmpsp->p[2].y=y+15; for (i=0;i<tmpsp->masses;i++) { tmpsp->p[i].mass=1; tmpsp->p[i].type=MT_ENEMY_SHIP; tmpsp->p[i].radius=7; tmpsp->p[i].drag_profile_factor=3; QueIns(&tmpsp->p[i],ode->last_mass); } tmpsp->springs=3; tmpsp->s[0].end1=&tmpsp->p[0]; tmpsp->s[0].end2=&tmpsp->p[1]; tmpsp->s[1].end1=&tmpsp->p[1]; tmpsp->s[1].end2=&tmpsp->p[2]; tmpsp->s[2].end1=&tmpsp->p[2]; tmpsp->s[2].end2=&tmpsp->p[0]; for (i=0;i<tmpsp->springs;i++) { tmpsp->s[i].rest_len= D3Dist(&tmpsp->s[i].end1->x,&tmpsp->s[i].end2->x); tmpsp->s[i].const=10000; tmpsp->s[i].strength =20000; tmpsp->s[i].color=BLACK; QueIns(&tmpsp->s[i],ode->last_spring); } remaining++; break; case ST_ENEMY2: tmpsp->fire_rate=5.0; tmpsp->masses=5; tmpsp->p[0].x=x; tmpsp->p[0].y=y; tmpsp->p[1].x=x-7; tmpsp->p[1].y=y+10; tmpsp->p[2].x=x+7; tmpsp->p[2].y=y+10; tmpsp->p[3].x=x-14; tmpsp->p[3].y=y+20; tmpsp->p[4].x=x+14; tmpsp->p[4].y=y+20; for (i=0;i<tmpsp->masses;i++) { tmpsp->p[i].mass=1; tmpsp->p[i].type=MT_ENEMY_SHIP; tmpsp->p[i].radius=6; tmpsp->p[i].drag_profile_factor=5; QueIns(&tmpsp->p[i],ode->last_mass); } tmpsp->springs=7; tmpsp->s[0].end1=&tmpsp->p[0]; tmpsp->s[0].end2=&tmpsp->p[1]; tmpsp->s[1].end1=&tmpsp->p[0]; tmpsp->s[1].end2=&tmpsp->p[2]; tmpsp->s[2].end1=&tmpsp->p[1]; tmpsp->s[2].end2=&tmpsp->p[2]; tmpsp->s[3].end1=&tmpsp->p[1]; tmpsp->s[3].end2=&tmpsp->p[3]; tmpsp->s[4].end1=&tmpsp->p[2]; tmpsp->s[4].end2=&tmpsp->p[4]; tmpsp->s[5].end1=&tmpsp->p[2]; tmpsp->s[5].end2=&tmpsp->p[3]; tmpsp->s[6].end1=&tmpsp->p[1]; tmpsp->s[6].end2=&tmpsp->p[4]; for (i=0;i<tmpsp->springs;i++) { tmpsp->s[i].rest_len= D3Dist(&tmpsp->s[i].end1->x,&tmpsp->s[i].end2->x); tmpsp->s[i].const= 40000; tmpsp->s[i].strength =75000; if (i>=3) tmpsp->s[i].color=LTPURPLE; else tmpsp->s[i].color=BLACK; QueIns(&tmpsp->s[i],ode->last_spring); } remaining++; break; } QueIns(tmpsp,ship_head.last); return tmpsp; } U0 MissileDel(Missile *tmpmi) { I64 i; if (tmpmi->active) { QueRem(tmpmi); for(i=0;i<5;i++) QueRem(&tmpmi->s[i]); QueRem(&tmpmi->p_front); QueRem(&tmpmi->p_back); tmpmi->active=FALSE; } } U0 ShipDel(Ship *tmpsp) { I64 i; if (!tmpsp) return; for (i=0;i<tmpsp->masses;i++) QueRem(&tmpsp->p[i]); for (i=0;i<tmpsp->springs;i++) QueRem(&tmpsp->s[i]); for (i=0;i<2;i++) MissileDel(&tmpsp->missiles[i]); QueRem(tmpsp); Free(tmpsp); remaining--; } U0 PlaceShip(I64 type) { Ship *tmpsp; if (CheckOverlap) return; while (TRUE) { tmpsp=ShipNew(RandU16%(Fs->pix_width-20)+10, RandU16%(Fs->pix_height-20)+10,type); if (CheckOverlap) ShipDel(tmpsp); else break; } } //********************************** Human Ship I64 Tweaked() { CD3 p,p1,p2; if (human) { D3Sub(&p1,&human->p[0].x,&human->p[1].x); D3Sub(&p2,&human->p[0].x,&human->p[2].x); D3Unit(D3Add(&p,&p1,&p2)); D3Sub(&p1,&human->p[0].x,&human->p[3].x); D3Sub(&p2,&human->p[0].x,&human->p[4].x); D3Unit(&p1); D3Unit(&p2); if (!(human->s[3].flags&SSF_INACTIVE) && D3Dot(&p,&p1)>Cos(20*pi/180)) return 3; if (!(human->s[5].flags&SSF_INACTIVE) && D3Dot(&p,&p2)>Cos(20*pi/180)) return 4; return 0; } } U0 AllDel(CMathODE *ode) { Ship *tmpsp,*tmpsp1; QueRem(ode); tmpsp=ship_head.next; while (tmpsp!=&ship_head) { tmpsp1=tmpsp->next; ShipDel(tmpsp); tmpsp=tmpsp1; } human=NULL; QueDel(&shot_head,TRUE); ODEDel(ode); } Bool LaserPlot(CDC *dc,I64 x,I64 y,I64) { I64 c; c=GrPeek(dc,x,y); if (c!=BLACK && c!=WHITE) return FALSE; else { GrPlot(dc,x,y); return TRUE; } } //********************************** U0 DrawIt(CTask *task,CDC *dc) { I64 i,j; F64 arg; Ship *tmpsp; Shot *tmps; Missile *tmpmi; CD3 p,p1,p2; F64 t_left,t_right,spin,d,x,y; MySpring *tmpsps; MyMass *tmpm; U8 *img; Bool draw_laser_line=FALSE; if (ode!=task->last_ode) return; dc->color=WHITE; GrPrint(dc,0,0,"Level:%d Score:%d High Score:%d",level,score,best_score); if (game_over) { if (Blink) GrPrint(dc,(task->pix_width-9*FONT_WIDTH)/2, (task->pix_height-FONT_HEIGHT)/2,"Game Over"); } else if (show_level_msg) { if (Blink) GrPrint(dc,(task->pix_width-8*FONT_WIDTH)/2, (task->pix_height-FONT_HEIGHT)/2+50,"Level %d",level); } for (i=0;i<STARS_NUM;i++) GrPlot(dc,stars_x[i],stars_y[i]); tmpm=ode->next_mass; while (tmpm!=&ode->next_mass) { if (tmpm->type==MT_ANTIMATTER_SPLAT) { dc->color=LTGREEN; GrPlot(dc,tmpm->x,tmpm->y); } else if (tmpm->type==MT_ION) { dc->color=YELLOW; GrPlot(dc,tmpm->x,tmpm->y); } tmpm=tmpm->next; } tmpsps=ode->next_spring; while (tmpsps!=&ode->next_spring) { if (!(tmpsps->flags&SSF_INACTIVE) && tmpsps->color) { dc->color=tmpsps->color; GrLine(dc,tmpsps->end1->x,tmpsps->end1->y, tmpsps->end2->x,tmpsps->end2->y); } tmpsps=tmpsps->next; } tmpmi=missile_head.next; while (tmpmi!=&missile_head) { if (tmpmi->active) { if (tmpmi->launched && tmpmi->exploding) { d=(tS-tmpmi->fuse_time)/(tmpmi->die_timeout-tmpmi->fuse_time); d=70*Sin(pi*d)*tmpmi->tons+1; for (i=1;i<d;i++) { if (i&1) dc->color=YELLOW; else dc->color=LTRED; GrCircle(dc,tmpmi->p_front.x,tmpmi->p_front.y,i); } } else Sprite3ZB(dc,(tmpmi->p_front.x+tmpmi->p_back.x)/2, (tmpmi->p_front.y+tmpmi->p_back.y)/2,0,tmpmi->img, Arg(tmpmi->p_front.x-tmpmi->p_back.x, tmpmi->p_front.y-tmpmi->p_back.y)); } tmpmi=tmpmi->next; } tmpsp=ship_head.next; while (tmpsp!=&ship_head) { if (!tmpsp->exploding) { switch (tmpsp->type) { case ST_HUMAN1: if (tmpsp->spacewalk_side) { t_left=0; t_right=0; } else { if (d=D3Norm(D3Sub(&p1,&tmpsp->p[0].x,&tmpsp->p[1].x))) { D3Sub(&p2,&tmpsp->p[0].DxDt,&tmpsp->p[1].DxDt); D3Cross(&p,&p1,&p2); spin=p.z/d; } else spin=0; t_left =Clamp(human_t_left+SPIN_GAIN*spin*human_antispin, 0,THRUST_MAX); if (d=D3Norm(D3Sub(&p1,&tmpsp->p[0].x,&tmpsp->p[2].x))) { D3Sub(&p2,&tmpsp->p[0].DxDt,&tmpsp->p[2].DxDt); D3Cross(&p,&p1,&p2); spin=p.z/d; } else spin=0; t_right=Clamp(human_t_right-SPIN_GAIN*spin*human_antispin, 0,THRUST_MAX); } D3Sub(&p1,&tmpsp->p[1].x,&tmpsp->p[0].x); D3Sub(&p2,&tmpsp->p[2].x,&tmpsp->p[0].x); D3Unit(D3Add(&p,&p1,&p2)); if (!(tmpsp->s[3].flags&SSF_INACTIVE)) { dc->color=YELLOW; D3AddEqu(D3Mul(&p1,t_left/25,&p),&tmpsp->p[3].x); GrLine(dc,tmpsp->p[1].x,tmpsp->p[1].y,p1.x,p1.y); arg=Arg(p.x,p.y); Sprite3ZB(dc,tmpsp->p[3].x,tmpsp->p[3].y,0,<thruster>,arg); } if (!(tmpsp->s[5].flags&SSF_INACTIVE)) { dc->color=YELLOW; D3AddEqu(D3Mul(&p2,t_right/25,&p),&tmpsp->p[4].x); GrLine(dc,tmpsp->p[2].x,tmpsp->p[2].y,p2.x,p2.y); arg=Arg(p.x,p.y); Sprite3ZB(dc,tmpsp->p[4].x,tmpsp->p[4].y,0,<thruster>,arg); } if (tS>tmpsp->reload_timeout) img=<gun_ready>; else img=<gun_busy>; arg=Arg(p.x,p.y); switch (level) { case 3: if (!(tmpsp->s[3].flags&SSF_INACTIVE)) Sprite3ZB(dc,tmpsp->p[3].x,tmpsp->p[3].y,0,img,arg); if (!(tmpsp->s[5].flags&SSF_INACTIVE)) Sprite3ZB(dc,tmpsp->p[4].x,tmpsp->p[4].y,0,img,arg); case 2: if (!(tmpsp->s[1].flags&SSF_INACTIVE)) Sprite3ZB(dc,tmpsp->p[1].x,tmpsp->p[1].y,0,img,arg); if (!(tmpsp->s[2].flags&SSF_INACTIVE)) Sprite3ZB(dc,tmpsp->p[2].x,tmpsp->p[2].y,0,img,arg); case 1: Sprite3ZB(dc,tmpsp->p[0].x,tmpsp->p[0].y,0,img,arg); break; default: Sprite3ZB(dc,tmpsp->p[0].x,tmpsp->p[0].y,0,<Laser>,arg); if (tmpsp->lasering && !tmpsp->laser_overheat) { draw_laser_line=TRUE; Snd(74); } } ctrl_panel.laser_temperature=tmpsp->laser_temperature; if (tmpsp->spacewalk_side) { d=1.0-(tmpsp->spacewalk_timeout-tS)/SPACEWALK_TIME; if (d>1.0) { tmpsp->spacewalk_side=0; ctrl_panel.spacewalk=FALSE; } else { if (d<0.5) { d=d*2; x=tmpsp->p[0].x*(1.0-d)+ tmpsp->p[tmpsp->spacewalk_side].x*(d); y=tmpsp->p[0].y*(1.0-d)+ tmpsp->p[tmpsp->spacewalk_side].y*(d); } else { d=(d-0.5)*2; x=tmpsp->p[tmpsp->spacewalk_side].x*(1.0-d)+ tmpsp->p[0].x*(d); y=tmpsp->p[tmpsp->spacewalk_side].y*(1.0-d)+ tmpsp->p[0].y*(d); } Sprite3ZB(dc,x,y,0,<spacewalk>,arg+0.75*Sin(tS*2)); } } else { if (ctrl_panel.spacewalk) { if (tmpsp->spacewalk_side=Tweaked) tmpsp->spacewalk_timeout=tS+SPACEWALK_TIME; else ctrl_panel.spacewalk=FALSE; } } break; case ST_ENEMY2: for (i=3;i<tmpsp->masses;i++) { dc->color=PURPLE; GrCircle(dc,tmpsp->p[i].x,tmpsp->p[i].y,tmpsp->p[i].radius); GrFloodFill(dc,tmpsp->p[i].x,tmpsp->p[i].y+2,TRUE); dc->color=WHITE; GrCircle(dc,tmpsp->p[i].x,tmpsp->p[i].y,tmpsp->p[i].radius); } case ST_ENEMY1: D3DivEqu(D3Sub(&p1,&tmpsp->p[1].x,&tmpsp->p[0].x),2.0); D3DivEqu(D3Sub(&p2,&tmpsp->p[2].x,&tmpsp->p[0].x),2.0); D3Unit(D3Add(&p,&p1,&p2)); if (tS>tmpsp->reload_timeout) img=<gun_ready>; else img=<gun_busy>; arg=Arg(p.x,p.y); Sprite3ZB(dc,tmpsp->p[0].x,tmpsp->p[0].y,0,img,arg); arg=Arg(p1.x,p1.y); Sprite3ZB(dc,tmpsp->p[0].x+p1.x,tmpsp->p[0].y+p1.y,0, <EnemySide>,arg); arg=Arg(p2.x,p2.y); Sprite3ZB(dc,tmpsp->p[0].x+p2.x,tmpsp->p[0].y+p2.y,0, <EnemySide>,arg); break; } for (i=0;i<tmpsp->masses;i++) { dc->color=YELLOW; if (tmpsp->p[i].temperature>=1.0) GrCircle(dc,tmpsp->p[i].x,tmpsp->p[i].y, tmpsp->p[i].temperature); } } else if (tmpsp->die_time<=tS<=tmpsp->die_timeout) for (j=0;j<tmpsp->masses;j++) { d=(tS-tmpsp->die_time)/(tmpsp->die_timeout-tmpsp->die_time); d=7*Sin(pi*d)*(6+j)+1; for (i=1;i<d;i++) { if (i&1) dc->color=YELLOW; else dc->color=LTRED; GrCircle(dc,tmpsp->p[j].x,tmpsp->p[j].y,i); } } tmpsp=tmpsp->next; } tmps=shot_head.next; while (tmps!=&shot_head) { if (tmps->radius<1.0) { dc->color=LTGREEN; GrPlot(dc,tmps->p.x,tmps->p.y); } else { dc->color=YELLOW; GrCircle(dc,tmps->p.x,tmps->p.y,tmps->radius); if (tmps->radius>=2.0) GrFloodFill(dc,tmps->p.x,tmps->p.y,TRUE); dc->color=LTGREEN; GrCircle(dc,tmps->p.x,tmps->p.y,tmps->radius); } tmps=tmps->next; } if (human && draw_laser_line) { D3Sub(&p1,&human->p[1].x,&human->p[0].x); D3Sub(&p2,&human->p[2].x,&human->p[0].x); D3Unit(D3Add(&p,&p1,&p2)); dc->color=LTBLUE; Line(dc,human->p[0].x-10*p.x,human->p[0].y-10*p.y,0, human->p[0].x-800*p.x,human->p[0].y-800*p.y,0,&LaserPlot); } tmpmi=missile_head.next; while (tmpmi!=&missile_head) { if (tmpsp=tmpmi->target) { dc->color=LTRED; GrCircle(dc,tmpsp->p[0].x,tmpsp->p[0].y,10); GrPrint(dc,tmpsp->p[0].x+12,tmpsp->p[0].y-4,tmpmi->label); } tmpmi=tmpmi->next; } } U0 Explosion(MyMass *tmpm1,MyMass *tmpm2,F64 tons) { MyMass *tmpm; CD3 p1; F64 d; tmpm=ode->next_mass; while (tmpm!=&ode->next_mass) { if (tmpm!=tmpm1 && tmpm!=tmpm2) { D3Sub(&p1,&tmpm->state->x,&tmpm1->state->x); d=D3NormSqr(&p1)-tmpm->radius*tmpm->radius; if (d<100.0*100.0) { if (d<1) d=1; else d=Sqrt(d); d=250000*tons/d`2; D3MulEqu(&p1,d); D3AddEqu(&tmpm->DstateDt->DxDt,&p1); } } tmpm=tmpm->next; } } Ship TargetGet(Missile *tmpmi) { Ship *tmpsp,*res=NULL; F64 dd,best_dd=F64_MAX; I64 i; CD3 p,p1,p2; D3Unit(D3Sub(&p,&tmpmi->p_front.state->x,&tmpmi->p_back.state->x)); tmpsp=ship_head.next; while (tmpsp!=&ship_head) { if (!tmpsp->exploding && tmpsp!=tmpmi->owner) for (i=0;i<tmpsp->masses;i++) { D3Sub(&p1,&tmpsp->p[i].state->x,&tmpmi->p_front.state->x); D3Unit(D3Copy(&p2,&p1)); D3Cross(&p1,&p,&p2); if (D3Dot(&p,&p2)>0 && D3Norm(&p1)<=pi/16) { dd=D3NormSqr(&p1); if (dd<best_dd) { best_dd=dd; res=tmpsp; } } } tmpsp=tmpsp->next; } return res; } U0 MyDerivative(CMathODE *ode,F64,COrder2D3 *,COrder2D3 *) { I64 i; F64 d,dd,dd2,spin,t_left,t_right,theta_err,theta_thrust,DthetaDt; CTask *task=ode->win_task; CD3 p,p1,p2; Ship *tmpsp; Missile *tmpmi; MyMass *tmpm,*tmpm1; tmpm=ode->next_mass; while (tmpm!=&ode->next_mass) { if (tmpm->type!=MT_SOLAR_FLARE && tmpm->type!=MT_ION) { d=tmpm->state->x; if (d-tmpm->radius<0) tmpm->DstateDt->DxDt+=Sqr(Sqr(Sqr(d-tmpm->radius))); if (d+tmpm->radius>task->pix_width) tmpm->DstateDt->DxDt-=Sqr(Sqr(Sqr((d+tmpm->radius)-task->pix_width))); d=tmpm->state->y; if (d-tmpm->radius<0) tmpm->DstateDt->DyDt+=Sqr(Sqr(Sqr(d-tmpm->radius))); if (d+tmpm->radius>task->pix_height) tmpm->DstateDt->DyDt-=Sqr(Sqr(Sqr((d+tmpm->radius)-task->pix_height))); } if (tmpm->type!=MT_ION && tmpm->type!=MT_ANTIMATTER_SPLAT) { tmpm1=ode->next_mass; while (tmpm1!=&ode->next_mass) { if (tmpm!=tmpm1) { if (tmpm1->type==MT_ANTIMATTER_SPLAT) { if (tmpm->type==MT_HUMAN_SHIP || tmpm->type==MT_ENEMY_SHIP) { D3Sub(&p,&tmpm->state->x,&tmpm1->state->x); dd=D3NormSqr(&p)+1; if (dd<100000) { D3MulEqu(&p,100000/dd); D3AddEqu(&tmpm1->DstateDt->DxDt,&p); } } } else if (tmpm1->type!=MT_ION) { D3Sub(&p,&tmpm->state->x,&tmpm1->state->x); dd=D3NormSqr(&p); dd2=Sqr(tmpm->radius+tmpm1->radius); if (dd<=dd2) { d=Sqrt(dd)+0.0001; D3MulEqu(&p,Sqr(Sqr(dd2-dd))/d); D3AddEqu(&tmpm ->DstateDt->DxDt,&p); D3SubEqu(&tmpm1->DstateDt->DxDt,&p); } } } tmpm1=tmpm1->next; } } tmpm=tmpm->next; } tmpsp=ship_head.next; while (tmpsp!=&ship_head) { if (tmpsp->exploding && tmpsp->die_time<=tS<=tmpsp->die_timeout) for (i=0;i<tmpsp->masses;i++) Explosion(&tmpsp->p[i],NULL,tmpsp->p[i].radius/250.0); switch (tmpsp->type) { case ST_HUMAN1: if (!tmpsp->exploding) { if (tmpsp->spacewalk_side) { t_left=0; t_right=0; d=1.0-(tmpsp->spacewalk_timeout-tS)/SPACEWALK_TIME; if (0.485<d<0.515) { D3Unit(D3Sub(&p,&tmpsp->p[2].state->x,&tmpsp->p[1].state->x)); if (tmpsp->spacewalk_side==3) { tmpsp->p[3].DstateDt->DxDt-=10*THRUST_MAX*p.x; tmpsp->p[3].DstateDt->DyDt-=10*THRUST_MAX*p.y; tmpsp->p[1].DstateDt->DxDt+=10*THRUST_MAX*p.x; tmpsp->p[1].DstateDt->DyDt+=10*THRUST_MAX*p.y; } else { tmpsp->p[4].DstateDt->DxDt+=10*THRUST_MAX*p.x; tmpsp->p[4].DstateDt->DyDt+=10*THRUST_MAX*p.y; tmpsp->p[2].DstateDt->DxDt-=10*THRUST_MAX*p.x; tmpsp->p[2].DstateDt->DyDt-=10*THRUST_MAX*p.y; } } } else { if (d=D3Norm(D3Sub(&p1,&tmpsp->p[0].state->x, &tmpsp->p[1].state->x))) { D3Sub(&p2,&tmpsp->p[0].state->DxDt,&tmpsp->p[1].state->DxDt); D3Cross(&p,&p1,&p2); spin=p.z/d; } else spin=0; t_left =Clamp(human_t_left+SPIN_GAIN*spin*human_antispin, 0,THRUST_MAX); if (d=D3Norm(D3Sub(&p1,&tmpsp->p[0].state->x, &tmpsp->p[2].state->x))) { D3Sub(&p2,&tmpsp->p[0].state->DxDt,&tmpsp->p[2].state->DxDt); D3Cross(&p,&p1,&p2); spin=p.z/d; } else spin=0; t_right=Clamp(human_t_right-SPIN_GAIN*spin*human_antispin, 0,THRUST_MAX); D3Sub(&p1,&tmpsp->p[0].state->x,&tmpsp->p[1].state->x); D3Sub(&p2,&tmpsp->p[0].state->x,&tmpsp->p[2].state->x); D3Unit(D3Add(&p,&p1,&p2)); if (!(tmpsp->s[3].flags&SSF_INACTIVE)) { D3Mul(&p1,t_left,&p); D3AddEqu(&tmpsp->p[3].DstateDt->DxDt,&p1); } if (!(tmpsp->s[5].flags&SSF_INACTIVE)) { D3Mul(&p2,t_right,&p); D3AddEqu(&tmpsp->p[4].DstateDt->DxDt,&p2); } } } break; } tmpsp=tmpsp->next; } tmpmi=missile_head.next; while (tmpmi!=&missile_head) { if (tmpmi->active) { if (tmpmi->launched) { if (tmpmi->exploding) Explosion(&tmpmi->p_front,&tmpmi->p_back,tmpmi->tons); else { //Guide missile if (tmpsp=tmpmi->target) { D3Unit(D3Sub(&p,&tmpmi->p_front.state->x, &tmpmi->p_back.state->x)); D3Sub(&p1,&tmpsp->p[0].state->x,&tmpmi->p_front.state->x); d=D3Norm(&p1); D3Unit(&p1); theta_err=D3Dot(&p,&p1); D3Sub(&p1,&tmpmi->p_front.state->DxDt,&tmpmi->p_back.state->DxDt); D3Cross(&p2,&p,&p1); DthetaDt=D3Norm(&p2); if (p2.z<0) DthetaDt=-DthetaDt; theta_thrust=Clamp(200*(theta_err+2*DthetaDt)/(d+200),-pi/8,pi/8); p2.x=p.x*Cos(theta_thrust)-p.y*Sin(theta_thrust); p2.y=p.y*Cos(theta_thrust)+p.x*Sin(theta_thrust); p2.z=0; D3AddEqu(&tmpmi->p_back.DstateDt->DxDt,D3MulEqu(&p2,THRUST_MAX)); } } } else tmpmi->target=TargetGet(tmpmi); } else tmpmi->target=NULL; tmpmi=tmpmi->next; } } U0 CheckDamage() { I64 i,j,death_score; Ship *tmpsp,*tmpsp1; MyMass *tmpm,*tmpm1,*best_mass; CD3 p,p1,p2; F64 d,best_distance; Bool facing_sun=FALSE; if (human) { D3Sub(&p1,&human->p[1].x,&human->p[0].x); D3Sub(&p2,&human->p[2].x,&human->p[0].x); D3Add(&p,&p1,&p2); if (p.x>0) facing_sun=TRUE; } tmpm=ode->next_mass; while (tmpm!=&ode->next_mass) { if (tmpm->type==MT_ION) { if (facing_sun) { tmpm1=ode->next_mass; while (tmpm1!=&ode->next_mass) { if (tmpm1->type==MT_HUMAN_SHIP) { D3Sub(&p,&tmpm1->x,&tmpm->x); if (D3NormSqr(&p)<Sqr(tmpm1->radius)) tmpm1->temperature+=3.0; } tmpm1=tmpm1->next; } } } else if (tmpm->type==MT_ANTIMATTER_SPLAT) { tmpm1=ode->next_mass; while (tmpm1!=&ode->next_mass) { if (tmpm1->type!=MT_ION && tmpm1->type!=MT_ANTIMATTER_SPLAT) { D3Sub(&p,&tmpm1->x,&tmpm->x); if (D3NormSqr(&p)<Sqr(tmpm1->radius)) tmpm1->temperature+=0.4; } tmpm1=tmpm1->next; } } else tmpm->temperature*=0.9; tmpm=tmpm->next; } if (human) { human->laser_temperature*=0.975; if (human->laser_overheat) { if (human->laser_temperature<LASER_THRESHOLD_TEMP) human->laser_overheat=FALSE; } if (!human->laser_overheat && human->lasering) { if (human->laser_temperature>=LASER_TEMP_MAX) { human->laser_overheat=TRUE; Snd; } else { human->laser_temperature+=1.0; D3Sub(&p1,&human->p[0].x,&human->p[1].x); D3Sub(&p2,&human->p[0].x,&human->p[2].x); D3Unit(D3Add(&p,&p1,&p2)); p2.x=p.y; p2.y=-p.x; p2.z=0; best_mass=NULL; best_distance=F64_MAX; tmpm=ode->next_mass; while (tmpm!=&ode->next_mass) { D3Sub(&p1,&human->p[0].x,&tmpm->x); if (Abs(D3Dot(&p1,&p2))<tmpm->radius && D3Dot(&p1,&p)<0.0) { d=D3NormSqr(&p1); if (d<best_distance) { best_distance=d; best_mass=tmpm; } } tmpm=tmpm->next; } if (best_mass) best_mass->temperature+=1.0; } } } tmpsp=ship_head.next; while (tmpsp!=&ship_head) { tmpsp1=tmpsp->next; death_score=0; switch (tmpsp->type) { case ST_HUMAN1: if (tmpsp->exploding) { if (tS>tmpsp->die_timeout) { ShipDel(tmpsp); human=NULL; } } else for (i=0;i<tmpsp->springs;i++) { if (Abs(tmpsp->s[i].f)>tmpsp->s[i].strength) { tmpsp->s[i].flags|=SSF_INACTIVE; if (i==4) MissileDel(&tmpsp->missiles[0]); else if (i==5) MissileDel(&tmpsp->missiles[1]); } if (tmpsp->s[i].flags&SSF_INACTIVE && i<3) death_score++; } break; default: if (tmpsp->exploding) { if (tS>tmpsp->die_timeout) { ShipDel(tmpsp); score+=level; if (score>best_score) best_score=score; } } else { j=0; for (i=0;i<tmpsp->springs;i++) { if (tmpsp->s[i].flags&SSF_INACTIVE) j++; else if (Abs(tmpsp->s[i].f)>tmpsp->s[i].strength) { tmpsp->s[i].flags|=SSF_INACTIVE; j++; } } if (j>1) death_score++; } } if (!tmpsp->exploding) { for (i=0;i<tmpsp->masses;i++) if (tmpsp->p[i].temperature>MASS_TEMP_MAX) death_score++; if (death_score) { tmpsp->exploding=TRUE; tmpsp->die_time=tS; tmpsp->die_timeout=tS+0.75; Noise(750,74,93); if (tmpsp->type==ST_HUMAN1) game_over=TRUE; } } tmpsp=tmpsp1; } } //********************************** Shots Shot *ShotNew(I64 type,CD3 *_p,CD3 *_v,F64 r,F64 fuse_time, CD3 *_p_gun_offset=NULL) { Shot *tmps=CAlloc(sizeof(Shot)); D3Copy(&tmps->p.x,_p); tmps->radius=r; tmps->splats=20*r; tmps->fuse_time=tS+fuse_time; tmps->p.mass=0.3*r*r*r; tmps->p.type=type; if (_p_gun_offset) D3AddEqu(&tmps->p.x,_p_gun_offset); D3Copy(&tmps->p.DxDt,_v); QueIns(&tmps->p,ode->last_mass); QueIns(tmps,shot_head.last); } U0 SolarFlares() { CD3 p,v,p1,p2; CTask *task=ode->win_task; if (!alarm && t_solar_storm-2.0<tS<t_solar_storm+1.0) { Sweep(2000,74,93); alarm=TRUE; } if (t_solar_storm<tS) { //If solar storm has arrived if (tS<t_solar_storm+5.0) { //If solar storm not over if (Rand<.1) { D3Equ(&p,-300,Rand*task->pix_height,0); D3Equ(&v,200.0,0,0); ShotNew(MT_SOLAR_FLARE,&p,&v,25,0.1); } } else { t_solar_storm=tS+25*Rand; //Schedule next solar storm alarm=FALSE; } } } U0 FireOneGun(Ship *tmpsp,I64 n,F64 r,F64 fuse_time) { I64 ona; CD3 p,v,p1,p2; Shot *tmps; D3Sub(&p1,&tmpsp->p[0].x,&tmpsp->p[1].x); D3Sub(&p2,&tmpsp->p[0].x,&tmpsp->p[2].x); D3Unit(D3Add(&p,&p1,&p2)); D3MulEqu(D3Copy(&p1,&p),r+tmpsp->p[0].radius+5); D3AddEqu(D3MulEqu(D3Copy(&v,&p),1000/(r+1)),&tmpsp->p[n].DxDt); tmps=ShotNew(MT_ANTIMATTER_BALL,&tmpsp->p[n].x,&v,r,fuse_time,&p1); D3MulEqu(&p,tmps->p.mass/tmpsp->p[n].mass/100.0); D3SubEqu(&tmpsp->p[n].DxDt,&p); tmpsp->reload_timeout=tS+r/tmpsp->fire_rate; ona=Freq2Ona(500/r); Noise(100,ona,ona+12); } U0 FireOneMissile(Ship *tmpsp,I64 n) { I64 i; Missile *tmpmi=&tmpsp->missiles[n]; if (!tmpmi->launched && tmpmi->target) { tmpmi->fuse_time=tS+1.0; tmpmi->die_timeout=tmpmi->fuse_time+0.125; tmpmi->img=<8>; for (i=1;i<5;i++) tmpmi->s[i].flags|=SSF_INACTIVE; tmpmi->launched=TRUE; Sweep(250,53,56); } } U0 HumanFireGunBegin() { F64 r=3.0*ctrl_panel.shot_radius/CTRL_PANEL_RANGE+0.5, fuse_time=ToF64(ctrl_panel.fuse_time+1)/CTRL_PANEL_RANGE; if (human) { if (!human->exploding && !human->spacewalk_side && tS>human->reload_timeout) switch (level) { case 3: if (!(human->s[3].flags&SSF_INACTIVE)) FireOneGun(human,3,r,fuse_time); if (!(human->s[5].flags&SSF_INACTIVE)) FireOneGun(human,4,r,fuse_time); case 2: if (!(human->s[1].flags&SSF_INACTIVE)) FireOneGun(human,1,r,fuse_time); if (!(human->s[2].flags&SSF_INACTIVE)) FireOneGun(human,2,r,fuse_time); case 1: FireOneGun(human,0,r,fuse_time); break; } } } U0 HumanFireMissileBegin(I64 n) { if (human && !human->exploding && !human->spacewalk_side && tS>human->reload_timeout) FireOneMissile(human,n); } U0 HumanFireLaserBegin() { if (human && !human->exploding && !human->spacewalk_side && tS>human->reload_timeout) human->lasering=TRUE; } U0 HumanFireLaserEnd() { if (human && !human->exploding) { human->lasering=FALSE; Snd; } } U0 SplatNew(Shot *tmps,F64 die_time,F64 start,F64 end) { MyMass *tmpm; F64 theta=Arg(tmps->p.DxDt,tmps->p.DyDt); I64 i; for (i=0;i<tmps->splats;i++) { tmpm=CAlloc(sizeof(MyMass)); D3Copy(&tmpm->x,&tmps->p.x); tmpm->radius=1; tmpm->mass=1; tmpm->die_timeout=tS+die_time; if (tmps->p.type==MT_SOLAR_FLARE) tmpm->type=MT_ION; else tmpm->type=MT_ANTIMATTER_SPLAT; D3Copy(&tmpm->DxDt,&tmps->p.DxDt); tmpm->DxDt+=50*Sqr(tmps->radius)*Rand* Sin(start+theta+(end-start)*i/tmps->splats); tmpm->DyDt+=50*Sqr(tmps->radius)*Rand* Cos(start+theta+(end-start)*i/tmps->splats); QueIns(tmpm,ode->last_mass); } } U0 ExpireShots() { Shot *tmps=shot_head.next,*tmps1; while (tmps!=&shot_head) { tmps1=tmps->next; if (tS>tmps->fuse_time) { if (tmps->p.type==MT_SOLAR_FLARE) SplatNew(tmps,1.0,3*pi/8,5*pi/8); else SplatNew(tmps,.2,0,2*pi); QueRem(tmps); QueRem(&tmps->p); Free(tmps); } tmps=tmps1; } } U0 ExpireSplats() { MyMass *tmpm,*tmpm1; tmpm=ode->next_mass; while (tmpm!=&ode->next_mass) { tmpm1=tmpm->next; if ((tmpm->type==MT_ION || tmpm->type==MT_ANTIMATTER_SPLAT) && tS>tmpm->die_timeout) { QueRem(tmpm); Free(tmpm); } tmpm=tmpm1; } } U0 ExpireMissiles() { I64 i; F64 dd,best_dd; Missile *tmpmi=missile_head.next,*tmpm1; while (tmpmi!=&missile_head) { tmpm1=tmpmi->next; if (tmpmi->launched) { best_dd=F64_MAX; if (tmpmi->target) for (i=0;i<tmpmi->target->masses;i++) { dd=D3DistSqr(&tmpmi->p_front.x,&tmpmi->target->p[i].x); if (dd<best_dd) best_dd=dd; } if (!tmpmi->exploding && (best_dd<30*30 || tS>tmpmi->fuse_time)) { tmpmi->p_front.mass=10.0; //They go flying, if too light. tmpmi->p_back.mass =10.0; tmpmi->exploding=TRUE; Noise(50,93,105); } else if (tS>tmpmi->die_timeout) MissileDel(tmpmi); } tmpmi=tmpm1; } } //********************************** AI U0 AI() { CD3 p,p1,p2; Ship *tmpsp=ship_head.next; if (human && !human->exploding) { while (tmpsp!=&ship_head) { D3Sub(&p1,&tmpsp->p[0].x,&tmpsp->p[1].x); D3Sub(&p2,&tmpsp->p[0].x,&tmpsp->p[2].x); D3Add(&p,&p1,&p2); D3Sub(&p1,&human->p[0].x,&tmpsp->p[0].x); if (D3Dot(D3Unit(&p),D3Unit(&p1))>0.995 && tS>tmpsp->reload_timeout) { FireOneGun(tmpsp,0,1.5+.5,.4); } tmpsp=tmpsp->next; } } } //********************************** Init U0 InitLevel() { I64 i; MyMass *tmpm,*tmpm1; t_solar_storm=0; tmpm=ode->next_mass; while (tmpm!=&ode->next_mass) { tmpm1=tmpm->next; if (tmpm->type==MT_ION || tmpm->type==MT_ANTIMATTER_SPLAT) { QueRem(tmpm); Free(tmpm); } tmpm=tmpm1; } if (level==1) OneTimePopUp(&msg_flags,XMSGF_SOLAR_STORM, "Face away from Sun in solar storm.\n"); if (level==4) OneTimePopUp(&msg_flags,XMSGF_ANTISPIN, "Press $GREEN$<CURSOR-DOWN>$FG$ for anti-spin stabilizer.\n"); human=ShipNew(Fs->pix_width/2,Fs->pix_height/2,ST_HUMAN1); for (i=0;i<level+2;i++) PlaceShip(ST_ENEMY1); PlaceShip(ST_ENEMY2); show_level_msg=TRUE; ODEPause(ode); } U0 Init() { I64 i; game_over=FALSE; score=0; level=1; QueInit(&ship_head); QueInit(&shot_head); QueInit(&missile_head); for (i=0;i<STARS_NUM;i++) { stars_x[i]=RandU16%GR_WIDTH; stars_y[i]=RandU16%GR_HEIGHT; } human_t_left=0; human_t_right=0; human_antispin=0; InitLevel; } //********************************** Main U0 XCaliber() { I64 ch,msg_code,arg1,arg2,sc; CCtrl *cp=CtrlPanelNew; SettingsPush; //See SettingsPush Fs->text_attr=BLACK<<4+WHITE; MenuPush( "File {" " Abort(,CH_SHIFT_ESC);" " Exit(,CH_ESC);" "}" "Game {" " Restart(,'\n');" " LevelUp(,'+');" " LevelDown(,'-');" "}" "Play {" " Fire(,CH_SPACE);" " Thrust(,,SC_CURSOR_UP);" " StopSpin(,,SC_CURSOR_DOWN);" " Left(,,SC_CURSOR_LEFT);" " Right(,,SC_CURSOR_RIGHT);" " LeftMissile(,,SC_CURSOR_LEFT|SCF_CTRL);" " RightMissile(,,SC_CURSOR_RIGHT|SCF_CTRL);" " Spackwalk(,'w');" " LongerFuse(,,SC_CURSOR_RIGHT|SCF_SHIFT);" " ShorterFuse(,,SC_CURSOR_LEFT|SCF_SHIFT);" " LargerShot(,,SC_CURSOR_UP|SCF_SHIFT);" " SmallerShot(,,SC_CURSOR_DOWN|SCF_SHIFT);" "}" ); AutoComplete; WinBorder; WinMax; DocCursor; DocClear; Fs->win_inhibit=WIG_TASK_DFT-WIF_SELF_FOCUS -WIF_SELF_BORDER-WIF_FOCUS_TASK_MENU-WIF_SELF_CTRLS; Fs->draw_it=&DrawIt; do { ode=ODENew(0,0.01,ODEF_HAS_MASSES); ode->derive=&MyDerivative; ode->min_tolerance=1e-9; ode->drag_v3=0.00001; Init; QueIns(ode,Fs->last_ode); ch=0; do { while (!game_over && !show_level_msg && (msg_code=ScanMsg(&arg1,&arg2,1<<MSG_KEY_DOWN|1<<MSG_KEY_UP))) { switch (msg_code) { case MSG_KEY_DOWN: ch=arg1; sc=arg2; switch (ch) { case 0: switch (sc.u8[0]) { case SC_CURSOR_RIGHT: if (sc&SCF_CTRL) HumanFireMissileBegin(0); else if (sc&SCF_SHIFT) ctrl_panel.fuse_time+=2; else human_t_right=THRUST_MAX; break; case SC_CURSOR_LEFT: if (sc&SCF_CTRL) HumanFireMissileBegin(1); else if (sc&SCF_SHIFT) ctrl_panel.fuse_time-=2; else human_t_left =THRUST_MAX; break; case SC_CURSOR_UP: if (sc&SCF_SHIFT) ctrl_panel.shot_radius+=2; else { human_t_right=THRUST_MAX; human_t_left =THRUST_MAX; } break; case SC_CURSOR_DOWN: if (sc&SCF_SHIFT) ctrl_panel.shot_radius-=2; else human_antispin=ANTISPIN_MAX; break; } break; case CH_SPACE: if (level<4) HumanFireGunBegin; else HumanFireLaserBegin; break; case 'w': ctrl_panel.spacewalk=TRUE; break; case '+': level++; break; case '-': level--; break; } break; case MSG_KEY_UP: ch=arg1; sc=arg2; switch (ch) { case 0: switch (sc.u8[0]) { case SC_CURSOR_RIGHT: human_t_right=0; break; case SC_CURSOR_LEFT: human_t_left =0; break; case SC_CURSOR_UP: human_t_right=0; human_t_left =0; break; case SC_CURSOR_DOWN: human_antispin=0; break; } break; case '\n': ch=0; break; case CH_SPACE: if (level>=4) HumanFireLaserEnd; break; } break; } } AI; SolarFlares; ExpireShots; ExpireSplats; ExpireMissiles; CheckDamage; Refresh; //msgs are only qued by winmgr if (show_level_msg) { ch=GetKey(&sc); if (ch=='\n') ch=0; ODEPause(ode,OFF); show_level_msg=FALSE; } else if (game_over) { ch=ScanChar; } else { if (!remaining) { level++; ShipDel(human); human=NULL; InitLevel; } } } while (ch!=CH_ESC && ch!='\n' && ch!=CH_SHIFT_ESC); AllDel(ode); } while (ch!=CH_ESC && ch!=CH_SHIFT_ESC); SettingsPop; CtrlPanelDel(cp); MenuPop; RegWrite("TempleOS/XCaliber", "I64 best_score=%d;\n" "I64 msg_flags=%d;\n",best_score,msg_flags); }