395 lines
18 KiB
C++
395 lines
18 KiB
C++
RegSetDftEntry("TempleOS/BomberGolf","I64 best_score=99999;\n");
|
|
RegExeBranch("TempleOS/BomberGolf");
|
|
|
|
|
|
|
|
$SP,"<1>",BI=1$
|
|
|
|
|
|
|
|
|
|
$SP,"<2>",BI=2$
|
|
|
|
|
|
|
|
$SP,"<3>",BI=3$
|
|
|
|
|
|
$SP,"<4>",BI=4$
|
|
|
|
|
|
$SP,"<5>",BI=5$
|
|
|
|
|
|
|
|
$SP,"<6>",BI=6$
|
|
|
|
|
|
|
|
|
|
$SP,"<7>",BI=7$
|
|
|
|
|
|
|
|
|
|
$SP,"<8>",BI=8$
|
|
|
|
|
|
|
|
|
|
$SP,"<9>",BI=9$
|
|
|
|
|
|
|
|
|
|
$SP,"<10>",BI=10$
|
|
|
|
|
|
#define MAP_WIDTH 600
|
|
#define MAP_HEIGHT 600
|
|
|
|
#define NUM_TREES 64
|
|
class Tree
|
|
{
|
|
I64 x,y;
|
|
} trees[NUM_TREES];
|
|
|
|
|
|
I64 target_cnt,key_cnt;
|
|
|
|
|
|
#define NUM_TARGETS 10
|
|
|
|
#define MDF_TANK 0
|
|
#define MDF_BUNKER 1
|
|
|
|
#define TANK_V 10.0
|
|
|
|
class Target
|
|
{
|
|
F64 x,y,é;
|
|
CSprite *alive_img,*dead_img1,*dead_img2;
|
|
U8 type;
|
|
Bool dead,pad[6];
|
|
} targets[NUM_TARGETS];
|
|
|
|
#define FALL_TIME 3.00
|
|
#define EXPLODE_TIME 0.25
|
|
class Bomb
|
|
{
|
|
Bomb *next,*last;
|
|
F64 x,y,t;
|
|
Bool exploding;
|
|
} bomb_root;
|
|
|
|
F64 v,x,y,
|
|
é,éf; //éf is the final theta. é is gradually changed until it reaches éf.
|
|
|
|
U0 DrawIt(CTask *task,CDC *dc)
|
|
{
|
|
I64 i,j;
|
|
Bomb *tempb;
|
|
Target *tempt;
|
|
F64 ts=tS,dx,dy;
|
|
|
|
dc->color=ROPF_DITHER|BROWN<<16|YELLOW;
|
|
GrRect3(dc,0,0,0,dc->width,dc->height);
|
|
|
|
dc->x=task->pix_width>>1;
|
|
dc->y=task->pix_height>>1;
|
|
dc->flags|=DCF_TRANSFORMATION;
|
|
Mat4x4TranslationEqu(dc->r,x,y,0);
|
|
Mat4x4RotZ(dc->r,é);
|
|
dc->color=BLACK;
|
|
GrBorder(dc,-MAP_WIDTH>>1,-MAP_HEIGHT>>1,MAP_WIDTH>>1,MAP_HEIGHT>>1);
|
|
for (i=0;i<NUM_TARGETS;i++) {
|
|
tempt=&targets[i];
|
|
if (tempt->dead) {
|
|
if (i&1) {
|
|
dc->flags|=DCF_SYMMETRY|DCF_JUST_MIRROR;
|
|
DCSymmetry3Set(dc,tempt->x,tempt->y,0,tempt->x,tempt->y,1,
|
|
tempt->x+1024*Cos(tempt->é),tempt->y+1024*Sin(tempt->é),0);
|
|
}
|
|
if (Blink(15))
|
|
SpriteZ3B(dc,tempt->x,tempt->y,0,tempt->dead_img1,tempt->é);
|
|
else
|
|
SpriteZ3B(dc,tempt->x,tempt->y,0,tempt->dead_img2,tempt->é);
|
|
dc->flags&=~(DCF_SYMMETRY|DCF_JUST_MIRROR);
|
|
} else
|
|
SpriteZ3B(dc,tempt->x,tempt->y,0,tempt->alive_img,tempt->é);
|
|
}
|
|
|
|
for (i=0;i<NUM_TREES;i++)
|
|
Sprite3(dc,trees[i].x,trees[i].y,0,$IB,"<2>",BI=2$);
|
|
|
|
for (i=0;i<NUM_TARGETS;i++) {
|
|
tempt=&targets[i];
|
|
if (tempt->dead) {
|
|
for (j=0;j<40;j++) {
|
|
dc->pen_width=4;
|
|
if (j&1)
|
|
dc->color=ROPF_DITHER|LTGRAY<<16|BLACK;
|
|
else
|
|
dc->color=ROPF_DITHER|DKGRAY<<16|LTGRAY;
|
|
dx=15*Sin(ts/4+j<<6)+j>>2;
|
|
dy=10*FullTri(ts/3+j/2.0,20)+j>>2;
|
|
GrPlot3(dc,tempt->x+5+dx+0.5*dy,tempt->y+0.5*dx+dy,0);
|
|
}
|
|
}
|
|
}
|
|
|
|
tempb=bomb_root.next;
|
|
while (tempb!=&bomb_root) {
|
|
if (tempb->t+FALL_TIME<tS) {
|
|
if (Blink(10))
|
|
Sprite3(dc,tempb->x,tempb->y,0,$IB,"<9>",BI=9$);
|
|
else
|
|
Sprite3(dc,tempb->x,tempb->y,0,$IB,"<10>",BI=10$);
|
|
}
|
|
tempb=tempb->next;
|
|
}
|
|
|
|
dc->flags&=~DCF_TRANSFORMATION;
|
|
Sprite3(dc,task->pix_width>>1,task->pix_height>>1,0,$IB,"<1>",BI=1$);
|
|
dc->color=RED;
|
|
GrPrint(dc,0,0,"Targets:%02d KeyStrokes:%04d Best:%04d",
|
|
target_cnt,key_cnt,best_score);
|
|
if (!target_cnt && Blink(4))
|
|
GrPrint(dc,(task->pix_width-FONT_WIDTH*14)>>1,
|
|
(task->pix_height-FONT_HEIGHT)>>1-32,"Game Completed");
|
|
}
|
|
|
|
U0 BombHit(Bomb *tempb)
|
|
{
|
|
I64 i;
|
|
for (i=0;i<NUM_TARGETS;i++) {
|
|
if (!targets[i].dead &&
|
|
SqrI64(tempb->x-targets[i].x)+SqrI64(tempb->y-targets[i].y)<20*20) {
|
|
targets[i].dead=TRUE;
|
|
target_cnt--;
|
|
}
|
|
}
|
|
QueRem(tempb);
|
|
Free(tempb);
|
|
}
|
|
|
|
U0 BombDrop(F64 x,F64 y)
|
|
{
|
|
I64 i;
|
|
Bomb *tempb=MAlloc(sizeof(Bomb));
|
|
tempb->x=x;
|
|
tempb->y=y;
|
|
tempb->t=tS;
|
|
tempb->exploding=FALSE;
|
|
QueIns(tempb,bomb_root.last);
|
|
Sweep(FALL_TIME*1000,1000,500);
|
|
}
|
|
|
|
I64 AnimateTask(CTask *parent)
|
|
{
|
|
I64 i,w=parent->pix_width,h=parent->pix_height;
|
|
Bomb *tempb,*tempb1;
|
|
Target *tempt;
|
|
while (TRUE) {
|
|
if (bomb_root.next==&bomb_root) {
|
|
if (target_cnt)
|
|
Snd(100+60*Clamp(0.1*(1.0+Abs(Wrap(éf-é,-ã)))`4.0,-3,3));
|
|
else if (key_cnt<best_score) {
|
|
best_score=key_cnt;
|
|
Sleep(150); Snd(1000);Sleep(150);Snd(0);
|
|
Sleep(150); Snd(1000);Sleep(150);Snd(0);
|
|
} else
|
|
Snd(0);
|
|
}
|
|
|
|
é+=0.01*(éf-é);
|
|
x+=0.01*v*Sin(é);
|
|
y+=0.01*v*Cos(é);
|
|
|
|
for (i=0;i<NUM_TARGETS;i++) {
|
|
tempt=&targets[i];
|
|
if (!tempt->dead && tempt->type==MDF_TANK) {
|
|
tempt->x+=0.01*TANK_V*Cos(tempt->é);
|
|
tempt->y+=0.01*TANK_V*Sin(tempt->é);
|
|
if (i&1)
|
|
tempt->é+=0.01*ã/16;
|
|
else
|
|
tempt->é-=0.01*ã/16;
|
|
}
|
|
}
|
|
|
|
tempb=bomb_root.next;
|
|
while (tempb!=&bomb_root) {
|
|
tempb1=tempb->next;
|
|
if (tempb->t+FALL_TIME+EXPLODE_TIME<tS)
|
|
BombHit(tempb);
|
|
else if (tempb->t+FALL_TIME<tS && !tempb->exploding) {
|
|
Noise(EXPLODE_TIME*1000,500,1000);
|
|
tempb->exploding=TRUE;
|
|
}
|
|
tempb=tempb1;
|
|
}
|
|
|
|
Sleep(10);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
U0 Init()
|
|
{
|
|
I64 i;
|
|
Target *tempt;
|
|
|
|
v=20;
|
|
x=-MAP_WIDTH>>1;
|
|
y=-MAP_HEIGHT>>1;
|
|
éf=é=1*ã/4;
|
|
|
|
QueInit(&bomb_root);
|
|
|
|
MemSet(trees,0,sizeof(trees));
|
|
for (i=0;i<NUM_TREES;i++) {
|
|
trees[i].x=RandU32%MAP_WIDTH -MAP_WIDTH >>1;
|
|
trees[i].y=RandU32%MAP_HEIGHT-MAP_HEIGHT>>1;
|
|
}
|
|
|
|
MemSet(targets,0,sizeof(targets));
|
|
for (i=0;i<NUM_TARGETS;i++) {
|
|
tempt=&targets[i];
|
|
tempt->x=RandU32%MAP_WIDTH -MAP_WIDTH >>1;
|
|
tempt->y=RandU32%MAP_HEIGHT-MAP_HEIGHT>>1;
|
|
if (i<NUM_TARGETS/3) {
|
|
tempt->type=MDF_BUNKER;
|
|
tempt->é=(RandU16&3)*ã/2;
|
|
tempt->alive_img=$IB,"<6>",BI=6$;
|
|
tempt->dead_img1=$IB,"<7>",BI=7$;
|
|
tempt->dead_img2=$IB,"<8>",BI=8$;
|
|
} else {
|
|
tempt->type=MDF_TANK;
|
|
tempt->é=Rand*2*ã;
|
|
tempt->alive_img=$IB,"<3>",BI=3$;
|
|
tempt->dead_img1=$IB,"<4>",BI=4$;
|
|
tempt->dead_img2=$IB,"<5>",BI=5$;
|
|
}
|
|
}
|
|
key_cnt=0;
|
|
target_cnt=NUM_TARGETS;
|
|
}
|
|
|
|
U0 CleanUp()
|
|
{
|
|
QueDel(&bomb_root,TRUE);
|
|
}
|
|
|
|
U0 BomberGolf()
|
|
{
|
|
I64 sc;
|
|
MenuPush(
|
|
"File {"
|
|
" Abort(,CH_SHIFT_ESC);"
|
|
" Exit(,CH_ESC);"
|
|
"}"
|
|
"Play {"
|
|
" Restart(,'\n');"
|
|
" Faster(,,SC_CURSOR_UP);"
|
|
" Slower(,,SC_CURSOR_DOWN);"
|
|
" Left(,,SC_CURSOR_LEFT);"
|
|
" Right(,,SC_CURSOR_RIGHT);"
|
|
" Bomb(,CH_SPACE);"
|
|
"}"
|
|
);
|
|
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
|
AutoComplete;
|
|
WinBorder;
|
|
WinMax;
|
|
DocCursor;
|
|
DocClear;
|
|
Fs->animate_task=Spawn(&AnimateTask,Fs,"Animate",,Fs);
|
|
Fs->draw_it=&DrawIt;
|
|
Init;
|
|
try {
|
|
while (TRUE)
|
|
switch (GetKey(&sc)) {
|
|
case 0:
|
|
switch (sc.u8[0]) {
|
|
case SC_CURSOR_UP:
|
|
v+=10;
|
|
if (v>300) v=300;
|
|
break;
|
|
case SC_CURSOR_DOWN:
|
|
v-=10;
|
|
if (v<20) v=20;
|
|
break;
|
|
case SC_CURSOR_LEFT:
|
|
key_cnt++;
|
|
éf+=1.0/(Abs(Wrap(éf-é,-ã))+2*ã);
|
|
break;
|
|
case SC_CURSOR_RIGHT:
|
|
key_cnt++;
|
|
éf-=1.0/(Abs(Wrap(éf-é,-ã))+2*ã);
|
|
break;
|
|
|
|
}
|
|
break;
|
|
case CH_SPACE:
|
|
key_cnt++;
|
|
BombDrop(-x-0.8*FALL_TIME*v*Sin(é),-y-0.8*FALL_TIME*v*Cos(é));
|
|
break;
|
|
case '\n':
|
|
CleanUp;
|
|
Init;
|
|
break;
|
|
case CH_ESC:
|
|
case CH_SHIFT_ESC:
|
|
goto bm_done;
|
|
}
|
|
bm_done:
|
|
} catch
|
|
PutExcept;
|
|
CleanUp;
|
|
SettingsPop;
|
|
MenuPop;
|
|
RegWriteBranch("TempleOS/BomberGolf","I64 best_score=%d;\n",best_score);
|
|
}
|
|
|
|
BomberGolf;
|
|
|