/*****************************************************************************
Tag.c - JavaScript to play tag with a computer.
The size of the image is the playing field.
*****************************************************************************/
// These values are constants which do not change
// obstacles (rubber posts)
var posts_x = [140, 280, 420, 140, 280, 420];
var posts_y = [120, 120, 120, 240, 240, 240];
var post_width = 31;
var sprite_diameter = 63;
var sprite_radius = 31;
// These values are constants which are calculated at run-time
// These variables track the playing field
var image_width, image_height, right_wall, bottom_wall;
// These values are not constants
// These variables track the mouse
var mouse_x, mouse_y;
// This object tracks the person
var person = [];
// This object tracks the robot
var robot = [];
// These variables keep score
var round = 0;
var score_high = 0;
var timer_id = 0;
/***************************************************************************
Startup initialization
This source depends on the functions provided in Tools.c which
must be included before this source file.
***************************************************************************/
Sprite_Make ("Person");
// Save person values
person.x = 0;
person.y = 0;
Sprite_Move (Tag, Person, person.x, person.y);
// Calculate square of distance to post
post_d = (sprite_diameter + post_width) >> 1;
post_sq = Math.pow (post_d, 2)
post_d += 1;
// Save field size which can't change
image_width = Tag.clientWidth;
image_height = Tag.clientHeight;
right_wall = image_width - sprite_diameter;
bottom_wall = image_height - sprite_diameter;
Sprite_Make ("Robot");
// Save robot values
robot.x = right_wall;
robot.y = bottom_wall;
robot.dx = 0;
robot.dy = 0;
robot_sq = Math.pow (sprite_diameter, 2)
Sprite_Move (Tag, Robot, robot.x, robot.y);
Scores_List ();
document.onmousemove = handlerMM;
document.onclick = Play_Start;
Tag_Message.innerText = "Click on the field to start the game.";
/******************************************************************************
Mouse move handler
******************************************************************************/
function handlerMM ()
{
mouse_x = document.body.scrollLeft + window.event.clientX - Tag.offsetLeft;
mouse_y = document.body.scrollTop + window.event.clientY - Tag.offsetTop;
}
/******************************************************************************
Click handler to start play
******************************************************************************/
function Play_Start ()
{
// Already playing?
if (round)
return;
score_high = 0;
Score_Time.innerText = score_high;
Sprite_Move (Tag, Person, person.x, person.y);
Sprite_Move (Tag, Robot, robot.x, robot.y);
Round_Start ();
}
/******************************************************************************
Start the next round
******************************************************************************/
function Round_Start ()
{
person.x = 0;
person.y = 0;
person.dx = 0;
person.dy = 0;
robot.x = right_wall;
robot.y = bottom_wall;
robot.dx = 0;
robot.dy = 0;
++round;
if (round > 2)
{
Scores_Update ();
round = 0;
Tag_Message.innerText = "Click on the field to start the game.";
return;
}
if (round & 1)
Tag_Message.innerText = "Run! Go tag the computer!";
else
Tag_Message.innerText = "Run! The computer is coming to tag you!";
setTimeout ("Play_Move ()", 1000);
}
/******************************************************************************
timer function for moves during play
******************************************************************************/
function Play_Move ()
{
var dmax;
if (round & 1)
--score_high;
else
++score_high
Score_Time.innerText = score_high;
Move_Object (person, mouse_x, mouse_y);
Sprite_Move (Tag, Person, person.x, person.y);
if (round & 1)
Robot_Run ();
else
Move_Object (robot, person.x, person.y);
Sprite_Move (Tag, Robot, robot.x, robot.y);
// Slow down the robot.
dmax = Math.floor (20 + score_high / 100);
if (dmax < 0)
dmax = 0;
if (dmax < Math.abs (robot.dx))
{
if (robot.dx < 0)
robot.dx = - dmax;
else
robot.dx = dmax;
}
if (dmax < Math.abs (robot.dy))
{
if (robot.dy < 0)
robot.dy = - dmax;
else
robot.dy = dmax;
}
if (Robot_Tag ())
{
if (0 != timer_id)
clearInterval (timer_id);
timer_id = 0;
Round_Start ();
}
else
{
if (0 == timer_id)
timer_id = setInterval ("Play_Move ()", 50);
}
}
/******************************************************************************
The sprite makes the moves
******************************************************************************/
function Move_Object (sprite, dx, dy)
{
var x, y, i;
// Which way does the pointer say to run
x = dx - sprite.x - sprite_radius;
x = x - Factorial (sprite.dx);
if (x < sprite.dx)
--sprite.dx;
if (x > sprite.dx)
++sprite.dx;
y = dy - sprite.y - sprite_radius;
y = y - Factorial (sprite.dy);
if (y < sprite.dy)
--sprite.dy;
if (y > sprite.dy)
++sprite.dy;
sprite.x += sprite.dx;
sprite.y += sprite.dy;
for (var i in posts_x)
Post_Crash (sprite, posts_x[i], posts_y[i]);
// crash into left wall?
if (sprite.x < 0)
{
sprite.x = 0;
sprite.dx = 0;
}
// crash into right wall?
if (sprite.x > right_wall)
{
sprite.x = right_wall;
sprite.dx = 0;
}
// crash into top wall?
if (sprite.y < 0)
{
sprite.y = 0;
sprite.dy = 0;
}
// crash into bottom wall?
if (sprite.y > bottom_wall)
{
sprite.y = bottom_wall;
sprite.dy = 0;
}
}
/******************************************************************************
the robot runs away
******************************************************************************/
function Robot_Run ()
{
var x, y;
x = posts_x[5] - sprite_radius + posts_x[5] - person.x;
y = posts_y[5] - sprite_radius + posts_y[5] - person.y;
Move_Object (robot, x, y);
}
/******************************************************************************
Calculate factorial
******************************************************************************/
function Factorial (x)
{
y = 0;
while (x)
{
y += x;
if (x < 0)
++x;
else
--x;
}
return y;
}
/******************************************************************************
Crash into a post?
******************************************************************************/
function Post_Crash (sprite, x, y)
{
// How far are we from that post?
dx = sprite.x + sprite_radius - x;
dy = sprite.y + sprite_radius - y;
d = Math.pow (dx, 2) + Math.pow (dy, 2);
// Did we crash?
if (post_sq > d)
{
// Bounce back a little bit
angle = Math.atan2 (dx ,dy);
dx = Math.ceil (post_d * Math.sin (angle));
dy = Math.ceil (post_d * Math.cos (angle));
sprite.x = x + dx - sprite_radius;
sprite.y = y + dy - sprite_radius;
}
}
/******************************************************************************
Tag robot?
******************************************************************************/
function Robot_Tag ()
{
d = Math.pow (person.x - robot.x, 2) + Math.pow (person.y - robot.y, 2);
// Did we tag?
if (robot_sq < d)
return false;
return true;
}