M
Mark Szlazak
The following page simulates a pool cue and cue ball:
http://members.aol.com/myscript/cue.html
Mouse cursor position around the cue ball determines where a roll-over
of 179 pool cue images is placed around the ball and which one of those
images is displayed. Each pool cue image is in a slightly different
orientation and the correct one is chosen to match the orientation of
the cursor around the ball. Holding down the left mouse button and
dragging the cursor away from the ball along the direction of the cue
then releasing the button makes a shot with the pool cue.
Here is the problem. With some displays of this page, I get a good
roll-over effect while moving my cursor around the ball. The pool cue
images change with cursor position in a smooth even way giving a good
animation of the cue changing orientations around the ball. However, at
other times I get a rough effect and it seems as if a delay is
happening maybe because some images are being downloaded again instead
of retrieved from the browsers cache. I'm guessing at this as the
explanation and don't really know why this is going on with some
displays of this page. Can anyone help in determining what is wrong?
Here is the code:
===================================================================
<html>
<head>
<style>
#ball {
position:absolute;
visibility:hidden;
z-index:10;
}
#cuelyr {
position:absolute;
visibility:hidden;
z-index:5;
}
#box {
position:absolute;
visibility:hidden;
z-index:1;
}
</style>
</head>
<body>
<script>
window.status = ' ';
opera = (window.opera)? 1:0;
nn4 = (document.layers)? 1:0;
ie = (document.all && !opera)? 1:0;
dom = (document.getElementById)? 1:0;
cueLength = 200;
RADIUS = 20;
toDegs = 180/Math.PI;
VMIN = -0.75;
VMAX = 0.75;
cues = [];
if (!nn4 && !ie) document.write("<div id='loadingMsg'>Images
loading</div>");
(function imageLoader() {
for (i=0; i <= 358; i+=2) {
imgSRC = 'cue'+i+'.gif';
cues = new Image();
cues.cnt = 0;
cues.onload = imagesToLoad(i);
cues.onerror = createErrorHandler(imgSRC);
cues.src = imgSRC;
}
})();
function imagesToLoad(i) {
return function () {
if ((i += 2) <= 358) window.status = (179 - (i>>1)) + ' images left
to load.';
else {
window.status = 'Done';
if (!nn4 && !ie) document.getElementById('loadingMsg').innerHTML="";
trapEvents();
}
}
}
function createErrorHandler(imgSRC) {
return function () {
this.src = (this.cnt++ < 3)? imgSRC : 'missing.gif';
}
}
(function setBox(left, top, width, height, border) {
if (!left || left < 0 ) left = 0;
if (!top || top < 0) top = 0;
document.write(
'<div id="box">' +
'<table cellpadding=0 cellspacing=0 border='+border+' width='+width+'
height='+height+'>' +
'<tr><td> <\/td><\/tr><\/table><\/div>'
);
var lyr;
if (nn4) { lyr = document.layers['box']; lyr.style = lyr; }
else lyr = (ie)? document.all['box']
dom)?
document.getElementById('box'):null;
var box = lyr.style;
box.left = left;
box.top = top;
box.visibility = (nn4)? 'show':'visible';
XMIN = left + border + RADIUS + 1;
XMAX = width + left - border - RADIUS;
YMIN = top + border + RADIUS + 1;
YMAX = height + top - border - RADIUS;
})(60, 30, 675, 400, 5);
(function setBall(imgSRC, left, top) {
if (!left || left < 0 ) left = 0;
if (!top || top < 0) top = 0;
document.write('<div id="ball"><img src="' + imgSRC + '"
border=0><\/div>');
if (nn4)
{ lyr = document.layers['ball']; lyr.style = lyr; }
else
lyr = (ie)? document.all['ball']
dom)?
document.getElementById('ball'):null;
cueball = lyr.style;
cueball.left = left;
cueball.top = top;
cueball.visibility = (nn4)? 'show':'visible';
cueball.X = left + RADIUS;
cueball.Y = top + RADIUS;
cueball.Vx;
cueball.Vy;
cueball.isZero = function(x) {
return (x > VMIN && x < VMAX)? 1:0;
}
cueball.move = function() {
if (cueball.isZero(cueball.Vx) && cueball.isZero(cueball.Vy)) {
setTimeout('cue.reset()',500);
return;
}
var nextX = cueball.X + cueball.Vx;
var nextY = cueball.Y + cueball.Vy;
if (nextX <= XMIN) { cueball.X = XMIN; cueball.Vx *= -.98; }
else if (nextX >= XMAX) { cueball.X = XMAX; cueball.Vx *= -.98; }
else { cueball.X = nextX; cueball.Vx *= .98; }
if (nextY <= YMIN) { cueball.Y = YMIN; cueball.Vy *= -.98; }
else if (nextY >= YMAX) { cueball.Y = YMAX; cueball.Vy *= -.98; }
else { cueball.Y = nextY; cueball.Vy *= .98; }
cueball.left = cueball.X - RADIUS;
cueball.top = cueball.Y - RADIUS;
setTimeout('cueball.move()',0);
}
})('grayball.gif',350,205);
(function setCue() {
var lyr, rn, rads;
var toRads = Math.PI/180;
document.write('<div id="cuelyr"><img name="poolcue" src="cue0.gif"
border=0><\/div>');
if (nn4)
{ lyr = document.layers['cuelyr']; lyr.style = lyr; }
else
lyr = (ie)? document.all['cuelyr']
dom)?
document.getElementById('cuelyr'):null;
cue = lyr.style;
cue.distance = 1;
cue.rotation = 0;
cue.drag;
cue.showing;
cue.halfLength = cueLength/2;
cue.xNormal = new Array();
cue.yNormal = new Array();
for(rn=0; rn <= 358; rn+=2) {
cue.xNormal[rn] = -Math.sin(rads = toRads*(rn - 90));
cue.yNormal[rn] = Math.cos(rads);
}
cue.setDistance = function(d) {
cue.distance = (d<0)? 0
d>35)? 35:d;
}
cue.setRotation = function(r) {
r = (r % 2 != 0)? --r : r;
cue.rotation = (r > 358)? 0 : r;
}
cue.place = function() {
var round = Math.round;
var s;
cue.img.src = cues[cue.rotation].src;
cue.left = round(cueball.X - cue.halfLength +
cue.xNormal[cue.rotation]*(cue.halfLength + (s = RADIUS +
cue.distance)));
cue.top = round(cueball.Y - cue.halfLength +
cue.yNormal[cue.rotation]*(cue.halfLength + s));
}
cue.takeShot = function() {
releaseTrapping();
cueball.Vx = -Vxn;
cueball.Vy = -Vyn;
setTimeout('cue.hide(); cueball.move()', 100);
}
cue.reset = function() {
trapEvents();
cue.distance = 1;
cue.rotation = 0;
cue.place();
cue.show();
}
cue.show = function() {
cue.visibility = (nn4)? "show":"visible";
cue.showing = 1;
}
cue.hide = function() {
cue.showing = 0;
cue.visibility = (nn4)? "hide":"hidden";
}
})();
function MouseMove(x,y) {
var dX, dY;
var round = Math.round;
var atan2 = Math.atan2;
var sqrt = Math.sqrt;
if (cue.showing) {
mouseX = x; mouseY = y;
dX = x - cueball.X;
dY = y - cueball.Y;
if (cue.drag)
cue.setRotation(round((dY < 0)? atan2(dY,dX)*toDegs + 360:
atan2(dY,dX)*toDegs));
else
cue.setDistance(((currentDistance = sqrt(dX*dX+dY*dY)) -
startDistance));
cue.place();
}
return false;
}
function trapEvents() {
if (nn4) {
document.captureEvents(Event.MOUSEDOWN | Event.MOUSEUP |
Event.MOUSEMOVE);
document.onmousemove = function(e) { return MouseMove(e.pageX,
e.pageY); }
}
else
document.onmousemove = (ie)? function() { return
MouseMove(event.clientX, event.clientY); } : function(e) { return
MouseMove(e.clientX, e.clientY); }
document.onmousedown = function(e) {
cue.drag = 0;
var sqrt = Math.sqrt;
var dX, dY;
startDistance = sqrt((dX=mouseX-cueball.X)*dX +
(dY=mouseY-cueball.Y)*dY);
return false;
}
document.onmouseup = function(e) {
cue.drag = 1;
Vxn = cue.distance * cue.xNormal[cue.rotation];
Vyn = cue.distance * cue.yNormal[cue.rotation];
cue.distance = 0;
cue.place();
cue.takeShot();
}
}
function releaseTrapping() {
if (nn4) document.releaseEvents(Event.MOUSEDOWN | Event.MOUSEUP |
Event.MOUSEMOVE);
document.onmousemove = null;
document.onmousedown = null;
document.onmouseup = null;
}
function pageLoadHandler() {
cue.showing = 1;
cue.drag = 1;
cue.img = (nn4)? cue.document.images.poolcue : document.poolcue;
cue.rotation = 0;
cue.place();
cue.visibility = (nn4)? "show":"visible";
}
onload = (ie||nn4)? pageLoadHandler
ageLoadHandler();
</script>
</body>
</html>
http://members.aol.com/myscript/cue.html
Mouse cursor position around the cue ball determines where a roll-over
of 179 pool cue images is placed around the ball and which one of those
images is displayed. Each pool cue image is in a slightly different
orientation and the correct one is chosen to match the orientation of
the cursor around the ball. Holding down the left mouse button and
dragging the cursor away from the ball along the direction of the cue
then releasing the button makes a shot with the pool cue.
Here is the problem. With some displays of this page, I get a good
roll-over effect while moving my cursor around the ball. The pool cue
images change with cursor position in a smooth even way giving a good
animation of the cue changing orientations around the ball. However, at
other times I get a rough effect and it seems as if a delay is
happening maybe because some images are being downloaded again instead
of retrieved from the browsers cache. I'm guessing at this as the
explanation and don't really know why this is going on with some
displays of this page. Can anyone help in determining what is wrong?
Here is the code:
===================================================================
<html>
<head>
<style>
#ball {
position:absolute;
visibility:hidden;
z-index:10;
}
#cuelyr {
position:absolute;
visibility:hidden;
z-index:5;
}
#box {
position:absolute;
visibility:hidden;
z-index:1;
}
</style>
</head>
<body>
<script>
window.status = ' ';
opera = (window.opera)? 1:0;
nn4 = (document.layers)? 1:0;
ie = (document.all && !opera)? 1:0;
dom = (document.getElementById)? 1:0;
cueLength = 200;
RADIUS = 20;
toDegs = 180/Math.PI;
VMIN = -0.75;
VMAX = 0.75;
cues = [];
if (!nn4 && !ie) document.write("<div id='loadingMsg'>Images
loading</div>");
(function imageLoader() {
for (i=0; i <= 358; i+=2) {
imgSRC = 'cue'+i+'.gif';
cues = new Image();
cues.cnt = 0;
cues.onload = imagesToLoad(i);
cues.onerror = createErrorHandler(imgSRC);
cues.src = imgSRC;
}
})();
function imagesToLoad(i) {
return function () {
if ((i += 2) <= 358) window.status = (179 - (i>>1)) + ' images left
to load.';
else {
window.status = 'Done';
if (!nn4 && !ie) document.getElementById('loadingMsg').innerHTML="";
trapEvents();
}
}
}
function createErrorHandler(imgSRC) {
return function () {
this.src = (this.cnt++ < 3)? imgSRC : 'missing.gif';
}
}
(function setBox(left, top, width, height, border) {
if (!left || left < 0 ) left = 0;
if (!top || top < 0) top = 0;
document.write(
'<div id="box">' +
'<table cellpadding=0 cellspacing=0 border='+border+' width='+width+'
height='+height+'>' +
'<tr><td> <\/td><\/tr><\/table><\/div>'
);
var lyr;
if (nn4) { lyr = document.layers['box']; lyr.style = lyr; }
else lyr = (ie)? document.all['box']
document.getElementById('box'):null;
var box = lyr.style;
box.left = left;
box.top = top;
box.visibility = (nn4)? 'show':'visible';
XMIN = left + border + RADIUS + 1;
XMAX = width + left - border - RADIUS;
YMIN = top + border + RADIUS + 1;
YMAX = height + top - border - RADIUS;
})(60, 30, 675, 400, 5);
(function setBall(imgSRC, left, top) {
if (!left || left < 0 ) left = 0;
if (!top || top < 0) top = 0;
document.write('<div id="ball"><img src="' + imgSRC + '"
border=0><\/div>');
if (nn4)
{ lyr = document.layers['ball']; lyr.style = lyr; }
else
lyr = (ie)? document.all['ball']
document.getElementById('ball'):null;
cueball = lyr.style;
cueball.left = left;
cueball.top = top;
cueball.visibility = (nn4)? 'show':'visible';
cueball.X = left + RADIUS;
cueball.Y = top + RADIUS;
cueball.Vx;
cueball.Vy;
cueball.isZero = function(x) {
return (x > VMIN && x < VMAX)? 1:0;
}
cueball.move = function() {
if (cueball.isZero(cueball.Vx) && cueball.isZero(cueball.Vy)) {
setTimeout('cue.reset()',500);
return;
}
var nextX = cueball.X + cueball.Vx;
var nextY = cueball.Y + cueball.Vy;
if (nextX <= XMIN) { cueball.X = XMIN; cueball.Vx *= -.98; }
else if (nextX >= XMAX) { cueball.X = XMAX; cueball.Vx *= -.98; }
else { cueball.X = nextX; cueball.Vx *= .98; }
if (nextY <= YMIN) { cueball.Y = YMIN; cueball.Vy *= -.98; }
else if (nextY >= YMAX) { cueball.Y = YMAX; cueball.Vy *= -.98; }
else { cueball.Y = nextY; cueball.Vy *= .98; }
cueball.left = cueball.X - RADIUS;
cueball.top = cueball.Y - RADIUS;
setTimeout('cueball.move()',0);
}
})('grayball.gif',350,205);
(function setCue() {
var lyr, rn, rads;
var toRads = Math.PI/180;
document.write('<div id="cuelyr"><img name="poolcue" src="cue0.gif"
border=0><\/div>');
if (nn4)
{ lyr = document.layers['cuelyr']; lyr.style = lyr; }
else
lyr = (ie)? document.all['cuelyr']
document.getElementById('cuelyr'):null;
cue = lyr.style;
cue.distance = 1;
cue.rotation = 0;
cue.drag;
cue.showing;
cue.halfLength = cueLength/2;
cue.xNormal = new Array();
cue.yNormal = new Array();
for(rn=0; rn <= 358; rn+=2) {
cue.xNormal[rn] = -Math.sin(rads = toRads*(rn - 90));
cue.yNormal[rn] = Math.cos(rads);
}
cue.setDistance = function(d) {
cue.distance = (d<0)? 0
}
cue.setRotation = function(r) {
r = (r % 2 != 0)? --r : r;
cue.rotation = (r > 358)? 0 : r;
}
cue.place = function() {
var round = Math.round;
var s;
cue.img.src = cues[cue.rotation].src;
cue.left = round(cueball.X - cue.halfLength +
cue.xNormal[cue.rotation]*(cue.halfLength + (s = RADIUS +
cue.distance)));
cue.top = round(cueball.Y - cue.halfLength +
cue.yNormal[cue.rotation]*(cue.halfLength + s));
}
cue.takeShot = function() {
releaseTrapping();
cueball.Vx = -Vxn;
cueball.Vy = -Vyn;
setTimeout('cue.hide(); cueball.move()', 100);
}
cue.reset = function() {
trapEvents();
cue.distance = 1;
cue.rotation = 0;
cue.place();
cue.show();
}
cue.show = function() {
cue.visibility = (nn4)? "show":"visible";
cue.showing = 1;
}
cue.hide = function() {
cue.showing = 0;
cue.visibility = (nn4)? "hide":"hidden";
}
})();
function MouseMove(x,y) {
var dX, dY;
var round = Math.round;
var atan2 = Math.atan2;
var sqrt = Math.sqrt;
if (cue.showing) {
mouseX = x; mouseY = y;
dX = x - cueball.X;
dY = y - cueball.Y;
if (cue.drag)
cue.setRotation(round((dY < 0)? atan2(dY,dX)*toDegs + 360:
atan2(dY,dX)*toDegs));
else
cue.setDistance(((currentDistance = sqrt(dX*dX+dY*dY)) -
startDistance));
cue.place();
}
return false;
}
function trapEvents() {
if (nn4) {
document.captureEvents(Event.MOUSEDOWN | Event.MOUSEUP |
Event.MOUSEMOVE);
document.onmousemove = function(e) { return MouseMove(e.pageX,
e.pageY); }
}
else
document.onmousemove = (ie)? function() { return
MouseMove(event.clientX, event.clientY); } : function(e) { return
MouseMove(e.clientX, e.clientY); }
document.onmousedown = function(e) {
cue.drag = 0;
var sqrt = Math.sqrt;
var dX, dY;
startDistance = sqrt((dX=mouseX-cueball.X)*dX +
(dY=mouseY-cueball.Y)*dY);
return false;
}
document.onmouseup = function(e) {
cue.drag = 1;
Vxn = cue.distance * cue.xNormal[cue.rotation];
Vyn = cue.distance * cue.yNormal[cue.rotation];
cue.distance = 0;
cue.place();
cue.takeShot();
}
}
function releaseTrapping() {
if (nn4) document.releaseEvents(Event.MOUSEDOWN | Event.MOUSEUP |
Event.MOUSEMOVE);
document.onmousemove = null;
document.onmousedown = null;
document.onmouseup = null;
}
function pageLoadHandler() {
cue.showing = 1;
cue.drag = 1;
cue.img = (nn4)? cue.document.images.poolcue : document.poolcue;
cue.rotation = 0;
cue.place();
cue.visibility = (nn4)? "show":"visible";
}
onload = (ie||nn4)? pageLoadHandler
</script>
</body>
</html>