An object trapped in an imaginary container

The next example demonstrates more regular movement on the part of an object "bouncing around" in a limited 3-D space (or "container"), much as a circle might bounce around in a 2-D Pong window.

Most object acivity is controlled by a single for loop. During each pass through the loop, the position of the object is adjusted by adding a "velocity vector" to the current position.

If the adjusted (or "predicted") position will be outside the container, the velocity vector is changed to prevent escape, and the object's position is adjusted as before.

If the velocity adjustments are small enough, movement should appear smooth.

vector startVelocity;
vector containerSize;

default
{
    state_entry()
    {
        llSay( 0, "Hello, Avatar! Touch to start bouncing.");
        startVelocity = < .7, .5, .6 >;
        containerSize = < 3, 3, 3 >;   // these are offsets from center.
    }

    touch_start(integer total_number)
    {
        llSay( 0, "Touched" );

        vector startPosition;
        vector currentPosition;
        vector possibleNextPosition;
        vector newPosition;

        vector currentVelocity;
        
        vector containerMinima;
        vector containerMaxima;

        float scaleMax;   // maximum object dimension.
        float radius;     // estimated radius of the object.
    
        // get the size of the largest dimension.       
        vector scale = llGetScale(); 
        if( scale.x >= scale.y ) 
        { 
           scaleMax = scale.x; 
        } 
        else 
        { 
           scaleMax = scale.y; 
        }

        // calculate an approximate object radius.  This approximation
        // may not be very good for non-spherical prims.
        if( scaleMax < scale.z ) scaleMax = scale.z;
        radius = scaleMax / 2;  
       
        // define cubical container boundaries for a cube of 6 x 6 x 6 
        // meters centered around the starting position. 
        startPosition = llGetPos();

        containerMinima = startPosition - containerSize;
        containerMaxima = startPosition + containerSize;

        currentVelocity = startVelocity;  
        currentPosition = startPosition;   
        integer i;

        for( i = 1; i < 100; i++ )
        {
            // predict where the object will be if it continues with 
            // its current velocity.
            possibleNextPosition = currentPosition + currentVelocity;
   
            // If one or more of its predicted position vector components 
            // will be outside the container, change the direction of the
            // velocity component corresponding to that position component.
                 
            if( ( possibleNextPosition.x - radius ) < containerMinima.x )
            {
                currentVelocity.x = llFabs( currentVelocity.x ); 
            }
            else if( ( possibleNextPosition.x + radius ) > containerMaxima.x )
            {
                currentVelocity.x = - llFabs( currentVelocity.x );
            }

            if( ( possibleNextPosition.y - radius ) < containerMinima.y )
            {
                currentVelocity.y = llFabs( currentVelocity.y );
            }
            else if( ( possibleNextPosition.y + radius ) > containerMaxima.y )
            {
                currentVelocity.y = - llFabs( currentVelocity.y );
            }

            if( ( possibleNextPosition.z - radius ) < containerMinima.z )
            {
                currentVelocity.z = llFabs( currentVelocity.z );
            }
            else if( ( possibleNextPosition.z + radius ) > containerMaxima.z )
            {
                currentVelocity.z = - llFabs( currentVelocity.z );
            }
 
            newPosition = currentPosition + currentVelocity;
            llSetPos( newPosition );   // reposition object.
            currentPosition = newPosition;
        }
         
        // move object back to starting position...
        llSay( 0, "Wrapping up..." );
        while ( llVecDist( llGetPos(), startPosition) > 0.001) 
        {
            llSetPos( startPosition );
        }
     
        llSay( 0, "Object now resting and resetting script." );
        llResetScript();  // return object to ready state.
    }
}

The algorithm will work better if the object to be bounced is spherical, and close to the default .5 meter size. To keep the bouncing object from settling into a repetitive track, you may wish to add some randomness to the velocity components either occasionally or during each iteration.