Bending Fish

Written by: Headmaster

Original Author: 

Create Date: 10/29/2009

Category: Animation

Description: I found this on a website a long time ago and even though we have animesh, it was fun to use and I thought others might like it to play with. i left the copyright in place because Shine Renoir deserves the kudos for it.

Download Script Here: 

Download All Files

 

 

 

// bending fish
// 2007 Copyright by Shine Renoir (This email address is being protected from spambots. You need JavaScript enabled to view it.)
//

//First create a box A. Edit it, click Object->More and select the Physical checkbox. Then create a box B and select the Features->Flexible Path checkbox. Set 1 for wind for testing. Now first select box B, then ctrl-click box A to select both and click Link in Tools menu. This makes box A the root prim in the link set. Now the whole link set is physical, but box B is still flexible.

//Finally you can add the script below to the link set for a fish movement. Edit the objects by checking the "Edit linked parts" checkbox to make box A invisible, apply texture to box B and rotate it for the right bending effect, change the flexible parameters and move box A within the link set for more realistic movement (somewhere inside the fish).


// The center position is stored on rez.

// maximum swim radius from last center
float radius = 3.0;

// maximum swim distance for swimming up or down from last center
float height = 1.0;

// delay in seconds for next movement
float delay = 4.0;

// internal channel for communication
integer CHANNEL = -87;

// last center position
vector center;

float randBetween(float min, float max)
{
    return llFrand(max - min) + min;
}

init()
{
    llOwnerSay("start swimming");
    llListen(CHANNEL, "", llGetOwner(), "");
    llSetTimerEvent(0.0);
    llSetStatus(STATUS_ROTATE_X, FALSE);
    llSetStatus(STATUS_ROTATE_Y, FALSE);
    float t = llSqrt(2.0) / 2.0;
    llSetRot(<0, 0, 0, 0>);
    center = llGetPos();
    llSetBuoyancy(1.0);
    llSetTimerEvent(delay);
}

default
{
    touch_start(integer num)
    {
        llDialog(llGetOwner(), "Click 'stop', then move the fish to a new center and then click 'start'. Change parameters with the other buttons", ["radius", "height", "delay", "stop", "start"], -33);
    }

    state_entry()
    {
        init();
    }

    on_rez(integer start_num)
    {
        init();
    }

    timer()
    {
        // get current position
        vector pos = llGetPos();
        
        // calculate random next position
        vector dest = pos;
        dest.x += randBetween(-radius, radius);
        dest.y += randBetween(-radius, radius);
        dest.z += randBetween(-radius, height);
        
        // move to center, if outside radius
        integer i;
        for (i = 0; i < 3; i++) {
            if (llVecMag(dest - center) > radius) {
                dest = (dest - pos) / 2.0 + pos;
            }
        } 
        if (dest.z < center.z - height) {
            dest.z += 0.5;
        }
        if (dest.z > center.z + height) {
            dest.z -= 0.5;
        }
        
        // fallback: if other objects pushes the fish, move back to center
        if (llVecMag(dest - center) > radius) {
            dest = center;
        }

        // calculate new rotation and move to target
        vector delta = pos - dest;
        float angle = llAtan2(delta.y, delta.x) + PI / 2.0;
        rotation rot = llEuler2Rot(<0, 0, angle>);
        llRotLookAt(rot, 1.0, 1.0);
        llMoveToTarget(dest, 2);
    }

    listen(integer channel, string name, key id, string message)
    {
        if (message == "stop") {
            llOwnerSay("stop swimming");
            llSetTimerEvent(0.0);
            llStopMoveToTarget();
        } else if (message == "start") {
            init();
        } else if (message == "radius") {
            llDialog(llGetOwner(), "Change radius in meters from center of the fish. Current radius: " + (string) radius, ["radius +1", "radius -1", "radius +5", "radius -5"], -33);
        } else if (message == "radius +1") {
            radius += 1.0;
            llOwnerSay("new radius: " + (string) radius);
        } else if (message == "radius -1") {
            radius -= 1.0;
            if (radius < 1.0) {
                radius = 1.0;
            }
            llOwnerSay("new radius: " + (string) radius);
        } else if (message == "radius +5") {
            radius += 5.0;
            llOwnerSay("new radius: " + (string) radius);
        } else if (message == "radius -5") {
            radius -= 5.0;
            if (radius < 1.0) {
                radius = 1.0;
            }
            llOwnerSay("new radius: " + (string) radius);
        } else if (message == "height") {
            llDialog(llGetOwner(), "Change moving height in meters. Current height: " + (string) height, ["height +1", "height -1", "height +5", "height -5"], -33);
        } else if (message == "height +1") {
            height += 1.0;
            llOwnerSay("new height: " + (string) height);
        } else if (message == "height -1") {
            height -= 1.0;
            if (height < 1.0) {
                height = 1.0;
            }
            llOwnerSay("new height: " + (string) height);
        } else if (message == "height +5") {
            height += 5.0;
            llOwnerSay("new height: " + (string) height);
        } else if (message == "radius -5") {
            height -= 5.0;
            if (height < 1.0) {
                height = 1.0;
            }
            llOwnerSay("new height: " + (string) height);
        } else if (message == "delay") {
            llDialog(llGetOwner(), "Change max delay in seconds. Current delay: " + (string) delay, ["delay +1", "delay -1"], -33);
        } else if (message == "delay +1") {
            delay += 1.0;
            llOwnerSay("new delay: " + (string) delay);
        } else if (message == "delay -1") {
            delay -= 1.0;
            if (delay < 1.0) {
                delay = 1.0;
            }
            llOwnerSay("new delay: " + (string) delay);
        }
    }
}

 

Have Questions? Need help? Leave a note for Kitsune Lassiter in Second Life

 

 

Additional Notes & Instructions(If any):