• Bitte schaltet eure Ad Blocker aus. SLinfo kann nur betrieben werden, wenn es durch Werbung Einnahmen erzielt. Vielen Dank!!
  • Wir freuen uns, wenn du dich in unserem Forum anmeldest. Bitte beachte, dass die Freigabe per Hand durchgeführt wird (Schutz vor Spammer). Damit kann die Freigabe bis zu 24 Stunden dauern.
  • Wir verwenden Cookies, um Inhalte und Anzeigen zu personalisieren, Funktionen für soziale Medien anbieten zu können und die Zugriffe auf unsere Website zu analysieren. Sie geben Einwilligung zu unseren Cookies, wenn Sie unsere Webseite weiterhin nutzen.

bounce script richtungsbewegung stoppen

Duffy Kohime

Aktiver Nutzer
Hallo zusammen,
nach ner längeren Pause hab ich nochmal eine Idee um was zu basteln, komme aber nicht weiter, weil mein Object immer abhaut.
dieses script habe ich:
Code:
vector startpos;

vector randvector()
{
//    float maxmax = 4.00;
//    float max = llFrand(maxmax);
//    float x = llFrand(max+llFrand(max));
//    max = llFrand(maxmax);
//    float y = llFrand(max+llFrand(max));
//    max = llFrand(maxmax);
//    float z = llFrand(max+llFrand(max));
//    vector rvect = <x,y,z>;
//    return rvect;

    float x = llRound(llFrand(1));
    float y = llRound(llFrand(1));
    float z = llRound(llFrand(5));
    if (z < 3) z = 1;
    vector rvect = <x,y,z>;
//    llOwnerSay((string)rvect);
    return rvect;
}

GetStart()
{
    startpos = llGetPos();
}

Reset()
{
    llSetStatus(STATUS_PHYSICS,FALSE); 
    llSetPos(startpos);
}

bounce()
{
    llSetStatus(STATUS_PHYSICS,TRUE);
    llApplyImpulse(randvector(),FALSE);
    
}

default
{
    state_entry()
    {
        llSetTimerEvent(1);
    }

    touch_start(integer total_number)
    {
    }

    timer()
    { 
        bounce();
    }

}
Das Script ansich ist ja nix besonderes und sicher bekannt. Aber wie bekomme ich es hin das mein object in einem bestimmten Bereich springt, bzw radius. im Moment ist es so das es immer in eine Richtung abdackelt und irgendwann weg ist wenn keine Begrenzung Drumherum ist.
geht das ?

Danke Euch greetz Duff

edit x und y auf null setzen soweit bin ich hab ich vergessen zu erwähnen. aber würde gerne radius einarbeiten z.b 5x5 m
 
Zuletzt bearbeitet:
Naja wenn du das Ding anschubst hüpft es eben immer weiter. Mit Timer und llVecDist kannst ja prüfen ob es noch in dem Bereich ist und gegebenfalls wieder ausschalten bzw. ne andere Richtung geben.
 
Hallo Duffy,

in meinem Beispiel mache ich das mit llMoveToTarget:

Code:
float RADIUS = 5.0; //meter

float fTimer = 1.0; //seconds

float fMinTau = 0.2; //minimum Tau (time to reach target).

vector vOriginalPosition; //store start-position.

integer iSTARTED = FALSE; //store active-state.
start()
{ //store start-position and start movement.
    vOriginalPosition = llGetPos();
    llSetTimerEvent(fTimer);
    llSetStatus(STATUS_PHYSICS, TRUE);
    iSTARTED = TRUE;
}
stop()
{ //end movement and reset position.
    llSetTimerEvent(0.0);
    llSetStatus(STATUS_PHYSICS, FALSE);
    llSetRegionPos(vOriginalPosition);
    iSTARTED = FALSE;
}
move()
{ //movement within radius.
    vector vTarget = <llFrand(RADIUS),llFrand(RADIUS),llFrand(RADIUS)>;
    if (llFrand(1.0) > 0.5)
    {
        vTarget.x = -vTarget.x;
    }
    if (llFrand(1.0) > 0.5)
    {
        vTarget.y = -vTarget.y;
    }
    if (llFrand(1.0) > 0.5)
    {
        vTarget.z = -vTarget.z;
    }
    llMoveToTarget(vOriginalPosition + vTarget, llFrand(fTimer) + fMinTau);
}
default
{
    state_entry()
    {
        start();
    }
    touch_start(integer total_number)
    {
        if (iSTARTED)
        { //toggle on / off.
            stop();
        }
        else
        {
            start();
        }
    }
    timer()
    {
        move();
    }
}


