1161 lines
105 KiB
HolyC
1161 lines
105 KiB
HolyC
|
//The ball and men were generated
|
|||
|
//with $LK,"::/Apps/GrModels/Run.HC"$.
|
|||
|
//They were cut-and-pasted here.
|
|||
|
|
|||
|
$BG,14$
|
|||
|
$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$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<11>",BI=11$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<12>",BI=12$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<13>",BI=13$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<14>",BI=14$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<15>",BI=15$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<16>",BI=16$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<17>",BI=17$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<18>",BI=18$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<19>",BI=19$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<20>",BI=20$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<21>",BI=21$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<22>",BI=22$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<23>",BI=23$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$BG$class Frame
|
|||
|
{
|
|||
|
U8 *img[2];
|
|||
|
F64 dt;
|
|||
|
};
|
|||
|
|
|||
|
#define COURT_BORDER 10
|
|||
|
#define COLLISION_DAMP 0.8
|
|||
|
#define AIR_VISCOSITY 0.1
|
|||
|
|
|||
|
#define GRAVITY_ACCELERATION 500
|
|||
|
#define SHOT_VELOCITY 400
|
|||
|
#define DRIBBLE_T 0.25
|
|||
|
#define MAN_VELOCITY 150
|
|||
|
#define MAN_SQR_RADIUS (20*20)
|
|||
|
#define FOUL_VELOCITY_THRESHOLD 50
|
|||
|
#define JUMP_VELOCITY 250
|
|||
|
#define ROLL_VELOCITY_THRESHOLD 100
|
|||
|
#define RANDOM_MAN_ACCELERATION 30
|
|||
|
|
|||
|
#define HEAD_Z_OFFSET 200
|
|||
|
#define HAND_X_OFFSET 30
|
|||
|
#define HAND_Y_OFFSET 20
|
|||
|
#define HAND_SQR_OFFSET \
|
|||
|
(HAND_X_OFFSET*HAND_X_OFFSET+HAND_Y_OFFSET*HAND_Y_OFFSET)
|
|||
|
#define HAND_Z_OFFSET 110
|
|||
|
|
|||
|
#define FIRST_STANDING 0
|
|||
|
|
|||
|
#define RUNNING_IMGS_NUM 4
|
|||
|
#define FIRST_RUNNING 0
|
|||
|
#define LAST_RUNNING (FIRST_RUNNING+RUNNING_IMGS_NUM-1)
|
|||
|
|
|||
|
#define SHOOTING_IMGS_NUM 5
|
|||
|
#define FIRST_SHOOTING (LAST_RUNNING+1)
|
|||
|
#define LAST_SHOOTING (FIRST_SHOOTING+SHOOTING_IMGS_NUM-1)
|
|||
|
|
|||
|
#define DRIBBLING_IMGS_NUM 4
|
|||
|
#define FIRST_DRIBBLING (LAST_SHOOTING+1)
|
|||
|
#define LAST_DRIBBLING (FIRST_DRIBBLING+DRIBBLING_IMGS_NUM-1)
|
|||
|
|
|||
|
#define STOPPED_DRIBBLING_IMGS_NUM 2
|
|||
|
#define FIRST_STOPPED_DRIBBLING (LAST_DRIBBLING+1)
|
|||
|
#define LAST_STOPPED_DRIBBLING \
|
|||
|
(FIRST_STOPPED_DRIBBLING+STOPPED_DRIBBLING_IMGS_NUM-1)
|
|||
|
|
|||
|
Frame imgs[LAST_STOPPED_DRIBBLING+1]={
|
|||
|
{{$IB,"<6>",BI=6$,$IB,"<7>",BI=7$},2*DRIBBLE_T/RUNNING_IMGS_NUM},
|
|||
|
{{$IB,"<2>",BI=2$,$IB,"<3>",BI=3$},2*DRIBBLE_T/RUNNING_IMGS_NUM},
|
|||
|
{{$IB,"<6>",BI=6$,$IB,"<7>",BI=7$},2*DRIBBLE_T/RUNNING_IMGS_NUM},
|
|||
|
{{$IB,"<4>",BI=4$,$IB,"<5>",BI=5$},2*DRIBBLE_T/RUNNING_IMGS_NUM},
|
|||
|
{{$IB,"<8>",BI=8$,$IB,"<9>",BI=9$},0.1},{{$IB,"<10>",BI=10$,$IB,"<11>",BI=11$},0.2},
|
|||
|
{{$IB,"<12>",BI=12$,$IB,"<13>",BI=13$},0.2},{{$IB,"<12>",BI=12$,$IB,"<13>",BI=13$},0.1},{{$IB,"<14>",BI=14$,$IB,"<15>",BI=15$},0.1},
|
|||
|
{{$IB,"<20>",BI=20$,$IB,"<21>",BI=21$},2*DRIBBLE_T/DRIBBLING_IMGS_NUM},
|
|||
|
{{$IB,"<16>",BI=16$,$IB,"<17>",BI=17$},2*DRIBBLE_T/DRIBBLING_IMGS_NUM},
|
|||
|
{{$IB,"<20>",BI=20$,$IB,"<21>",BI=21$},2*DRIBBLE_T/DRIBBLING_IMGS_NUM},
|
|||
|
{{$IB,"<18>",BI=18$,$IB,"<19>",BI=19$},2*DRIBBLE_T/DRIBBLING_IMGS_NUM},
|
|||
|
{{$IB,"<20>",BI=20$,$IB,"<21>",BI=21$},DRIBBLE_T/STOPPED_DRIBBLING_IMGS_NUM},
|
|||
|
{{$IB,"<22>",BI=22$,$IB,"<23>",BI=23$},DRIBBLE_T/STOPPED_DRIBBLING_IMGS_NUM},
|
|||
|
};
|
|||
|
|
|||
|
RegDft("TempleOS/KeepAway","I64 best_score0=0,best_score1=9999;\n");
|
|||
|
RegExe("TempleOS/KeepAway");
|
|||
|
|
|||
|
F64 game_t_end,foul_t_end;
|
|||
|
I64 score0,score1;
|
|||
|
|
|||
|
#define PER_SIDE_NUM 3
|
|||
|
#define OBJS_NUM (PER_SIDE_NUM*2+1)
|
|||
|
Bool someone_shooting,someone_has_ball;
|
|||
|
F64 shot_land_t;
|
|||
|
|
|||
|
class Obj
|
|||
|
{
|
|||
|
I64 team; //-1 is ball
|
|||
|
F64 x,y,z,DxDt,DyDt,DzDt,<EFBFBD>,radius,stolen_t0;
|
|||
|
F64 get_ball_dt,get_ball_<EFBFBD>,nearest_man_dd,last_t0,next_t0,foul_t0;
|
|||
|
I64 last_img,next_img;
|
|||
|
Bool stopped,shooting,has_ball,nearest_ball,pad[4];
|
|||
|
} objs[OBJS_NUM],*ball,*human,*last_owner;
|
|||
|
|
|||
|
/*Just to be different, I didn't use the built-in
|
|||
|
DCF_TRANSFORMATION flag in this game.
|
|||
|
Instead, I chose a 45 degree angle
|
|||
|
between Y and Z as the view point.
|
|||
|
If I had used the transform, I would
|
|||
|
have to make all my men taller.
|
|||
|
This is a little simpler, and faster,
|
|||
|
but adds lots of factor 2 vals.
|
|||
|
|
|||
|
I also didn't use the $LK,"CMathODE",A="MN:CMathODE"$ feat,
|
|||
|
just to be different.
|
|||
|
*/
|
|||
|
|
|||
|
U0 DrawObj(CDC *dc,Obj *o,F64 tt)
|
|||
|
{
|
|||
|
U8 *tmps;
|
|||
|
F64 r1=Max(9-0.1*o->z,1),r2=Max(r1/4,1);
|
|||
|
|
|||
|
if (o==human)
|
|||
|
dc->color=LTRED;
|
|||
|
else
|
|||
|
dc->color=BLACK;
|
|||
|
GrEllipse(dc,o->x,o->y/2,r1,r2);
|
|||
|
GrFloodFill(dc,o->x,o->y/2);
|
|||
|
|
|||
|
if (o==ball)
|
|||
|
Sprite3(dc,o->x,(o->y-o->z)/2,GR_Z_ALL-o->y,$IB,"<1>",BI=1$);
|
|||
|
else {
|
|||
|
tmps=SpriteInterpolate((tt-o->last_t0)/(o->next_t0-o->last_t0),
|
|||
|
imgs[o->last_img].img[o->team],
|
|||
|
imgs[o->next_img].img[o->team]);
|
|||
|
Sprite3YB(dc,o->x,(o->y-o->z)/2,GR_Z_ALL-o->y,tmps,o-><EFBFBD>);
|
|||
|
Free(tmps);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
I64 ObjCompare(Obj *o1,Obj *o2)
|
|||
|
{
|
|||
|
return o1->y-o2->y;
|
|||
|
}
|
|||
|
|
|||
|
U0 DrawIt(CTask *task,CDC *dc)
|
|||
|
{
|
|||
|
F64 tt=tS,d,d_down,d_up;
|
|||
|
I64 i;
|
|||
|
Obj *o_sort[OBJS_NUM],*o;
|
|||
|
|
|||
|
DCDepthBufAlloc(dc);
|
|||
|
dc->ls.x=10000;
|
|||
|
dc->ls.y=60000;
|
|||
|
dc->ls.z=10000;
|
|||
|
d=65535/D3I32Norm(&dc->ls);
|
|||
|
dc->ls.x*=d;
|
|||
|
dc->ls.y*=d;
|
|||
|
dc->ls.z*=d;
|
|||
|
|
|||
|
dc->thick=2;
|
|||
|
dc->color=RED;
|
|||
|
GrBorder(dc,COURT_BORDER,COURT_BORDER,
|
|||
|
task->pix_width -1-COURT_BORDER,
|
|||
|
task->pix_height-1-COURT_BORDER);
|
|||
|
for (i=0;i<OBJS_NUM;i++) {
|
|||
|
o=o_sort[i]=&objs[i];
|
|||
|
if (o!=ball) {
|
|||
|
if (o->has_ball) {
|
|||
|
ball->x=o->x+HAND_X_OFFSET*Cos(o-><EFBFBD>-<EFBFBD>/2)+HAND_Y_OFFSET*Cos(o-><EFBFBD>);
|
|||
|
//The factor 2 is because the man is not transformed.
|
|||
|
ball->y=o->y+HAND_X_OFFSET*Sin(o-><EFBFBD>-<EFBFBD>/2)/2+HAND_Y_OFFSET*Sin(o-><EFBFBD>)/2;
|
|||
|
if (ball->z+ball->radius*2>o->z+HAND_Z_OFFSET)
|
|||
|
ball->z=o->z+HAND_Z_OFFSET-ball->radius*2;
|
|||
|
} else if (o->shooting) {
|
|||
|
ball->x=o->x;
|
|||
|
ball->y=o->y;
|
|||
|
ball->z=o->z+HEAD_Z_OFFSET;
|
|||
|
}
|
|||
|
if (tt>o->next_t0) {
|
|||
|
if (o->has_ball && (ball->z+ball->radius*2>=o->z+HAND_Z_OFFSET ||
|
|||
|
Abs(ball->DzDt)<30)) {
|
|||
|
//This is an approximation. My instinct tells me the viscosity term
|
|||
|
//needs an $LK,"Exp",A="MN:Exp"$(). However, we should be syncronized to img frames,
|
|||
|
//so we don't have to be perfect.
|
|||
|
d_down=1.0;
|
|||
|
d_up =1.0/COLLISION_DAMP;
|
|||
|
//Up bounce takes higher % because speed lost in collision.
|
|||
|
ball->DzDt=-((d_down+d_up)*
|
|||
|
(o->z+HAND_Z_OFFSET-ball->radius*4)/(1.0-AIR_VISCOSITY)+
|
|||
|
0.5*GRAVITY_ACCELERATION*(
|
|||
|
Sqr(DRIBBLE_T*d_up/(d_down+d_up))-
|
|||
|
Sqr(DRIBBLE_T*d_down/(d_down+d_up)) ))/DRIBBLE_T;
|
|||
|
}
|
|||
|
o->last_t0=tt;
|
|||
|
o->last_img=o->next_img++;
|
|||
|
if (o->stopped) {
|
|||
|
if (o->has_ball) {
|
|||
|
if (!(FIRST_STOPPED_DRIBBLING<=o->next_img<=LAST_STOPPED_DRIBBLING))
|
|||
|
o->next_img=FIRST_STOPPED_DRIBBLING;
|
|||
|
} else
|
|||
|
o->next_img=FIRST_STANDING;
|
|||
|
o->stopped=FALSE;
|
|||
|
} else if (o->shooting) {
|
|||
|
if (!(FIRST_SHOOTING<=o->last_img<=LAST_SHOOTING))
|
|||
|
o->next_img=FIRST_SHOOTING;
|
|||
|
if (o->next_img>LAST_SHOOTING) {
|
|||
|
o->next_img=FIRST_STANDING;
|
|||
|
someone_has_ball=someone_shooting=o->has_ball=o->shooting=FALSE;
|
|||
|
ball->DxDt=o->DxDt+SHOT_VELOCITY/sqrt2*Cos(o-><EFBFBD>-<EFBFBD>/2);
|
|||
|
ball->DyDt=o->DyDt+SHOT_VELOCITY/sqrt2*Sin(o-><EFBFBD>-<EFBFBD>/2);
|
|||
|
ball->DzDt=o->DzDt+SHOT_VELOCITY/sqrt2;
|
|||
|
shot_land_t=tt+(ball->DzDt+Sqrt(Sqr(ball->DzDt)+
|
|||
|
2*GRAVITY_ACCELERATION*ball->z))/GRAVITY_ACCELERATION;
|
|||
|
} else {
|
|||
|
ball->DxDt=0;
|
|||
|
ball->DyDt=0;
|
|||
|
ball->DzDt=0;
|
|||
|
}
|
|||
|
} else if (o->has_ball) {
|
|||
|
if (FIRST_RUNNING<=o->next_img<=LAST_RUNNING)
|
|||
|
o->next_img+=FIRST_DRIBBLING-FIRST_RUNNING;
|
|||
|
if (!(FIRST_DRIBBLING<=o->next_img<=LAST_DRIBBLING))
|
|||
|
o->next_img=FIRST_DRIBBLING;
|
|||
|
} else {
|
|||
|
if (FIRST_DRIBBLING<=o->next_img<=LAST_DRIBBLING)
|
|||
|
o->next_img+=FIRST_RUNNING-FIRST_DRIBBLING;
|
|||
|
if (!(FIRST_RUNNING<=o->next_img<=LAST_RUNNING))
|
|||
|
o->next_img=FIRST_RUNNING;
|
|||
|
}
|
|||
|
o->next_t0+=imgs[o->last_img].dt;
|
|||
|
if (o->next_t0<=tt)
|
|||
|
o->next_t0=tt+imgs[o->last_img].dt;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
QSortI64(o_sort,OBJS_NUM,&ObjCompare);
|
|||
|
for (i=0;i<OBJS_NUM;i++)
|
|||
|
DrawObj(dc,o_sort[i],tt);
|
|||
|
tt=(game_t_end-tS)/60;
|
|||
|
if (tt<=0) {
|
|||
|
dc->color=RED;
|
|||
|
tt=0;
|
|||
|
if (Blink)
|
|||
|
GrPrint(dc,(task->pix_width-FONT_WIDTH*9)>>1,
|
|||
|
(task->pix_height-FONT_HEIGHT)>>1,"Game Over");
|
|||
|
} else {
|
|||
|
if (tS<foul_t_end) {
|
|||
|
dc->color=LTRED;
|
|||
|
if (Blink)
|
|||
|
GrPrint(dc,(task->pix_width-FONT_WIDTH*4)>>1,
|
|||
|
(task->pix_height-FONT_HEIGHT)>>1,"Foul");
|
|||
|
}
|
|||
|
dc->color=BLACK;
|
|||
|
}
|
|||
|
GrPrint(dc,0,0,"Time:%d:%04.1fScore:",ToI64(tt),(tt-ToI64(tt))*60);
|
|||
|
GrPrint (dc,FONT_WIDTH*27,0,"Best Score:");
|
|||
|
|
|||
|
dc->color=LTCYAN;
|
|||
|
GrPrint(dc,FONT_WIDTH*20,0,"%02d",score0);
|
|||
|
dc->color=LTPURPLE;
|
|||
|
GrPrint(dc,FONT_WIDTH*23,0,"%02d",score1);
|
|||
|
|
|||
|
dc->color=LTCYAN;
|
|||
|
GrPrint(dc,FONT_WIDTH*39,0,"%02d",best_score0);
|
|||
|
dc->color=LTPURPLE;
|
|||
|
GrPrint(dc,FONT_WIDTH*42,0,"%02d",best_score1);
|
|||
|
}
|
|||
|
|
|||
|
U0 Shoot(Obj *o)
|
|||
|
{
|
|||
|
if (!someone_shooting && o->has_ball) {
|
|||
|
someone_shooting=o->stopped=o->shooting=TRUE;
|
|||
|
o->has_ball=FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
U0 AnimateTask(CTask *parent_task)
|
|||
|
{
|
|||
|
F64 d,dx,dy,dt,dx2,dy2,t0=tS;
|
|||
|
I64 i,j;
|
|||
|
Bool gets_ball;
|
|||
|
Obj *o,*nearest_ball[2];
|
|||
|
while (TRUE) {
|
|||
|
dt=tS-t0;
|
|||
|
t0=tS;
|
|||
|
|
|||
|
if (game_t_end && game_t_end<t0) {
|
|||
|
game_t_end=0;
|
|||
|
Beep;
|
|||
|
if (score0-score1>best_score0-best_score1) {
|
|||
|
best_score0=score0;
|
|||
|
best_score1=score1;
|
|||
|
Snd(86);Sleep(100); Snd;Sleep(100);
|
|||
|
Snd(86);Sleep(100); Snd;Sleep(100);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (game_t_end) {
|
|||
|
MemSet(&nearest_ball,0,sizeof(nearest_ball));
|
|||
|
for (i=0;i<OBJS_NUM;i++) {
|
|||
|
o=&objs[i];
|
|||
|
o->nearest_ball=FALSE;
|
|||
|
if (o!=ball) {
|
|||
|
d=0;
|
|||
|
for (j=0;j<5;j++) //Iterative estimate of how long to get ball.
|
|||
|
d=Sqrt(Sqr(ball->DxDt*d+ball->x-o->x)+
|
|||
|
Sqr(ball->DyDt*d+ball->y-o->y))/MAN_VELOCITY;
|
|||
|
o->get_ball_dt=d;
|
|||
|
o->get_ball_<EFBFBD>=Arg(ball->DxDt*d+ball->x-o->x,
|
|||
|
ball->DyDt*d+ball->y-o->y);
|
|||
|
if (o!=last_owner && !nearest_ball[o->team] ||
|
|||
|
o->get_ball_dt<nearest_ball[o->team]->get_ball_dt)
|
|||
|
nearest_ball[o->team]=o;
|
|||
|
}
|
|||
|
}
|
|||
|
nearest_ball[0]->nearest_ball=TRUE;
|
|||
|
nearest_ball[1]->nearest_ball=TRUE;
|
|||
|
|
|||
|
for (i=0;i<OBJS_NUM;i++) {
|
|||
|
o=&objs[i];
|
|||
|
if (o==ball) {
|
|||
|
o->x+=dt*o->DxDt;
|
|||
|
o->y+=dt*o->DyDt;
|
|||
|
if (!someone_shooting)
|
|||
|
o->z+=dt*(o->DzDt-0.5*GRAVITY_ACCELERATION*dt);
|
|||
|
} else {
|
|||
|
if (!o->has_ball) {
|
|||
|
if (t0-o->stolen_t0>2.0 && !someone_shooting) {
|
|||
|
dx=ball->x-o->x;
|
|||
|
dy=ball->y-o->y;
|
|||
|
if (dx*dx+dy*dy<HAND_SQR_OFFSET && ball->z<o->z+HAND_Z_OFFSET) {
|
|||
|
gets_ball=TRUE;
|
|||
|
for (j=0;j<PER_SIDE_NUM*2;j++)
|
|||
|
if (j!=i && objs[j].has_ball) {
|
|||
|
if (Rand<2.0*dt) {
|
|||
|
objs[j].stolen_t0=t0;
|
|||
|
objs[j].has_ball=FALSE;
|
|||
|
} else
|
|||
|
gets_ball=FALSE;
|
|||
|
}
|
|||
|
if (gets_ball) {
|
|||
|
someone_has_ball=o->has_ball=TRUE;
|
|||
|
if (o!=last_owner) {
|
|||
|
if (o->team) {
|
|||
|
if (t0<shot_land_t+0.1)
|
|||
|
score1+=6;
|
|||
|
else
|
|||
|
score1+=2;
|
|||
|
Noise(250,74,74);
|
|||
|
} else {
|
|||
|
if (t0<shot_land_t+0.1)
|
|||
|
score0+=6;
|
|||
|
else
|
|||
|
score0+=2;
|
|||
|
Noise(250,86,86);
|
|||
|
}
|
|||
|
last_owner=o;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
} else if (o!=human && Rand<0.25*dt)
|
|||
|
Shoot(o);
|
|||
|
if (!o->shooting) {
|
|||
|
if (o==human) {
|
|||
|
dx=(ms.pos.x-parent_task->pix_left-parent_task->scroll_x)-o->x;
|
|||
|
dy=(ms.pos.y-parent_task->pix_top-parent_task->scroll_y)*2-o->y;
|
|||
|
} else {
|
|||
|
if (!someone_has_ball && o->nearest_man_dd>4*MAN_SQR_RADIUS &&
|
|||
|
o->nearest_ball) {
|
|||
|
dx=o->DxDt=MAN_VELOCITY*Cos(o->get_ball_<EFBFBD>);
|
|||
|
dy=o->DyDt=MAN_VELOCITY*Sin(o->get_ball_<EFBFBD>);
|
|||
|
} else {
|
|||
|
dx=o->DxDt+=RANDOM_MAN_ACCELERATION/sqrt2*RandI16/I16_MAX*dt;
|
|||
|
dy=o->DyDt+=RANDOM_MAN_ACCELERATION/sqrt2*RandI16/I16_MAX*dt;
|
|||
|
}
|
|||
|
}
|
|||
|
d=Sqrt(dx*dx+dy*dy);
|
|||
|
if (d>=1.0) {
|
|||
|
o-><EFBFBD>=Arg(dx,dy)+<EFBFBD>/2;
|
|||
|
dx*=MAN_VELOCITY/sqrt2*dt/d;
|
|||
|
dy*=MAN_VELOCITY/sqrt2*dt/d;
|
|||
|
o->nearest_man_dd=F64_MAX;
|
|||
|
for (j=0;j<PER_SIDE_NUM*2;j++)
|
|||
|
if (j!=i) {
|
|||
|
dx2=objs[j].x-o->x;
|
|||
|
dy2=objs[j].y-o->y;
|
|||
|
d=Sqr(dx2)+Sqr(dy2);
|
|||
|
if (d<o->nearest_man_dd)
|
|||
|
o->nearest_man_dd=d;
|
|||
|
if (d<MAN_SQR_RADIUS) {
|
|||
|
if (d) {
|
|||
|
d=Sqrt(d);
|
|||
|
dx2/=d;
|
|||
|
dy2/=d;
|
|||
|
}
|
|||
|
if (t0>o->foul_t0+0.15) {
|
|||
|
d=(dx-objs[j].DxDt)*dx2+(dy-objs[j].DyDt)*dy2;
|
|||
|
if (o==human && t0>o->foul_t0+1.0 &&
|
|||
|
dt && d/dt>FOUL_VELOCITY_THRESHOLD &&
|
|||
|
objs[j].team) {
|
|||
|
Noise(250,62,62);
|
|||
|
score1+=1;
|
|||
|
foul_t_end=t0+1.0;
|
|||
|
}
|
|||
|
o->foul_t0=t0;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if (t0<o->foul_t0+0.15) {
|
|||
|
dx=-dx;
|
|||
|
dy=-dy;
|
|||
|
}
|
|||
|
o->x+=dx;
|
|||
|
o->y+=dy;
|
|||
|
o->stopped=FALSE;
|
|||
|
} else
|
|||
|
o->stopped=TRUE;
|
|||
|
}
|
|||
|
if (o->DzDt)
|
|||
|
o->z+=dt*(o->DzDt-0.5*GRAVITY_ACCELERATION*dt);
|
|||
|
}
|
|||
|
|
|||
|
if (o->x+o->radius>=parent_task->pix_width-COURT_BORDER) {
|
|||
|
o->x=parent_task->pix_width-COURT_BORDER-1-o->radius;
|
|||
|
o->DxDt=-COLLISION_DAMP*o->DxDt;
|
|||
|
if (o==ball)
|
|||
|
Noise(10,74,86);
|
|||
|
}
|
|||
|
if (o->x-o->radius<COURT_BORDER) {
|
|||
|
o->x=COURT_BORDER+o->radius;
|
|||
|
o->DxDt=-COLLISION_DAMP*o->DxDt;
|
|||
|
if (o==ball)
|
|||
|
Noise(10,74,86);
|
|||
|
}
|
|||
|
|
|||
|
if (o->y+o->radius*2>=(parent_task->pix_height-COURT_BORDER)*2) {
|
|||
|
o->y=(parent_task->pix_height-COURT_BORDER)*2-1-o->radius*2;
|
|||
|
o->DyDt=-COLLISION_DAMP*o->DyDt;
|
|||
|
if (o==ball)
|
|||
|
Noise(10,74,86);
|
|||
|
}
|
|||
|
if (o->y-o->radius*2<2*COURT_BORDER) {
|
|||
|
o->y=COURT_BORDER*2+o->radius*2;
|
|||
|
o->DyDt=-COLLISION_DAMP*o->DyDt;
|
|||
|
if (o==ball)
|
|||
|
Noise(10,74,86);
|
|||
|
}
|
|||
|
|
|||
|
if (o->z-o->radius*2<0) {
|
|||
|
o->z=o->radius*2;
|
|||
|
o->DzDt=-COLLISION_DAMP*o->DzDt;
|
|||
|
if (o->DzDt>ROLL_VELOCITY_THRESHOLD)
|
|||
|
Noise(10,74,86);
|
|||
|
if (o!=ball)
|
|||
|
o->DzDt=0;
|
|||
|
} else if (o->z-o->radius*2>0)
|
|||
|
o->DzDt-=GRAVITY_ACCELERATION*dt;
|
|||
|
if (o==ball) {
|
|||
|
d=Exp(-AIR_VISCOSITY*dt);
|
|||
|
o->DxDt*=d;
|
|||
|
o->DyDt*=d;
|
|||
|
o->DzDt*=d;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
Refresh;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
U0 Init()
|
|||
|
{
|
|||
|
I64 i;
|
|||
|
someone_shooting=FALSE;
|
|||
|
shot_land_t=0;
|
|||
|
MemSet(&objs,0,sizeof(objs));
|
|||
|
for (i=0;i<PER_SIDE_NUM*2;i++) {
|
|||
|
objs[i].team=i&1;
|
|||
|
objs[i].x=Fs->pix_width/2;
|
|||
|
objs[i].y=2*Fs->pix_height/2;
|
|||
|
objs[i].next_img=objs[i].last_img=FIRST_RUNNING;
|
|||
|
}
|
|||
|
last_owner=NULL;
|
|||
|
human=&objs[0];
|
|||
|
ball =&objs[i];
|
|||
|
ball->team=-1;
|
|||
|
ball->x=0.5*Fs->pix_width/2;
|
|||
|
ball->y=0.5*2*Fs->pix_height/2;
|
|||
|
ball->radius=11;
|
|||
|
ball->z=ball->radius;
|
|||
|
score0=score1=0;
|
|||
|
game_t_end=tS+3*60;
|
|||
|
foul_t_end=0;
|
|||
|
}
|
|||
|
|
|||
|
U0 KeepAway()
|
|||
|
{
|
|||
|
I64 msg_code,arg1,arg2;
|
|||
|
|
|||
|
PopUpOk(
|
|||
|
"Pass or hand-off to your team to score points.$$FG$$\n\n"
|
|||
|
"\t2 points for successful hand-off.\n"
|
|||
|
"\t6 points for successful pass.\n"
|
|||
|
"\t1 point penalty for foul.\n\n"
|
|||
|
"Left-Click\tto pass.\n\n"
|
|||
|
"Right-Click\tto jump.\n");
|
|||
|
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
|||
|
Fs->text_attr=BLACK+YELLOW<<4;
|
|||
|
Fs->win_inhibit|=WIG_DBL_CLICK;
|
|||
|
AutoComplete;
|
|||
|
WinBorder;
|
|||
|
WinMax;
|
|||
|
DocCursor;
|
|||
|
DocClear;
|
|||
|
|
|||
|
MenuPush(
|
|||
|
"File {"
|
|||
|
" Abort(,CH_SHIFT_ESC);"
|
|||
|
" Exit(,CH_ESC);"
|
|||
|
"}"
|
|||
|
"Play {"
|
|||
|
" Restart(,'\n');"
|
|||
|
" Shoot(,CH_SPACE);"
|
|||
|
" Jump(,'j');"
|
|||
|
"}"
|
|||
|
);
|
|||
|
|
|||
|
Init;
|
|||
|
Fs->draw_it=&DrawIt;
|
|||
|
Fs->animate_task=Spawn(&AnimateTask,Fs,"Animate",,Fs);
|
|||
|
|
|||
|
try {
|
|||
|
while (TRUE) {
|
|||
|
msg_code=GetMsg(&arg1,&arg2,
|
|||
|
1<<MSG_MS_L_DOWN|1<<MSG_MS_R_DOWN|1<<MSG_KEY_DOWN);
|
|||
|
switch (msg_code) {
|
|||
|
case MSG_MS_L_DOWN:
|
|||
|
ka_shoot:
|
|||
|
Shoot(human);
|
|||
|
break;
|
|||
|
case MSG_MS_R_DOWN:
|
|||
|
ka_jump:
|
|||
|
human->DzDt=JUMP_VELOCITY;
|
|||
|
break;
|
|||
|
case MSG_KEY_DOWN:
|
|||
|
switch (arg1) {
|
|||
|
case '\n':
|
|||
|
Init;
|
|||
|
break;
|
|||
|
case 'j':
|
|||
|
goto ka_jump;
|
|||
|
case CH_SPACE:
|
|||
|
goto ka_shoot;
|
|||
|
case CH_SHIFT_ESC:
|
|||
|
case CH_ESC:
|
|||
|
goto ka_done;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
ka_done: //Don't goto out of try
|
|||
|
GetMsg(,,1<<MSG_KEY_UP);
|
|||
|
} catch
|
|||
|
PutExcept;
|
|||
|
SettingsPop;
|
|||
|
MenuPop;
|
|||
|
RegWrite("TempleOS/KeepAway","I64 best_score0=%d,best_score1=%d;\n",
|
|||
|
best_score0,best_score1);
|
|||
|
}
|
|||
|
|