398 lines
18 KiB
HolyC
398 lines
18 KiB
HolyC
|
RegDft("TempleOS/BomberGolf","I64 best_score=99999;\n");
|
|||
|
RegExe("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 TREES_NUM 64
|
|||
|
class Tree
|
|||
|
{
|
|||
|
I64 x,y;
|
|||
|
} trees[TREES_NUM];
|
|||
|
|
|||
|
|
|||
|
I64 target_cnt,key_cnt;
|
|||
|
|
|||
|
|
|||
|
#define TARGETS_NUM 10
|
|||
|
|
|||
|
#define MDF_TANK 0
|
|||
|
#define MDF_BUNKER 1
|
|||
|
|
|||
|
#define TANK_V 10.0
|
|||
|
|
|||
|
class Target
|
|||
|
{
|
|||
|
F64 x,y,<EFBFBD>;
|
|||
|
U8 *alive_img,*dead_img1,*dead_img2;
|
|||
|
U8 type;
|
|||
|
Bool dead,pad[6];
|
|||
|
} targets[TARGETS_NUM];
|
|||
|
|
|||
|
#define FALL_TIME 3.00
|
|||
|
#define EXPLODE_TIME 0.25
|
|||
|
class Bomb
|
|||
|
{
|
|||
|
Bomb *next,*last;
|
|||
|
F64 x,y,t;
|
|||
|
Bool exploding;
|
|||
|
} bomb_head;
|
|||
|
|
|||
|
F64 v,x,y,
|
|||
|
<EFBFBD>,<EFBFBD>f; //<2F>f is the final theta. <20> is gradually changed until it reaches <20>f.
|
|||
|
|
|||
|
U0 DrawIt(CTask *task,CDC *dc)
|
|||
|
{
|
|||
|
I64 i,j;
|
|||
|
Bomb *tmpb;
|
|||
|
Target *tmpt;
|
|||
|
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,<EFBFBD>);
|
|||
|
dc->color=BLACK;
|
|||
|
GrBorder(dc,-MAP_WIDTH>>1,-MAP_HEIGHT>>1,MAP_WIDTH>>1,MAP_HEIGHT>>1);
|
|||
|
for (i=0;i<TARGETS_NUM;i++) {
|
|||
|
tmpt=&targets[i];
|
|||
|
if (tmpt->dead) {
|
|||
|
if (i&1) {
|
|||
|
dc->flags|=DCF_SYMMETRY|DCF_JUST_MIRROR;
|
|||
|
DCSymmetry3Set(dc,tmpt->x,tmpt->y,0,tmpt->x,tmpt->y,1,
|
|||
|
tmpt->x+1024*Cos(tmpt-><EFBFBD>),tmpt->y+1024*Sin(tmpt-><EFBFBD>),0);
|
|||
|
}
|
|||
|
if (Blink(15))
|
|||
|
Sprite3ZB(dc,tmpt->x,tmpt->y,0,tmpt->dead_img1,tmpt-><EFBFBD>);
|
|||
|
else
|
|||
|
Sprite3ZB(dc,tmpt->x,tmpt->y,0,tmpt->dead_img2,tmpt-><EFBFBD>);
|
|||
|
dc->flags&=~(DCF_SYMMETRY|DCF_JUST_MIRROR);
|
|||
|
} else
|
|||
|
Sprite3ZB(dc,tmpt->x,tmpt->y,0,tmpt->alive_img,tmpt-><EFBFBD>);
|
|||
|
}
|
|||
|
|
|||
|
for (i=0;i<TREES_NUM;i++)
|
|||
|
Sprite3(dc,trees[i].x,trees[i].y,0,$IB,"<2>",BI=2$);
|
|||
|
|
|||
|
for (i=0;i<TARGETS_NUM;i++) {
|
|||
|
tmpt=&targets[i];
|
|||
|
if (tmpt->dead) {
|
|||
|
for (j=0;j<40;j++) {
|
|||
|
dc->thick=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,tmpt->x+5+dx+0.5*dy,tmpt->y+0.5*dx+dy,0);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
tmpb=bomb_head.next;
|
|||
|
while (tmpb!=&bomb_head) {
|
|||
|
if (tmpb->t+FALL_TIME<tS) {
|
|||
|
if (Blink(10))
|
|||
|
Sprite3(dc,tmpb->x,tmpb->y,0,$IB,"<9>",BI=9$);
|
|||
|
else
|
|||
|
Sprite3(dc,tmpb->x,tmpb->y,0,$IB,"<10>",BI=10$);
|
|||
|
}
|
|||
|
tmpb=tmpb->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 *tmpb)
|
|||
|
{
|
|||
|
I64 i;
|
|||
|
for (i=0;i<TARGETS_NUM;i++) {
|
|||
|
if (!targets[i].dead &&
|
|||
|
SqrI64(tmpb->x-targets[i].x)+SqrI64(tmpb->y-targets[i].y)<20*20) {
|
|||
|
targets[i].dead=TRUE;
|
|||
|
target_cnt--;
|
|||
|
}
|
|||
|
}
|
|||
|
QueRem(tmpb);
|
|||
|
Free(tmpb);
|
|||
|
}
|
|||
|
|
|||
|
U0 BombDrop(F64 x,F64 y)
|
|||
|
{
|
|||
|
Bomb *tmpb=MAlloc(sizeof(Bomb));
|
|||
|
tmpb->x=x;
|
|||
|
tmpb->y=y;
|
|||
|
tmpb->t=tS;
|
|||
|
tmpb->exploding=FALSE;
|
|||
|
QueIns(tmpb,bomb_head.last);
|
|||
|
Sweep(FALL_TIME*1000,74,62);
|
|||
|
}
|
|||
|
|
|||
|
I64 AnimateTask(CTask *)
|
|||
|
{
|
|||
|
F64 last_t=tS,dt;
|
|||
|
I64 i;
|
|||
|
Bomb *tmpb,*tmpb1;
|
|||
|
Target *tmpt;
|
|||
|
while (TRUE) {
|
|||
|
dt=tS-last_t;
|
|||
|
last_t=tS;
|
|||
|
|
|||
|
if (bomb_head.next==&bomb_head) {
|
|||
|
if (target_cnt)
|
|||
|
Snd(Freq2Ona(100+60*Clamp(0.1*(1.0+Abs(Wrap(<EFBFBD>f-<EFBFBD>,-<EFBFBD>)))`4.0,-3,3)));
|
|||
|
else if (key_cnt<best_score) {
|
|||
|
best_score=key_cnt;
|
|||
|
Sleep(150); Snd(74);Sleep(150);Snd;
|
|||
|
Sleep(150); Snd(74);Sleep(150);Snd;
|
|||
|
} else
|
|||
|
Snd;
|
|||
|
}
|
|||
|
|
|||
|
<EFBFBD>+=dt*(<EFBFBD>f-<EFBFBD>);
|
|||
|
x+=dt*v*Sin(<EFBFBD>);
|
|||
|
y+=dt*v*Cos(<EFBFBD>);
|
|||
|
|
|||
|
for (i=0;i<TARGETS_NUM;i++) {
|
|||
|
tmpt=&targets[i];
|
|||
|
if (!tmpt->dead && tmpt->type==MDF_TANK) {
|
|||
|
tmpt->x+=dt*TANK_V*Cos(tmpt-><EFBFBD>);
|
|||
|
tmpt->y+=dt*TANK_V*Sin(tmpt-><EFBFBD>);
|
|||
|
if (i&1)
|
|||
|
tmpt-><EFBFBD>+=dt*<EFBFBD>/16;
|
|||
|
else
|
|||
|
tmpt-><EFBFBD>-=dt*<EFBFBD>/16;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
tmpb=bomb_head.next;
|
|||
|
while (tmpb!=&bomb_head) {
|
|||
|
tmpb1=tmpb->next;
|
|||
|
if (tmpb->t+FALL_TIME+EXPLODE_TIME<tS)
|
|||
|
BombHit(tmpb);
|
|||
|
else if (tmpb->t+FALL_TIME<tS && !tmpb->exploding) {
|
|||
|
Noise(EXPLODE_TIME*1000,62,74);
|
|||
|
tmpb->exploding=TRUE;
|
|||
|
}
|
|||
|
tmpb=tmpb1;
|
|||
|
}
|
|||
|
|
|||
|
Sleep(10);
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
U0 Init()
|
|||
|
{
|
|||
|
I64 i;
|
|||
|
Target *tmpt;
|
|||
|
|
|||
|
v=20;
|
|||
|
x=-MAP_WIDTH>>1;
|
|||
|
y=-MAP_HEIGHT>>1;
|
|||
|
<EFBFBD>f=<EFBFBD>=1*<EFBFBD>/4;
|
|||
|
|
|||
|
QueInit(&bomb_head);
|
|||
|
|
|||
|
MemSet(trees,0,sizeof(trees));
|
|||
|
for (i=0;i<TREES_NUM;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<TARGETS_NUM;i++) {
|
|||
|
tmpt=&targets[i];
|
|||
|
tmpt->x=RandU32%MAP_WIDTH -MAP_WIDTH >>1;
|
|||
|
tmpt->y=RandU32%MAP_HEIGHT-MAP_HEIGHT>>1;
|
|||
|
if (i<TARGETS_NUM/3) {
|
|||
|
tmpt->type=MDF_BUNKER;
|
|||
|
tmpt-><EFBFBD>=(RandU16&3)*<EFBFBD>/2;
|
|||
|
tmpt->alive_img=$IB,"<6>",BI=6$;
|
|||
|
tmpt->dead_img1=$IB,"<7>",BI=7$;
|
|||
|
tmpt->dead_img2=$IB,"<8>",BI=8$;
|
|||
|
} else {
|
|||
|
tmpt->type=MDF_TANK;
|
|||
|
tmpt-><EFBFBD>=Rand*2*<EFBFBD>;
|
|||
|
tmpt->alive_img=$IB,"<3>",BI=3$;
|
|||
|
tmpt->dead_img1=$IB,"<4>",BI=4$;
|
|||
|
tmpt->dead_img2=$IB,"<5>",BI=5$;
|
|||
|
}
|
|||
|
}
|
|||
|
key_cnt=0;
|
|||
|
target_cnt=TARGETS_NUM;
|
|||
|
}
|
|||
|
|
|||
|
U0 CleanUp()
|
|||
|
{
|
|||
|
QueDel(&bomb_head,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++;
|
|||
|
<EFBFBD>f+=1.0/(Abs(Wrap(<EFBFBD>f-<EFBFBD>,-<EFBFBD>))+2*<EFBFBD>);
|
|||
|
break;
|
|||
|
case SC_CURSOR_RIGHT:
|
|||
|
key_cnt++;
|
|||
|
<EFBFBD>f-=1.0/(Abs(Wrap(<EFBFBD>f-<EFBFBD>,-<EFBFBD>))+2*<EFBFBD>);
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
break;
|
|||
|
case CH_SPACE:
|
|||
|
key_cnt++;
|
|||
|
BombDrop(-x-0.8*FALL_TIME*v*Sin(<EFBFBD>),-y-0.8*FALL_TIME*v*Cos(<EFBFBD>));
|
|||
|
break;
|
|||
|
case '\n':
|
|||
|
CleanUp;
|
|||
|
Init;
|
|||
|
break;
|
|||
|
case CH_ESC:
|
|||
|
case CH_SHIFT_ESC:
|
|||
|
goto bm_done;
|
|||
|
}
|
|||
|
bm_done:
|
|||
|
} catch
|
|||
|
PutExcept;
|
|||
|
SettingsPop;
|
|||
|
CleanUp;
|
|||
|
MenuPop;
|
|||
|
RegWrite("TempleOS/BomberGolf","I64 best_score=%d;\n",best_score);
|
|||
|
}
|
|||
|
|
|||
|
BomberGolf;
|
|||
|
|