Die von dir verwendete Methode hat den Nachteil, dass bis zur nächsten Überprüfung wo sich das Prim befindet, es schon längst über alle Berge sein kann.
 
Wenn das ganze mehr oder weniger zufällig "hüpfen" soll, dann muss man schon über den Impuls arbeiten, den das Ding mit llAplyImpulse kriegt. Allerdings muss man dann den Vektor, den man dieser Funktion mitgibt, so modifizieren, dass er eben nicht ohne alle Grenzen in alle Richtungen geht. Man braucht also erst mal ein Zentrum, um das sich alles Hüpfen drehen soll. Das holt man sich z.B. per vector Startpos = llGetPos() beim Script-Start/nach einem Reset. Dann lässt man das Ding einmal zufällig hüpfen, so dass das Objekt eben nicht mehr am Startpunkt liegt und anschließend startet man den Timer, in dem das Objekt regelmäßig hüpft.

Und genau hier müsste man nun den Richtungsvektor bzw. den Impulsvektor bisschen manipulieren. Und zwar so, dass das Objekt immer stärker zum Startpunkt hin springt als in irgendwelche andere Richtungen.
Also holt man erst mal wieder einen Zufallsvektor RandVec, der dann normiert wird (über llVecNorm), so dass RandVec danach eben die Länge 1 hat. Damit haben wir erst mal einen immer gleich großen Impuls, nur in verschiedene zufällige Richtungen. Was dann noch fehlt ist ein skalieren des Richtungsvektors, und zwar so, dass er weniger groß wird, wenn er weg geht vom Startpunkt, aber größer wird, wenn er in Richtung Startpunkt geht. Also brauchen wir zusätzlich zum Zufallsvektor noch den Vektor von der momentanen Position in Richtung Startpunkt. So dass man eben den Winkel zwischen dem Zufallsvektor und dem Vektor in Richtung Start bestimmen kann. (gibt leider keine direkte LSL Funktion dafür, aber man kann das ja über den cosinus und Skalarprodukt usw. leicht per script ausrechnen) Ist dieser Winkel dann z.B. 180°, dann geht das Springen direkt weg vom Startpunkt. Ist der Winkel 0°, dann geht der Zufallswinkel direkt in Richtung Start. (Man muss da nur mit den Richtungen der Vektoren bisschen aufpassen) Also muss man eben den Impuls über a * RandVec abhängig von diesem Winkel zwischen den Vektoren skalieren. Bei großem Winkel lässt man den Impuls über ein kleines a klein werden, bei kleinen Winkel kann man a größer werden lassen, so dass eben der Impuls in Richtung Startpunkt auch größer wird.
Welche Werte man da genau nehmen muss hängt dann von der jeweiligen Situation usw. ab, wobei der Impuls generell nicht größer als 20 werden kann (llAplyImpuls ist auf eine Magnitude/Größe des Vektors von 20 begrenzt), und 0 sollten man a nicht werden lassen, da das Objekt dann in diesem Takt sonst wohl gar nicht springt.

Am Ende sollte das Objekt jednfalls immer noch zufällig durch die Gegend springen, aber einen Bereich rund um den Startpunkt haben, an dem es sich am wahrscheinlichsten aufhält.
 
nach bisschen testen in SL: Der Zufall hat da manchmal eine miese Verteilung, deswegen sollte man eine "Rückholroutine" einbauen

Code:
vector startpos;
//die folgenden Werte muss man anpassen:
float TickerTime = 1.0;
float factor = 40.0; //generelle Skalierung des Zuffallsimpulses
float Distance = 20.0 //Radius im den sich das Ding bewegen soll

vector randvec(){
    vector ret;
    ret.x = llFrand(4.0) - 2.0;
    ret.y = llFrand(4.0) - 2.0;
    ret.z = llFrand(4.0) + 1.0;
    return ret;
}

