• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

SFML słaba detekcja kolizji

VPS Starter Arubacloud
0 głosów
434 wizyt
pytanie zadane 1 września 2019 w C i C++ przez inczyk Początkujący (410 p.)
edycja 1 września 2019 przez inczyk

Witam. Od niedawna uczę się biblioteki SFML w C++ i próbuję napisać prostą grę. Detekcja kolizji 'postaci' i platformy działa prawie dobrze. Mianowicie gdy prawym-dolnym krańcem 'postaci' uderzy się lewy-górny kraniec platformy (i analogiczne po drugiej stronie) 'postać' się zacina w miejscu. Oto kod:

#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <windows.h>
#include <iostream>
int predkosc_skoku = 2;
bool wPowietrzu = false;
bool skok = false;
bool wcisnietySkok = false;
bool wPrawo = false;
bool wLewo = false;
bool spadanie = false;
int predkosc = 0;
sf::Vector2f pozycja_postac;
sf::Vector2f pozycja_platforma;
sf::Vector2f rozmiar_platforma;
sf::Vector2f rozmiar_postac;
int main()
{
    sf::RenderWindow oknoAplikacji;
    oknoAplikacji.create(sf::VideoMode(1000, 880, 32), "Kurs SFML"); //tworzenie sceny 800x600 32 bit kolor

    sf::RectangleShape postac(sf::Vector2f(100, 100));//postac
    postac.setPosition(350, 5);
    postac.setFillColor(sf::Color(255, 255, 255, 255));


    sf::RectangleShape platforma(sf::Vector2f(700, 85));//platforma
    platforma.setPosition(150, 515);
    platforma.setFillColor(sf::Color(139, 69, 19));
    platforma.setOutlineColor(sf::Color(0, 150, 20));
    platforma.setOutlineThickness(5);

    while (oknoAplikacji.isOpen())
    {    //program wykonujący się ciągle
        oknoAplikacji.clear(sf::Color());           //wyczyszczenie ekranu

        std::cout << pozycja_postac.y + rozmiar_postac.y << " oraz " << pozycja_platforma.y - 5 << " oraz ";
        std::cout << pozycja_postac.y + rozmiar_postac.y - pozycja_platforma.y - 5 << " oraz " << skok << " oraz " << predkosc_skoku << std::endl;//wypisanie waznych danych do konsoli

        pozycja_postac = postac.getPosition();
        pozycja_platforma = platforma.getPosition();
        rozmiar_postac = postac.getSize();
        rozmiar_platforma = platforma.getSize();

        /*if (pozycja_postac.y + rozmiar_postac.x < pozycja_platforma.y-5)
        {
            spadanie = true;
        }
        else
            spadanie = false;*/
        spadanie = true;

        if (pozycja_postac.y + rozmiar_postac.y >= pozycja_platforma.y - 5 && pozycja_postac.y<pozycja_platforma.y+rozmiar_platforma.y+10/* <--- pion*/&&
        pozycja_postac.x+rozmiar_postac.x>=pozycja_platforma.x&&pozycja_postac.x<=pozycja_platforma.x+rozmiar_platforma.x)
        {//detekcja kolizji w pionie
            spadanie = false;
        }



         
        if (skok==false&&pozycja_postac.y + rozmiar_postac.y - pozycja_platforma.y - 5 > -10 && pozycja_postac.y + rozmiar_postac.y - pozycja_platforma.y - 5 < 0
            && pozycja_postac.x + rozmiar_postac.x >= pozycja_platforma.x&&pozycja_postac.x <= pozycja_platforma.x + rozmiar_platforma.x + 10)//wyrownanie
        {
            postac.setPosition(pozycja_postac.x, pozycja_platforma.y-rozmiar_postac.y-5);
        }

        if (skok == true)//skok
        {
            wPowietrzu = true;
            postac.move(0, -predkosc_skoku);
            predkosc_skoku-=1;
            if (predkosc_skoku == 2)
            {
                spadanie = true;
                skok = false;
            }
        }

        if (spadanie==true)//spadanie
        {
            wPowietrzu = true;
            postac.move(0, -predkosc_skoku);
            if(predkosc_skoku>-20)
            predkosc_skoku-=1;
            
        }
        else if(skok==false)//koniec spadania
        {
            wPowietrzu = false;
            predkosc_skoku = 2;
        }

        /*if (skok)                            //skok o x kratek (spada rowniez o x kratek)
        {
            wPowietrzu = true;
            postac.move(0, -predkosc_skoku);
            predkosc_skoku--;

            if (predkosc_skoku == -21)
            {
                wPowietrzu = false;
                predkosc_skoku = 20;
                skok = false;
            }
        }*/





        if (wPrawo)//ustalenie kierunku chodzenia
            predkosc = 8;
        else if (!wLewo)
            predkosc = 0;

        if (wLewo)
            predkosc = -8;
        else if (!wPrawo)
            predkosc = 0;

        //detekcja kolizji w poziomie
        if (pozycja_postac.x + rozmiar_postac.x >= pozycja_platforma.x - 10 && pozycja_postac.x + rozmiar_postac.x<pozycja_platforma.x + rozmiar_postac.x && pozycja_postac.y + rozmiar_postac.y > pozycja_platforma.y && pozycja_postac.y < pozycja_platforma.y + rozmiar_platforma.y /*lewo*/ ||
            pozycja_postac.x <= pozycja_platforma.x + rozmiar_platforma.x + 10 && pozycja_postac.x>rozmiar_postac.x+rozmiar_postac.x && pozycja_postac.y + rozmiar_postac.y > pozycja_platforma.y && pozycja_postac.y < pozycja_platforma.y + rozmiar_platforma.y /*prawo*/)
        {

            std::cout << "stop...";
            predkosc = 0;

        }


        if (predkosc != 0)//przmieszczanie 'bohatera'
        {
            postac.move(predkosc, 0);
        }



        sf::Event zdarzenie;
        while (oknoAplikacji.pollEvent(zdarzenie))
        {//obsługa zdarzeń

            if (zdarzenie.type == sf::Event::KeyPressed&&zdarzenie.key.code == sf::Keyboard::Enter)
            {
                postac.setPosition(350, 5);
                predkosc_skoku = 0;
            }

            if (zdarzenie.type == sf::Event::KeyPressed && zdarzenie.key.code == sf::Keyboard::W && !wPowietrzu && !wcisnietySkok)//przycisk skoku
            {
                predkosc_skoku = 20;
                skok = true;
                wcisnietySkok = true;

            }else if (zdarzenie.type == sf::Event::KeyReleased && zdarzenie.key.code == sf::Keyboard::W)
            {
                
                wcisnietySkok = false;

            }
            
            if (zdarzenie.type == sf::Event::KeyPressed && zdarzenie.key.code == sf::Keyboard::D)//przycisk w prawo
            {
                wPrawo = true;
            }
            else if (zdarzenie.type == sf::Event::KeyReleased && zdarzenie.key.code == sf::Keyboard::D)
            {
                wPrawo = false;

            }
            
            if (zdarzenie.type == sf::Event::KeyPressed && zdarzenie.key.code == sf::Keyboard::A)//przycisk w lewo
            {
                wLewo = true;
            }
            else if (zdarzenie.type == sf::Event::KeyReleased && zdarzenie.key.code == sf::Keyboard::A)
                {
                    wLewo = false;
                }

            if (zdarzenie.type == sf::Event::KeyPressed && zdarzenie.key.code == sf::Keyboard::Escape || zdarzenie.type == sf::Event::Closed)
            {
                //obsługa zdarzenia po wciśnięciu klawisza ESC albo po wciśnięciu przycisku wyjścia
                oknoAplikacji.close(); //np. zamknięcie aplikacji
            }

        }
        oknoAplikacji.draw(postac);
        oknoAplikacji.draw(platforma);

        oknoAplikacji.display();
        Sleep(20);
    }

    return 0;
}

