Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

13.07.2011, 16:16

2D Abstand ohne sqrt()

Hallo, ich möchte in meinem Spiel ein Sprite an eine zufällige Position setzten. Allerdings soll diese Position 100px entfernt von der "Hauptperson" sein. Ich würde aber ungern sqrt() verwenden, weil die Funktion ja sehr Performance aufwendig ist. Also hab ich mir überlegt, dass ich einfach prüfe ob die Differenz der Random- und Hauptpersonwerte größer als 71 ist (auf beiden Achsen). Wenn sie größer als 71 (oder genauer 70.71067) sind, dann ist das Sprite ja 100px weg.
Hier ist der Code den ich verwende. Er funktioniert allerdings nicht. Kann mir jemand sagen wieso? Hab ich einen Fehler im Code gemacht oder ist es logischen Denkfehler?
Vielen Dank



C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define ABS(a)              (((a) < 0) ? -(a) : (a))                    // absolute value

void RandomCoordinats(sf::Sprite &sprite)
{
    int maxwidth = App.GetWidth() - sprite.GetSize().x;
    int maxheight = App.GetHeight() - sprite.GetSize().y;

    int ixValue = 0;
    int iyValue = 0;

    do
    {
        ixValue = rand() % maxwidth + 1;
        iyValue = rand() % maxheight + 1;
    }while(ABS(m_pHero->GetPosition().x - ixValue) > 71 && ABS(m_pHero->GetPosition().y - iyValue) > 71);

    sprite.SetPosition(ixValue, iyValue);
}


EDIT: Noch eine Frage: wäre es schlau einen Counter einzubauen, der nach dem 5 Schleifendurchlauf oder so abbricht? Weil theoretisch könnte man ja in einer Endlosschleife landen... Oder ist die Wahrscheinlichkeit viel zu gering?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

13.07.2011, 16:17

Warum prüfst du nicht einfach auf das Quadrat von 100, also 10000 ? Das ist korrekt und sicher besser als deine Idee.
Übrigens ist dieses WHILE da eine ganz schlechte Idee. Unvorhersagbares Laufzeitverhalten, davon rate ich ganz stark ab.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

3

13.07.2011, 16:27

Meinst du etwa so:

C-/C++-Quelltext

1
2
3
4
5
6
7
...
    do
    {
        ixValue = m_pHero->GetPosition().x - (rand() % maxwidth + 1);
        iyValue = m_pHero->GetPosition().y - (rand() % maxheight + 1);
    }while(ixValue * ixValue + iyValue * iyValue < 10000);
...


Ja das mit dem while meinte ich ja oben in meinem Edit. Was würdest du mir den empfehlen?

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

4

13.07.2011, 16:34

Hat er grad geschrieben. Rechne einfach im Quadratischen Raum. Wenn du den Abstand überprüfen willst machst du ja:
sqrt(x*x + y*y)==100pixel
jetzt machst du einfach:
x*x + y*y == 100 * 100 pixel
und 100 * 100 ist 10000
also x*x + y*y == 10000
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

5

13.07.2011, 16:42

Ja das hab ich ja verstanden... und ich habs ja in meinem vorherigen Post auch umgesetzt. Ich seh nur gerade, dass ich einen Fehler gemacht habe... ich brauch den Wert ja noch. Also folgendes sollte funktionieren:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void RandomCoordinats(sf::Sprite &sprite)
{
    int maxwidth = App.GetWidth() - sprite.GetSize().x;
    int maxheight = App.GetHeight() - sprite.GetSize().y;

    int ixValue = 0;
    int iyValue = 0;
    int ixDiff = 0;
    int iyDiff = 0;

    do
    {
        ixValue = rand() % maxwidth + 1;
        iyValue = rand() % maxheight + 1;
        ixDiff = m_pHero->GetPosition().x - ixValue;
        iyDiff = m_pHero->GetPosition().y - iyValue;
    }while(ixDiff * ixDiff + iyDiff * iyDiff < 10000);

    sprite.SetPosition(ixValue, iyValue);
}


Die Frage die ich jetzt hab ist, wie ich die While schleife loswerde, weil es ja theoretisch seinen koennte, dass ich in einer Endlosschleife lande, oder das die Funktion lange zum beenden braucht. Das meine BlueCobolt mit Unvorhersagbares Laufzeitverhalten.

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

6

13.07.2011, 16:52

Mach es doch ganz anders.
Du willst es ja an einer zufälligen Position auf dem Kreis mit Radius 100 finden. Dann machst du einfach z.B zufällig die X-Koordinate und dann berechnest du aufgrund dieser die auf dem Kreis liegende Y-Koordinate. Das ist Mitteschulmathe und sollte auch schnell genug sein (würde ich mir aber noch keine Sorgen machen.. ein paar sqrt wären überhaupt kein Problem).

btw:
Dein ABS ist nicht gut. Schau mal z.B was passiert wenn du das hier machst:

C-/C++-Quelltext

1
ABS(i++)

Wenn überhaupt benutz lieber eine Funktion dazu.

7

13.07.2011, 16:58

Tut mir Leid ich hab mich falsch ausgedrückt... Das Sprite soll mindestens 100px entfernt sein. Also nicht im Radius von 100px...

Oh das mit dem ABS ist mir gar nicht aufgefallen... Ich brauchs zwar jetzt nicht mehr (ich hab ABS nur an dieser Stelle benutzt) aber nächstes Mal dann als Funktion :D

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

8

13.07.2011, 17:01

Naja. Das kannst du dann aber auch so ähnlich machen. Anstatt dann die genaue Y-Koordinate zu nehmen, die du berechnet hast nimmst du das einfach als Obergrenze für die Zufallszahl (also als Wert für das Modulo).

9

13.07.2011, 17:07

Ich versteh nicht so genau was du meinst, könntest du das nochmal erklären?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

10

13.07.2011, 17:09

Ich würde einen zufälligen Radius erzeugen, einen zufälligen Winkel und damit dann den Punkt berechnen. Die einmaligen Sin und Cos bekommst Du "gratis", da Du ja kein WHILE mehr hast. Diese wegzuoptimieren wäre absoluter Quatsch.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Werbeanzeige