default
{
    state_entry()
    {
        startpos = llGetPos();
        llSetStatus(STATUS_PHYSICS,TRUE);
        llApplyImpulse(randvec(), FALSE);
        llSetTimerEvent(TickerTime);
    }

    timer()
    {
        vector vrand;
        float angle;
        float impulse;

        //Vektor in Startrichtung bestimmen
        vector pos = llGetPos() - startpos + <0,0,0.01>; 
        //pos ist damit immer != 0, auch wenn das Teil am Start liegen bleibt
        
        if (llVecDist(llGetPos(),startpos) < Distance){
            //zufallswinkel bestimmen
            vrand = randvec();
            //winkel berechen zwischen den beiden
            angle = llAcos((pos * vrand)/(llVecMag(pos)*llVecMag(vrand)));
            angle = angle * RAD_TO_DEG;

        //impulse /Skalierung berechnen...    
        impulse = (180.0 - angle)/factor;          
        }

        //Sicherung, damit das Teil nicht zu weit weg fliegt...
        else{
            vrand = -pos; //zurück zum Start
            angle = 0;
            impulse = factor/10;
        }

        //Zufallsvektor normalisieren und über impulse Skalieren
        vrand = llVecNorm(vrand);
        vrand = impulse * vrand;

        //Impuls auslösen
        llApplyImpulse(vrand,FALSE);
    }
}
 
nach bisschen testen in SL: Der Zufall hat da manchmal eine miese Verteilung, deswegen sollte man eine "Rückholroutine" einbauen

Code:
vector startpos;
//die folgenden Werte muss man anpassen:
float TickerTime = 1.0;
float factor = 40.0; //generelle Skalierung des Zuffallsimpulses
float Distance = 20.0 //Radius im den sich das Ding bewegen soll

vector randvec(){
    vector ret;
    ret.x = llFrand(4.0) - 2.0;
    ret.y = llFrand(4.0) - 2.0;
    ret.z = llFrand(4.0) + 1.0;
    return ret;
}

default
{
    state_entry()
    {
        startpos = llGetPos();
        llSetStatus(STATUS_PHYSICS,TRUE);
        llApplyImpulse(randvec(), FALSE);
        llSetTimerEvent(TickerTime);
    }

    timer()
    {
        vector vrand;
        float angle;
        float impulse;

        //Vektor in Startrichtung bestimmen
        vector pos = llGetPos() - startpos + <0,0,0.01>; 
        //pos ist damit immer != 0, auch wenn das Teil am Start liegen bleibt
        
        if (llVecDist(llGetPos(),startpos) < Distance){
            //zufallswinkel bestimmen
            vrand = randvec();
            //winkel berechen zwischen den beiden
            angle = llAcos((pos * vrand)/(llVecMag(pos)*llVecMag(vrand)));
            angle = angle * RAD_TO_DEG;

        //impulse /Skalierung berechnen...    
        impulse = (180.0 - angle)/factor;          
        }

        //Sicherung, damit das Teil nicht zu weit weg fliegt...
        else{
            vrand = -pos; //zurück zum Start
            angle = 0;
            impulse = factor/10;
        }

        //Zufallsvektor normalisieren und über impulse Skalieren
        vrand = llVecNorm(vrand);
        vrand = impulse * vrand;

        //Impuls auslösen
        llApplyImpulse(vrand,FALSE);
    }
}


Das Skript ist semi-optional - abgesehen davon dass es nicht kompiliert weil ein Semikolon fehlt, stolpert ein Standard-Prim immer über sich selbst, dadurch sieht das nicht sehr gut aus.

Wenn du wirklich lieber ein 'Herumdackeln' möchtest, bietet sich doch ein Pathfinding-Character an:

Code:
vector vWithin = <10.0, 10.0, 5.0>;
vector vStart;
float fMaxSpeed = 25.0;
float fDesiredSpeed = 15.0;
integer iRunning = FALSE;

start()
{
    vStart = llGetPos();
    llCreateCharacter([CHARACTER_MAX_SPEED, fMaxSpeed, CHARACTER_DESIRED_SPEED, fDesiredSpeed]);
    llWanderWithin(llGetPos(), vWithin, [WANDER_PAUSE_AT_WAYPOINTS, TRUE]);
    iRunning = TRUE;
}
stop()
{
    llDeleteCharacter();
    llSetRegionPos(vStart);
    iRunning = FALSE;
}
default
{
    state_entry()
    {
        start();
    }
 
    touch_start(integer total_number)
    {
        if (iRunning)
        {
            stop();
        }
        else
        {
            start();
        }
    }
}
 
