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