// CONSTANTS
// sets a grid of WIDTH by HEIGHT and returns a unique number
// the cases of the grid are numbered line by line, left to right, starting from the bottom
integer WIDTH = 2;
integer HEIGHT = 2;
// With a grid of 2x2 (4 cases), you get a number from 0 to 3
vector bStartPos = <7.5, 5.0, 0.130>; // start position of the ball, center, relative to lower left corner (0, 0, 0)
integer minDir = 3; // minimum velocity
integer maxDir = 9; // maximum velocity
key sndMiss = "096becce-4835-8687-fcd8-059f203f8556";
key sndPaddle = "c85ae514-6329-da29-b959-7f3a73c46a3f";
key sndWall = "14785986-92dc-e9f8-838e-768b8043a036";
// VARIABLES
integer run = FALSE;
float bPosX; // x-position of ball
float bPosY; // y-position of ball
float bDirX; // x-direction of ball
float bDirY; // y-direction of ball
string strFloatX; // for llSay
string strFloatY;
integer collChk; // collision checked
list params; // position of player paddle
init()
{
llSetTimerEvent (0.0);
llSetLinkPrimitiveParamsFast(3, [PRIM_POSITION, <0.0, 0.0, 0.130>]); // game ball (child prim, so coordinates are local!)
llSleep(0.5);
solid();
llSetLinkPrimitiveParamsFast(4, [PRIM_POSITION, <-6.5, 0.0, 0.130>]); // computer paddle
bPosX = bStartPos.x;
bPosY = bStartPos.y;
bDirX = -(float)randIntBetween(minDir, maxDir) / 10; // generate a rnd integer, minimum 3 - maximum 9 (start with -x)
bDirY = (float)randIntBetween(minDir, maxDir) / 10;
strFloatX = llGetSubString((string)bDirX, 0, 3); // reduce to 2 decimals (e.g. -1.0) for llSay()
strFloatY = llGetSubString((string)bDirY, 0, 2);
collChk = FALSE;
params = [];
}
integer randInt(integer n)
{
return (integer)llFrand(n + 1);
}
integer randIntBetween(integer min, integer max)
{
return min + randInt(max - min);
}
transparent()
{
llSetLinkPrimitiveParamsFast(3, [PRIM_COLOR, ALL_SIDES, <0.0, 0.0, 0.0>, 0.0]); // make ball transparent
}
solid()
{
llSetLinkPrimitiveParamsFast(3, [PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0]); // make ball solid
}
default
{
state_entry()
{
init();
llSetLinkPrimitiveParamsFast(5, [PRIM_POSITION, <6.5, 0.0, 0.130>]); // player paddle
}
touch_start(integer total_number)
{
if (run == FALSE)
{
run = !run;
llSetTimerEvent(0.1);
}
}
touch(integer num_detected)
{
vector st = llDetectedTouchST(0);
integer x = llFloor(st.x * WIDTH);
integer y = llFloor(st.y * HEIGHT);
integer button = (y * WIDTH) + x;
button -= 2; // button becomes -1 or 1 for player
if (llAbs(button) == 1) // player's side of field is touched
llOwnerSay((string)button);
}
timer()
{
bPosY += bDirY;
if (bPosY > 10.0) // check top wall
{
llPlaySound(sndWall, 1.0);
bPosY = 10.0;
bDirY = -bDirY;
}
if (bPosY < 0.0) // check bottom wall
{
llPlaySound(sndWall, 1.0);
bPosY = 0.0;
bDirY = -bDirY;
}
bPosX += bDirX;
if (bPosX < 1.0) // check left wall
{
llPlaySound(sndPaddle, 1.0);
bPosX = 1.0;
bDirX = -bDirX;
}
if (bPosX > 14.0) // check collosion here!
{
if (collChk == FALSE)
{
collChk = TRUE; // check only once
params = llGetLinkPrimitiveParams(5, [PRIM_POS_LOCAL]);
vector vParams = llList2Vector(params, 0);
if (bPosY > ((vParams.y + 5.0) - 0.750) && bPosY < ((vParams.y + 5.0) + 0.750)) // collision!
{
llPlaySound(sndPaddle, 1.0);
bPosX = 14.0;
bDirX = -bDirX;
}
}
}
if (bPosX > 15.0) // check right wall
{
llPlaySound(sndMiss, 1.0);
transparent();
run = !run;
init();
}
llSetLinkPrimitiveParamsFast(3, [PRIM_POSITION, <bPosX - 7.5, bPosY - 5.0, bStartPos.z>]); // move ball
llSetLinkPrimitiveParamsFast(4, [PRIM_POSITION, <bStartPos.x - 14.0, bPosY - 5.0, bStartPos.z>]); // move computer paddle
}
}