A tutaj szwankująca detekcja kolizji (w całym kodzie jest ona podświetlona)

        //detekcja kolizji w poziomie
        if (pozycja_postac.x + rozmiar_postac.x >= pozycja_platforma.x - 10 && pozycja_postac.x + rozmiar_postac.x<pozycja_platforma.x + rozmiar_postac.x && pozycja_postac.y + rozmiar_postac.y > pozycja_platforma.y && pozycja_postac.y < pozycja_platforma.y + rozmiar_platforma.y /*lewo*/ ||
            pozycja_postac.x <= pozycja_platforma.x + rozmiar_platforma.x + 10 && pozycja_postac.x>rozmiar_postac.x+rozmiar_postac.x && pozycja_postac.y + rozmiar_postac.y > pozycja_platforma.y && pozycja_postac.y < pozycja_platforma.y + rozmiar_platforma.y /*prawo*/)
        {

            std::cout << "stop...";
            predkosc = 0;

        }

Próbowałem to naprawiać kilka dni, ale nie mam pomysłu, więc zwracam się z pomocą do was.

(nie bijcie za bardzo jeśli to wszystko jest napisane w najgorszy możliwy sposób :V)

komentarz 1 września 2019 przez Michał Gibas Pasjonat (19,630 p.)
Taka mała rada, proszę używać angielskich nazw zmiennych/funkcji/klas etc. NIGDY nie używaj w kodzie polskich nazw, to nieprofesjonalne i brzydkie ;v
1
komentarz 1 września 2019 przez tkz Nałogowiec (42,020 p.)
Problemem nie są polskie nazwy, a mieszanie ich  z angielskimi.
komentarz 1 września 2019 przez inczyk Początkujący (410 p.)
Poprawiłem już te błędy u siebie. Na przyszłość będę o tym pamiętał.

