Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Kolizje w grze RPG czyli jak opanować Elipsy

Ostatnio zmodyfikowano 2024-05-07 23:07
Autor Wiadomość
DejaVu
» 2024-05-07 22:24:58
To napisz sobie program testowy:
- narysuj elipsę na środku ekranu (obiekt1)
- narysuj drugą elipsę w miejscu w którym jest kursor (obiekt 2)
- rysuj prostokąt/cokolwiek innego, gdy elipsy się przecinają, abyś widział czy algorytm do wykrywania przecięć kolizji działa

Następnie przetestuj czy algorytm działa poprawnie (najedź na elipsę z lewej strony, potem z prawej, potem z góry, potem pod kątem itd). Jeżeli algorytm działa poprawnie, to będziesz wiedział, że możesz mu ufać i problem leży poza algorytmem kolizji.
P-181037
tBane
Temat założony przez niniejszego użytkownika
» 2024-05-07 22:30:05
hmm.. no dobra, tak zrobię. Jutro podzielę się kodem, który napiszę. Dzięki za odpowiedź
P-181038
DejaVu
» 2024-05-07 22:35:09
Zadanie dla ChatGPT 4:
To napisz sobie program testowy:
- narysuj elipsę na środku ekranu (obiekt1)
- narysuj drugą elipsę w miejscu w którym jest kursor (obiekt 2)
- rysuj prostokąt/cokolwiek innego, gdy elipsy się przecinają, abym widział czy algorytm do wykrywania przecięć kolizji działa

bool intersectionsTwoElipses( float x1, float y1, float rx1, float ry1, float x2, float y2, float rx2, float ry2 )
{
    // obliczamy kat elipsy wzgledem elipsy
    float len = sqrt( pow( x1 - x2, 2 ) + pow( y1 - y2, 2 ) );
    float angle = atan2( y2 - y1, x2 - x1 );
   
    // wyznaczamy punkt lezace na granicy jednej elipsy
    float px = x1 + rx1 * cos( angle );
    float py = y1 + ry1 * sin( angle );
   
    // sprawdzamy czy punkt znajduje sie wewnatrz drugiej elipsy
    if( pow(( px - x2 ) / rx2, 2 ) + pow(( py - y2 ) / ry2, 2 ) <= 1 )
         return true;
    else
         return false;
   
}

Użyj tego algorytmu bo chcę sprawdzić czy jest on poprawny. Potrzebuję kod C++ w SFML

Odpowiedź:
Rozumiem, że chcesz stworzyć program w C++ korzystający z biblioteki SFML, aby zwizualizować wykrywanie kolizji pomiędzy dwoma elipsami. Skorzystajmy z dostarczonego algorytmu i zaimplementujmy to w SFML.

Kod poniżej:

```cpp
#include <SFML/Graphics.hpp>
#include <cmath>

// Funkcja do wykrywania przecięć dwóch elips
bool intersectionsTwoElipses(float x1, float y1, float rx1, float ry1, float x2, float y2, float rx2, float ry2) {
    float len = std::sqrt(std::pow(x1 - x2, 2) + std::pow(y1 - y2, 2));
    float angle = std::atan2(y2 - y1, x2 - x1);

    float px = x1 + rx1 * std::cos(angle);
    float py = y1 + ry1 * std::sin(angle);

    return std::pow((px - x2) / rx2, 2) + std::pow((py - y2) / ry2, 2) <= 1;
}

int main() {
    const int windowWidth = 800;
    const int windowHeight = 600;

    // Inicjalizacja okna SFML
    sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight), "Collision Detection");

    // Pierwsza elipsa (środek ekranu)
    sf::CircleShape ellipse1;
    ellipse1.setRadius(50);
    ellipse1.setScale(2.0f, 1.0f);
    ellipse1.setPosition(windowWidth / 2 - 100, windowHeight / 2 - 50);
    ellipse1.setFillColor(sf::Color::Blue);

    // Druga elipsa (dynamiczna)
    sf::CircleShape ellipse2;
    ellipse2.setRadius(50);
    ellipse2.setScale(1.5f, 0.75f);
    ellipse2.setFillColor(sf::Color::Green);

    // Prostokąt (kolizja)
    sf::RectangleShape collisionIndicator;
    collisionIndicator.setSize(sf::Vector2f(100, 100));
    collisionIndicator.setFillColor(sf::Color::Red);
    collisionIndicator.setPosition(20, 20);

    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                window.close();
            }
        }

        // Aktualizacja pozycji drugiej elipsy na podstawie pozycji kursora
        sf::Vector2i mousePos = sf::Mouse::getPosition(window);
        ellipse2.setPosition(mousePos.x - 75, mousePos.y - 37.5f);

        // Wykrywanie kolizji między dwoma elipsami
        bool collision = intersectionsTwoElipses(
            ellipse1.getPosition().x + 100, ellipse1.getPosition().y + 50, 100, 50,
            ellipse2.getPosition().x + 75, ellipse2.getPosition().y + 37.5f, 75, 37.5f);

        // Wyświetlanie wskaźnika kolizji
        collisionIndicator.setPosition(20, 20);
        if (collision) {
            collisionIndicator.setFillColor(sf::Color::Red);
        } else {
            collisionIndicator.setFillColor(sf::Color::Transparent);
        }

        window.clear();
        window.draw(ellipse1);
        window.draw(ellipse2);
        window.draw(collisionIndicator);
        window.display();
    }

    return 0;
}
```

