426 lines
8.1 KiB
HolyC
426 lines
8.1 KiB
HolyC
|
//Uses $LK,"fixed-point",A="FI:::/Demo/Lectures/FixedPoint.HC"$.
|
|||
|
|
|||
|
$BG,2$
|
|||
|
|
|||
|
$SP,"<1>",BI=1$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<2>",BI=2$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<3>",BI=3$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<4>",BI=4$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<5>",BI=5$
|
|||
|
|
|||
|
|
|||
|
$BG$#define FRAMES 6
|
|||
|
|
|||
|
U8 *imgs[FRAMES]={
|
|||
|
$IB,"<1>",BI=1$,$IB,"<2>",BI=2$,$IB,"<3>",BI=3$,$IB,"<4>",BI=4$,$IB,"<3>",BI=3$,$IB,"<2>",BI=2$};
|
|||
|
|
|||
|
F64 fire_end_time;
|
|||
|
|
|||
|
class Trooper
|
|||
|
{
|
|||
|
I64 x,y,dx,dy,att,def,rng,player;
|
|||
|
F64 animate_time_base,fire_end_time;
|
|||
|
Trooper *target;
|
|||
|
};
|
|||
|
|
|||
|
#define TROOPERS_NUM 100
|
|||
|
Trooper tr[2][TROOPERS_NUM];
|
|||
|
|
|||
|
Bool time_lapse=FALSE;
|
|||
|
|
|||
|
#define TAP_MODE_RADIUS 50
|
|||
|
Bool tap_mode;
|
|||
|
|
|||
|
#define AI_NOTHING 0
|
|||
|
#define AI_TARGET 1
|
|||
|
#define AI_RANDOM 2
|
|||
|
#define AI_AI_NUM 3
|
|||
|
I64 ai_mode;
|
|||
|
|
|||
|
I64 ai_targets[10];
|
|||
|
|
|||
|
U0 DrawTrooper(CTask *,CDC *dc,Trooper *tmpt)
|
|||
|
{
|
|||
|
U8 *tmps;
|
|||
|
I64 x,y,gx,gy;
|
|||
|
F64 speed,tt;
|
|||
|
|
|||
|
if (tmpt->def>0) {
|
|||
|
x=tmpt->dx>>28;
|
|||
|
y=tmpt->dy>>28;
|
|||
|
speed=0.5*Sqrt(x*x+y*y);
|
|||
|
|
|||
|
tt=tmpt->animate_time_base+tS*speed;
|
|||
|
if (time_lapse) {
|
|||
|
x=(tmpt->x+500*tmpt->dx)>>32;
|
|||
|
y=(tmpt->y+500*tmpt->dy)>>32;
|
|||
|
} else {
|
|||
|
x=tmpt->x.i32[1];
|
|||
|
y=tmpt->y.i32[1];
|
|||
|
}
|
|||
|
if (tmpt->target) {
|
|||
|
gx=x;gy=y;
|
|||
|
if (tmpt->dx<0) {
|
|||
|
dc->flags|=DCF_SYMMETRY|DCF_JUST_MIRROR;
|
|||
|
DCSymmetrySet(dc,x,y,x,y+1);
|
|||
|
gx-=13;
|
|||
|
gy-=7;
|
|||
|
} else {
|
|||
|
dc->flags&=~DCF_SYMMETRY|DCF_JUST_MIRROR;
|
|||
|
gx+=13;
|
|||
|
gy-=7;
|
|||
|
}
|
|||
|
|
|||
|
dc->color=BLACK;
|
|||
|
Sprite3(dc,x+1,y,0,$IB,"<5>",BI=5$);
|
|||
|
|
|||
|
if (!tmpt->player)
|
|||
|
dc->color=LTCYAN;
|
|||
|
else
|
|||
|
dc->color=LTPURPLE;
|
|||
|
Sprite3(dc,x,y,0,$IB,"<5>",BI=5$);
|
|||
|
|
|||
|
dc->flags&=~(DCF_SYMMETRY|DCF_JUST_MIRROR);
|
|||
|
if (!tmpt->player)
|
|||
|
dc->color=WHITE;
|
|||
|
else
|
|||
|
dc->color=LTBLUE;
|
|||
|
GrLine3(dc,gx,gy,0,tmpt->target->x.i32[1],tmpt->target->y.i32[1],0);
|
|||
|
} else {
|
|||
|
if (tmpt->dx<0) {
|
|||
|
dc->flags|=DCF_SYMMETRY|DCF_JUST_MIRROR;
|
|||
|
DCSymmetrySet(dc,x,y,x,y+1);
|
|||
|
} else
|
|||
|
dc->flags&=~DCF_SYMMETRY|DCF_JUST_MIRROR;
|
|||
|
tmps=SpriteInterpolate(tt%1.0,imgs[tt%FRAMES],imgs[(tt+1.0)%FRAMES]);
|
|||
|
|
|||
|
dc->color=BLACK;
|
|||
|
Sprite3(dc,x+1,y,0,tmps);
|
|||
|
|
|||
|
if (!tmpt->player)
|
|||
|
dc->color=LTCYAN;
|
|||
|
else
|
|||
|
dc->color=LTPURPLE;
|
|||
|
Sprite3(dc,x,y,0,tmps);
|
|||
|
|
|||
|
Free(tmps);
|
|||
|
dc->flags&=~(DCF_SYMMETRY|DCF_JUST_MIRROR);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
U0 DrawIt(CTask *task,CDC *dc)
|
|||
|
{
|
|||
|
Trooper *tmpt=tr;
|
|||
|
I64 i,j,cnt[2],
|
|||
|
x=ms.pos.x-task->pix_left-task->scroll_x,
|
|||
|
y=ms.pos.y-task->pix_top-task->scroll_y;
|
|||
|
Bool repulsive=ms.pos.z>0 ^^ ms.rb,
|
|||
|
active=!winmgr.grab_scroll && (ms.lb||ms.rb);
|
|||
|
|
|||
|
for (j=0;j<2;j++) {
|
|||
|
cnt[j]=0;
|
|||
|
for (i=0;i<TROOPERS_NUM;i++,tmpt++) {
|
|||
|
if (tmpt->def>0) {
|
|||
|
DrawTrooper(task,dc,tmpt);
|
|||
|
cnt[j]++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if (tap_mode) {
|
|||
|
dc->color=YELLOW;
|
|||
|
GrCircle(dc,x,y,TAP_MODE_RADIUS);
|
|||
|
} else {
|
|||
|
if (repulsive) {
|
|||
|
if (active)
|
|||
|
dc->color=LTRED;
|
|||
|
else
|
|||
|
dc->color=RED;
|
|||
|
} else {
|
|||
|
if (active)
|
|||
|
dc->color=LTBLUE;
|
|||
|
else
|
|||
|
dc->color=BLUE;
|
|||
|
}
|
|||
|
GrCircle(dc,x,y,AbsI64(ms.pos.z));
|
|||
|
}
|
|||
|
dc->color=LTCYAN;
|
|||
|
GrPrint(dc,(task->win_right-8)*FONT_WIDTH,0,"%03d",cnt[0]);
|
|||
|
dc->color=LTPURPLE;
|
|||
|
GrPrint(dc,(task->win_right-4)*FONT_WIDTH,0,"%03d",cnt[1]);
|
|||
|
}
|
|||
|
|
|||
|
U0 DoAiTarget()
|
|||
|
{
|
|||
|
I64 i,j;
|
|||
|
Trooper *tmpt1,*tmpt0;
|
|||
|
for (i=0;i<10;i++) {
|
|||
|
tmpt0=&tr[0][ai_targets[i]];
|
|||
|
for (j=0;j<10;j++) {
|
|||
|
tmpt1=&tr[1][i*10+j];
|
|||
|
tmpt1->dx=(tmpt0->x-tmpt1->x)>>11;
|
|||
|
tmpt1->dy=(tmpt0->y-tmpt1->y)>>11;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
U0 UpdatePos()
|
|||
|
{
|
|||
|
I64 i,j;
|
|||
|
Trooper *tmpt=tr;
|
|||
|
for (j=0;j<2;j++)
|
|||
|
for (i=0;i<TROOPERS_NUM;i++,tmpt++) {
|
|||
|
tmpt->x+=tmpt->dx;
|
|||
|
if (tmpt->x>=GR_WIDTH<<32) tmpt->x-=GR_WIDTH<<32;
|
|||
|
if (tmpt->x<0) tmpt->x+=GR_WIDTH<<32;
|
|||
|
tmpt->y+=tmpt->dy;
|
|||
|
if (tmpt->y>=GR_HEIGHT<<32) tmpt->y-=GR_HEIGHT<<32;
|
|||
|
if (tmpt->y<0) tmpt->y+=GR_HEIGHT<<32;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
U0 ResolveFiring()
|
|||
|
{
|
|||
|
I64 i,j,dd,dx,dy;
|
|||
|
Trooper *tmpt=tr,*tmpt0,*tmpt1;
|
|||
|
|
|||
|
for (j=0;j<2;j++)
|
|||
|
for (i=0;i<TROOPERS_NUM;i++,tmpt++) {
|
|||
|
if (tmpt->target && tmpt->fire_end_time<tS) {
|
|||
|
tmpt->target->def-=tmpt->att;
|
|||
|
tmpt->fire_end_time=0;
|
|||
|
tmpt->target=NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (i=0;i<TROOPERS_NUM;i++) {
|
|||
|
tmpt0=&tr[0][i];
|
|||
|
for (j=0;j<TROOPERS_NUM;j++) {
|
|||
|
tmpt1=&tr[1][j];
|
|||
|
if (tmpt0->def>0 && tmpt1->def>0) {
|
|||
|
dx=(tmpt0->x-tmpt1->x)>>32;
|
|||
|
dy=(tmpt0->y-tmpt1->y)>>32;
|
|||
|
dd=dx*dx+dy*dy;
|
|||
|
if (dd<tmpt0->rng && !tmpt0->target) {
|
|||
|
fire_end_time=tmpt0->fire_end_time=tS+0.125;
|
|||
|
Snd(86);
|
|||
|
tmpt0->target=tmpt1;
|
|||
|
}
|
|||
|
if (dd<tmpt1->rng && !tmpt1->target) {
|
|||
|
fire_end_time=tmpt1->fire_end_time=tS+0.125;
|
|||
|
Snd(86);
|
|||
|
tmpt1->target=tmpt0;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (tS>=fire_end_time)
|
|||
|
Snd;
|
|||
|
}
|
|||
|
|
|||
|
U0 UpdateHumanVelocities()
|
|||
|
{
|
|||
|
F64 intensity;
|
|||
|
I64 i,j,dx,dy,d,
|
|||
|
x=ms.pos.x-Fs->pix_left-Fs->scroll_x,
|
|||
|
y=ms.pos.y-Fs->pix_top-Fs->scroll_y;
|
|||
|
Bool active=!winmgr.grab_scroll&&(ms.lb||ms.rb);
|
|||
|
Trooper *tmpt=&tr[0][0];
|
|||
|
if (tap_mode) {
|
|||
|
for (i=0;i<TROOPERS_NUM;i++,tmpt++) {
|
|||
|
dx=x- tmpt->x.i32[1];
|
|||
|
dy=y- tmpt->y.i32[1];
|
|||
|
if ((d=dx*dx+dy*dy) && d<TAP_MODE_RADIUS*TAP_MODE_RADIUS) {
|
|||
|
intensity=SqrI64(SqrI64(SqrI64(TAP_MODE_RADIUS)-d));
|
|||
|
dx=intensity*dx/d;
|
|||
|
dy=intensity*dy/d;
|
|||
|
tmpt->dx=tmpt->dx-dx;
|
|||
|
tmpt->dy=tmpt->dy-dy;
|
|||
|
} else {
|
|||
|
tmpt->dx-=0.2*tmpt->dx;
|
|||
|
tmpt->dy-=0.2*tmpt->dy;
|
|||
|
}
|
|||
|
}
|
|||
|
} else if (active) {
|
|||
|
j=400000000*ms.pos.z;
|
|||
|
if (ms.rb)
|
|||
|
j=-j;
|
|||
|
for (i=0;i<TROOPERS_NUM;i++,tmpt++) {
|
|||
|
dx=x- tmpt->x.i32[1];
|
|||
|
dy=y- tmpt->y.i32[1];
|
|||
|
if (d=dx*dx+dy*dy) {
|
|||
|
dx=j*dx/d;
|
|||
|
dy=j*dy/d;
|
|||
|
tmpt->dx=tmpt->dx-dx;
|
|||
|
tmpt->dy=tmpt->dy-dy;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
U0 Init()
|
|||
|
{
|
|||
|
I64 i,j,dx,dy;
|
|||
|
Trooper *tmpt;
|
|||
|
MsSet(,,25);
|
|||
|
tap_mode=FALSE;
|
|||
|
time_lapse=FALSE;
|
|||
|
fire_end_time=0;
|
|||
|
MemSet(tr,0,sizeof(tr));
|
|||
|
for (i=0;i<10;i++) {
|
|||
|
ai_targets[i]=RandU16%TROOPERS_NUM;
|
|||
|
dx=RandI32;
|
|||
|
dy=RandI32;
|
|||
|
for (j=0;j<10;j++) {
|
|||
|
tmpt=&tr[0][i*10+j];
|
|||
|
tmpt->x=(GR_WIDTH-100-i*10)<<32;
|
|||
|
tmpt->y=(GR_HEIGHT>>1-50+j*10)<<32;
|
|||
|
tmpt->att=3;
|
|||
|
tmpt->def=10;
|
|||
|
tmpt->rng=50*50;
|
|||
|
tmpt->animate_time_base=10*Rand;
|
|||
|
tmpt->player=0;
|
|||
|
|
|||
|
tmpt=&tr[1][i*10+j];
|
|||
|
tmpt->x=(100+i*10)<<32;
|
|||
|
tmpt->y=(GR_HEIGHT>>1-50+j*10)<<32;
|
|||
|
if (ai_mode==AI_RANDOM) {
|
|||
|
tmpt->dx=dx;
|
|||
|
tmpt->dy=dy;
|
|||
|
}
|
|||
|
tmpt->att=3;
|
|||
|
tmpt->def=10;
|
|||
|
tmpt->rng=50*50;
|
|||
|
tmpt->animate_time_base=10*Rand;
|
|||
|
tmpt->player=1;
|
|||
|
}
|
|||
|
}
|
|||
|
ai_mode=RandU16%AI_AI_NUM;
|
|||
|
}
|
|||
|
|
|||
|
U0 BattleLines()
|
|||
|
{
|
|||
|
CMenuEntry *tmpse;
|
|||
|
|
|||
|
MenuPush(
|
|||
|
"File {"
|
|||
|
" Abort(,CH_SHIFT_ESC);"
|
|||
|
" Exit(,CH_ESC);"
|
|||
|
"}"
|
|||
|
"Play {"
|
|||
|
" Restart(,'\n');"
|
|||
|
" TimeLapse(,'1');"
|
|||
|
" TapMode(,'2');"
|
|||
|
"}"
|
|||
|
);
|
|||
|
|
|||
|
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
|||
|
Fs->text_attr=GREEN<<4+WHITE;
|
|||
|
AutoComplete;
|
|||
|
WinBorder;
|
|||
|
WinMax;
|
|||
|
DocCursor;
|
|||
|
DocClear;
|
|||
|
Init;
|
|||
|
Fs->draw_it=&DrawIt;
|
|||
|
PopUpOk("The mouse wheel controls\n"
|
|||
|
"the command force.\n"
|
|||
|
"Attract or repel with\n"
|
|||
|
"left or right bttn.\n\n");
|
|||
|
|
|||
|
Fs->win_inhibit=WIG_TASK_DFT-WIF_SELF_FOCUS
|
|||
|
-WIF_SELF_BORDER-WIF_FOCUS_TASK_MENU;
|
|||
|
try {
|
|||
|
while (TRUE) {
|
|||
|
switch (ScanChar) {
|
|||
|
case '1':
|
|||
|
time_lapse=!time_lapse;
|
|||
|
tmpse=MenuEntryFind(Fs->cur_menu,"Play/TimeLapse");
|
|||
|
tmpse->checked=time_lapse;
|
|||
|
break;
|
|||
|
case '2':
|
|||
|
tap_mode=!tap_mode;
|
|||
|
tmpse=MenuEntryFind(Fs->cur_menu,"Play/TapMode");
|
|||
|
tmpse->checked=tap_mode;
|
|||
|
break;
|
|||
|
case CH_ESC:
|
|||
|
case CH_SHIFT_ESC:
|
|||
|
goto wg_done;
|
|||
|
case '\n':
|
|||
|
Init;
|
|||
|
break;
|
|||
|
}
|
|||
|
Sleep(40);
|
|||
|
if (ai_mode==AI_TARGET)
|
|||
|
DoAiTarget;
|
|||
|
UpdateHumanVelocities;
|
|||
|
UpdatePos;
|
|||
|
ResolveFiring;
|
|||
|
}
|
|||
|
wg_done:
|
|||
|
} catch
|
|||
|
PutExcept;
|
|||
|
SettingsPop;
|
|||
|
MenuPop;
|
|||
|
}
|
|||
|
|
|||
|
BattleLines;
|
|||
|
|