1 odpowiedź

+1 głos
odpowiedź 1 września 2019 przez Zayebisty Gaduła (3,200 p.)
no kod troche brzydki ale mniejsza... nw czy dobrze zrozumialem bo nie chcialo mi sie czytac calosci ale jak dla mnie zacina sie bo po wykryciu kolizji jest predkosc = 0;
komentarz 1 września 2019 przez inczyk Początkujący (410 p.)
predkosc=0; jest po to aby zatrzymac tego klocka :V Jeśli jest wciśnięty przycisk predkosc ustawia sie na 10 albo -10 (prawo lewo) a predkosc = 0 po prostu go zatrzymuje. ///edit  gdy predkosc=0 klocek dalej spada (jest na to inna zmienna)  /// Psuje się to dopiero gdy dziwnym sposobem wleci się klockiem w platformę. Wtedy zamiast wykryć kolizję od razu, klocek wchodzi w platformę (a nie powinien :V) i dopiero wtedy ustawia predkosc = 0;
komentarz 1 września 2019 przez tkz Nałogowiec (42,020 p.)
Skopiowałem kod, nic się nie zacina, nic się nie blokuje na krańcach.
komentarz 1 września 2019 przez inczyk Początkujący (410 p.)

Chodzi mi o to:

 

Teraz nie mogę się ruszyć w lewo, ani w prawo. Trzeba kliknąć Enter, aby zresetować program.

komentarz 1 września 2019 przez tkz Nałogowiec (42,020 p.)

Chyba masz inny kod niż wkleiłeś. 

komentarz 1 września 2019 przez inczyk Początkujący (410 p.)
Nie 'działa' to zawsze. Najczęściej robi się to gdy wyskoczysz z platformy i wlecisz bokiem, aby skończyć tak jak mój klocek

Podobne pytania

0 głosów
2 odpowiedzi 176 wizyt
pytanie zadane 4 marca 2017 w OpenGL, Unity przez Dominic Nowicjusz (160 p.)
0 głosów
1 odpowiedź 193 wizyt
0 głosów
2 odpowiedzi 395 wizyt

92,770 zapytań

141,695 odpowiedzi

320,518 komentarzy

62,107 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...