Eine Positionsabfrage in OGRE



  • Hallo ihr Lieben!

    Ich habe da ein kleines Problem. Ich bin derweil beschäftigt, in einem Spiel-Engine Fässer zu generieren, die jeweils bei Neuladen des Spiels zufällig verteilt werden sollen. Ich muss gestehen, dass ich mich mit dem Random-Mechanismus bisher so gut wie nicht auskannte (wenn da Fehler auffallen, würde ich auch da bitten, mich darauf aufmerksam zu machen :))

    Mein Problem ist: die Fässer überlappen sich teilweise, und das sollen sie nicht. Wie sollte so eine Positionsabfrage in meinem bisherigen Code aussehen? Hier mein bisheriger Code:

    srand( GetTickCount());
                float x,z;
                Entity* randomFass;
                SceneNode* randomNode;
                std::stringstream ss;
    
                for (int i = 0; i<10;i++)
                {
                    ss << i;
                    x = rand()%10000/10000.0f*(100+30) - 20;
                    z = rand()%10000/10000.0f*(100-10) - 20;
    
                    randomFass = mSceneMgr->createEntity(String("Fass")+ss.str(), "Fass04.mesh");
                    randomFass->setMaterialName("Material#14");
                    randomNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(String("FassNode")+ss.str());
    
                    randomNode->attachObject(randomFass);
                    randomFass->setMaterialName("Material#14");
                    randomNode->setPosition (x,0,z);
                }
    

    Schon einmal vielen Dank für Tipps und Antworten!

    Eure Sill 🙂



  • srand() nur einmal aufrufen 🙂

    x = rand()%10000/10000.0f*(100+30) - 20; // [0 - 0.9999] * 130 -20 ~~ -20...110
    z = rand()%10000/10000.0f*(100-10) - 20; // [0 - 0.9999] * 90  -20 ~~ -20...70
    randomNode->setPosition (x,0,z);
    

    Deine Fässer haben einen Durchmesser ... den solltest du vielleicht in deinem Placement berücksichtigen.
    Sei der Durchmesser 1 dann liegt
    Fass 1 mit ( (rand()%10000/10000.0f) == 0.0000) bei (-20.000,0,-20.000)
    Fass n mit ( (rand()%10000/10000.0f) == 0.0001) bei (-19.987,0,−19.991)

    Voila: Überlappung.

    Lösung 1: Raster dein Spielfeld mit der Breite der Fässer und lass nur 1 Fass pro Zelle zu.
    Lösung 2: Bemüh OGRE und teste ob die Boundingbox des neuen Fasses irgendeine bereits bestehende Boundingbox in der Scene schneidet, wenn ja mach ein neues Fass auf 😃



  • Also ich hab jetzt einen neuen Code. Das Überlappungs-Problem ist Geschichte.

    const int cols=3;                                    // Spalten
        const int rows=4;                                    // Reihen
        const float barrel_width = 10;                       // Breite des Fassmodells
        const Ogre::Vector3 start = Ogre::Vector3(0,0,0);    // Position des ersten Fasses
    
        srand ( time(NULL) );
        int col,row = -1;
        int barrel_num = 1;
        float x,z = -1;
        Ogre::Vector3 barrel_pos = Ogre::Vector3(0,0,0);
        //Ogre::Entity* ent;
        Ogre::SceneNode* node;
        Ogre::String barrel_name;
    
        for (int i = 0; i <cols*rows; i++)
        {
            // 50% ja/nein Zufall
            if ((rand() % 2)==1)
            {
                barrel_name = "Fass" + Ogre::StringConverter::toString(barrel_num);
                // Reihe+Spalte berechnen
                col = i%cols;
                row = i/cols;
    
                // x/z Koordinate berechnen
                x = col * barrel_width;
                z = row * barrel_width;
    
                barrel_pos = Ogre::Vector3(x,0,z) + start;
    
                // Fass-Entity erstellen
                ent = mSceneMgr->createEntity(barrel_name, "Fass01.mesh");
                node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
                node->attachObject(ent);
                //Fass Node positionieren
                node->setPosition(barrel_pos);
                // zufällige Drehung
                node->yaw(Ogre::Degree((rand() % 360)));
                barrel_num++;
            };
        }
    

    Das Dumme ist nur, dass die Fässer ne zufällige Anzahl haben. Ich möchte ihnen aber gerne eine feste geben. 😕



  • Du kannst einen Zähler mitlaufen lassen und so eine Maximalanzahl einstellen. Wichtig ist nur, dass diese Maximalanzahl auch mit der Chance zusammenstimmt (in deinem Fall derzeit 50%). Ist sie zu klein gewählt, werden Fässer immer nur im oberen/linken Bereich stehen.

    Eine Minimalanzahl wirst du nicht hinbekommen da du mit Zufallswerten die Chance bestimmst und im schlimmsten Fall geht das 50%-Chance-Experiment eben immer falsch und du hast kein einziges Fass.

    MfG SideWinder



  • BTW: Wenn die Anzahl fix sein soll würde ich einen anderen Algorithmus empfehlen. Du suchst n Mal eine Position aus, ist sie noch nicht besetzt, besetzt du sie, ansonsten suchst du eine neue Position. Das geht natürlich nur falls n << N ist. Wobei N die Anzahl der Felder insgesamt ist.

    MfG SideWinder


Anmelden zum Antworten