**Instrukcje:**

1. Upewnij się, że masz zainstalowaną bibliotekę SFML.
2. Skopiuj ten kod do pliku `main.cpp`.
3. Skonfiguruj środowisko (np. w Visual Studio) do używania biblioteki SFML.
4. Skopiuj odpowiednie pliki SFML (dll) do katalogu z wyjściowym plikiem binarnym.
5. Uruchom program, aby zobaczyć, jak elipsy oddziałują na siebie według dostarczonego algorytmu.

Wskaźnik kolizji będzie zmieniał kolor na czerwony, gdy elipsy się przecinają.

Przetestowałem kod (ctrl+c/ctrl+v) i... działa. Widać, że kolizje nie są dokładne i elipsy pomimo, że nachodzą na siebie pod kątem to nie wykrywa kolizji.

Tak więc jak widzisz w kilkanaście sekund uzyskałem kod testowy, który zapewne byś pisał godzinę.
P-181039
tBane
Temat założony przez niniejszego użytkownika
» 2024-05-07 22:44:04
no to kurde mam problem :-/ bo nie wiem jak generować kolizje elips, na których opiera się cała moja gra :-/
P-181040
DejaVu
» 2024-05-07 22:46:00
Sprawdź sobie te elipsy - może poziom dokładności/przybliżenie jest wystarczające.
P-181041
tBane
Temat założony przez niniejszego użytkownika
» 2024-05-07 23:07:19
dobra mam kod na przecięcie się dwóch elips. Teraz potworki ładnie podążają za graczem w polu widzenia:

C/C++
# define M_PI 3.14159265358979323846

bool pointInEllipse( float px, float py, float cx, float cy, float rx, float ry ) {
   
// Sprawdza, czy punkt (px, py) znajduje się wewnątrz elipsy o środku (cx, cy) i półosiach rx, ry
   
return( std::pow( px - cx, 2 ) / std::pow( rx, 2 ) ) +( std::pow( py - cy, 2 ) / std::pow( ry, 2 ) ) <= 1;
}

bool intersectionsTwoEllipses( float x1, float y1, float rx1, float ry1, float x2, float y2, float rx2, float ry2 ) {
   
const int numPoints = 100;
   
   
// Sprawdzenie punktów na pierwszej elipsie względem drugiej elipsy
   
for( int i = 0; i < numPoints; ++i ) {
       
float angle = 2 * M_PI * i / numPoints;
       
float px = x1 + rx1 * std::cos( angle );
       
float py = y1 + ry1 * std::sin( angle );
       
       
if( pointInEllipse( px, py, x2, y2, rx2, ry2 ) ) {
           
return true;
       
}
    }
   
   
// Sprawdzenie punktów na drugiej elipsie względem pierwszej elipsy
   
for( int i = 0; i < numPoints; ++i ) {
       
float angle = 2 * M_PI * i / numPoints;
       
float px = x2 + rx2 * std::cos( angle );
       
float py = y2 + ry2 * std::sin( angle );
       
       
if( pointInEllipse( px, py, x1, y1, rx1, ry1 ) ) {
           
return true;
       
}
    }
   
   
// Brak przecięcia
   
return false;
}
P-181042
1 « 2 »
Poprzednia strona Strona 2 z 2