Das Ding sollte ja doof in der Gegend rumspringen. Und mit einer Sphere mit entsprechenden Physik-parametern (Masse/Größe/Bouncing) passt es einigermaßen.
 
gugugg zusammen,
mal genial was ihr euch für Gedanken macht. aber es soll tatsächlich herumspringen wie ein flummi. und nicht herumdackeln. aber auch dieses script hat mir schon geholfen.
das eine script von shirly geht bei mir gar nicht rührt sich nix (rückholrutine), hab schon div Einstellungen geändert. aber nüx. das Semikolon habsch auch eingefügt.
das erste script von Martin.....ist schon ne menge wert ich versuche nur noch das dieses objekt sich nicht immer um die eigene achse dreht- für nen flummi nicht schlimm, aber je nach objekt sieht das unschön aus. müsste da verhindern das es rotiert (achsen).

aber bis hier hin schon genial. im Moment brauche ich noch ein bischen mehr zeit um es zu testen.usw. bin etwas eingespannt . aber der winter nat.

Lg Duffy ;)
 
das hier:

Code:
float Distance = 10.0; //Radius in dem das Ding springen soll
float factor = 2.0;    //stärke des Impulses beim Springen, nicht zu hoch drehen
//bei hohem Impuls kann sich die Sprungenergie schnell aufschaukeln.

vector startpos;

//zufallsvector generieren, normiert damit Länge/Betrag = 1.0
//so gehts in alle Richtungen gleich stark.
vector randvec(){
    vector ret;
    ret.x = llFrand(4.0) - 2.0;
    ret.y = llFrand(4.0) - 2.0;
    ret.z = llFrand(2.0) + 2.0;
    ret = llVecNorm(ret);
    return ret;
}


//Sprungfunktion
Jolly(){

    vector pos = llGetPos();
    if (llVecDist(pos,startpos) < Distance){
        vector dir = randvec() * factor;
        llApplyImpulse(dir,FALSE);
    }

    //zurückspringen, wenn zu weit entfernt
    else{
        //Vektor in Richtung Start
        vector startdir = pos - startpos;
        //Richtung nach oben anpassen, Normieren und Faktor berücksichtigen
        startdir = llVecNorm(-1 * startdir + <0,0,4.0>) * factor;
        //Springen
        llApplyImpulse(startdir,FALSE);
    }

    //timer, falls es doch mal liegen bleibt (lag)
    llSetTimerEvent(5.0);
}



default
{
    state_entry()
    {
        //Prim vorbereiten damit es besser springt
        llSetStatus(STATUS_DIE_AT_EDGE|STATUS_PHYSICS, TRUE);
        llSetPrimitiveParams([PRIM_MATERIAL,PRIM_MATERIAL_RUBBER]);
        llSetPrimitiveParams([PRIM_TYPE,3, 0, <0.0, 1.0, 0.0>, 0.0, ZERO_VECTOR, <0.0, 1.0, 0.0>]);//normale sphere

        //Startpunkt festlegen
        startpos = llGetPos();
        //Listener um es löschen zu können
        llListen(10,"",NULL_KEY,"");
        //springen um zu starten;
        llApplyImpulse(randvec(),FALSE);

    }

    collision_start(integer total_number)
    {
        Jolly();
    }

    land_collision_start(vector position)
    {
        Jolly();
    }
    touch_start(integer total_number)
    {
        Jolly();
    }

    //listener z.B. für llRegionSay in einem andern Prim, sollte das Teil doch mal abhauen wegen lag
    listen(integer channel, string name, key id, string message)
    {
        if (message == "die!"){
            llDie();
        }
    }
    //timer wegen lag: Wieder mal springen
    timer()
    {
        llApplyImpulse(<0,0,4>,FALSE);
    }

}

sollte eher wie ein Gummiball werden. Das Prim springt nun immer dann, wenn es aufkommt oder anstößt.
Ein Problem bei Physik in SL kann allerdings Lag sein, das kann dazu führen, dass ein Prim nicht mehr springt (deswegen der Timer) oder aber, dass es einfach mal abhaut und "weg fliegt". Deswegen STATUS_DIE_AT_EDGE und eben der Listener, über den man das Prim dann über ein "llRegionSay(10,"die!")" aus einem anderen Prim löschen kann.
 
@ Shirley

Ich fuerchte du musst die Masse noch beruecksichtigen, sobald der Ball 1.000 Meter gross ist, funktioniert es nicht mehr.

LG
Dae

Das mit der Größe geht nur in bestimmten Grenzen, da der Impuls bei llApplyImpulse maximal 20.0 groß sein kann. D.h. ab einer gewissen Größe müsste man das Ding noch zusätzlich hohl machen und auch über llSetPhysicsMaterial die Dichte entsprechend anpassen, damit das Prim leichter wird.

Aber für kleinere Prims bis 5m oder 6m oder so (grob geschätzt) sollte das hier gehen:

Code:
float Distance = 10.0; //Radius in dem das Ding springen soll
float densfact = 32.5;   //Dämpfung des Impulses beim Springen, nicht zu niedrig setzen
//bei hohem Impuls kann sich die Sprungenergie schnell aufschaukeln.

vector startpos;
float factor;
//zufallsvector generieren, normiert damit Länge = 1.0
//so gehts in alle Richtungen gleich stark.
vector randvec(){
    vector ret;
    ret.x = llFrand(4.0) - 2.0;
    ret.y = llFrand(4.0) - 2.0;
    ret.z = llFrand(2.0) + 2.0;
    ret = llVecNorm(ret);
    return ret;
}


//Sprungfunktion
Jolly(){

    vector pos = llGetPos();
    if (llVecDist(pos,startpos) < Distance){
        vector dir = randvec() * factor;
        llApplyImpulse(dir,FALSE);
    }

    //zurückspringen, wenn zu weit entfernt
    else{
        //Vektor in Richtung Start
        vector startdir = pos - startpos;
        //Richtung nach oben anpassen, Normieren und Faktor berücksichtigen
        startdir = llVecNorm(-1 * startdir + <0,0,4.0>) * factor;
        //Springen
        llApplyImpulse(startdir,FALSE);
    }

    //timer, falls es doch mal liegen bleibt (lag)
    llSetTimerEvent(5.0);
}



default
{
    state_entry()
    {
        //Prim vorbereiten damit es besser springt
        llSetStatus(STATUS_DIE_AT_EDGE|STATUS_PHYSICS, TRUE);
        llSetPrimitiveParams([PRIM_MATERIAL,PRIM_MATERIAL_RUBBER]);
        llSetPrimitiveParams([PRIM_TYPE,3, 0, <0.0, 1.0, 0.0>, 0.0, ZERO_VECTOR, <0.0, 1.0, 0.0>]);//normale sphere

        //Masse anpassen
        float mass = llGetMassMKS(); //Normal Prim Sphere = 65
        factor = mass / densfact;


        //Startpunkt festlegen
        startpos = llGetPos();
        //Listener um es löschen zu können
        llListen(10,"",NULL_KEY,"");
        //springen um zu starten;
        llApplyImpulse(randvec(),FALSE);

    }

    changed(integer change)
    {
        if (change & (CHANGED_SCALE|CHANGED_SHAPE)){
            float mass = llGetMassMKS();
            factor = mass / densfact;

        }
    }

    collision_start(integer total_number)
    {
        Jolly();
    }

    land_collision_start(vector position)
    {
        Jolly();
    }
    touch_start(integer total_number)
    {
        Jolly();
    }

    //listener z.B. für llRegionSay in einem andern Prim, sollte das Teil doch mal abhauen wegen lag
    listen(integer channel, string name, key id, string message)
    {
        if (message == "die!"){
            llDie();
        }
    }
    //timer wegen lag: Wieder mal springen
    timer()
    {
        llApplyImpulse(<0,0,4>,FALSE);
    }

}

Da ist nun die Masse noch mit berücksichtigt.
 
mit dem Physicparameter Sandbox bleibt das Objekt in einem 10m Umkreis, praktisch für erste Experimente wo man noch mit den Impulswerten herumspielt

llSetStatus((STATUS_SANDBOX|STATUS_DIE_AT_EDGE|STATUS_PHYSICS), TRUE);
 

Users who are viewing this thread

Zurück
Oben Unten