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

Kolizja w SFML

Object Storage Arubacloud
0 głosów
634 wizyt
pytanie zadane 5 sierpnia 2017 w C i C++ przez Programeł Gaduła (3,500 p.)

Witam

Mam problem z kolizją. Chce aby po dotknięciu graczem o obiekt lub w niego wejście pojawił się napis w konsoli "Kolizja!".

 klasa Object:

class Object
{
public:
    float width;
    float height;
    bool kolizja;    

    sf::Vector2f position;
    sf::RectangleShape shape;


    Object(float w, float h, float x, float y) : width(w), height(h), position(x,y), shape(sf::Vector2f(w,h)) {}
    
    bool isColision(Object object);
    void Colision();
};

int main:

int main()
{
    sf::RenderWindow window(sf::VideoMode(800,600),"SFML Kolizja");
    
    Object gracz = Object(60,130,100,460);
    gracz.shape.setFillColor(sf::Color::Green);
    gracz.shape.setPosition(gracz.position);

    Object obiekt = Object(90,300,500,300);
    obiekt.shape.setFillColor(sf::Color::White);
    obiekt.shape.setPosition(obiekt.position);

    while(window.isOpen())
    {
        sf::Event event;
        while(window.pollEvent(event))
        {
            if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) window.close();     
  
            if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::D) gracz.shape.move(10.f,0);

            if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::A) gracz.shape.move(-10.f,0);              
            
            if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::W) gracz.shape.move(0.f,-10.f);

            if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::S) gracz.shape.move(0.f,10.f);
        }
                  
        window.clear();

        window.draw(obiekt.shape);
        window.draw(gracz.shape);

        gracz.isColision(obiekt);
        gracz.Colision();

        window.display();
     }

    return 0;
}

metody klasy Object :

bool Object::isColision(Object object)
{
    if(position.x > object.position.x + object.width || position.x + width < object.position.x ||
        position.y > object.position.y + object.height || position.y + height < object.position.y)
            return kolizja=false ;
    else return kolizja=true;
}

void Object::Colision()
{
    if(kolizja == true) std::cout<<"Kolizja!"<<std::endl;
    else {}
}

za każdą pomoc wielkie dzięki :]

1
komentarz 5 sierpnia 2017 przez niezalogowany
edycja 5 sierpnia 2017

Mam kilka takich uwag na później (skoro odpowiedź chyba padła):
1. Nie katuj się zbędną ilością kodu. Zamieniaj takie rzeczy:

sf::Event event;
while (window.pollEvent(event))
{
	if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) window.close();
	if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::D) gracz.shape.move(10.f, 0);
	if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::A) gracz.shape.move(-10.f, 0);
	if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::W) gracz.shape.move(0.f, -10.f);
	if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::S) gracz.shape.move(0.f, 10.f);
}

Na takie:

sf::Event event;
while (window.pollEvent(event))
{
	if (event.type == sf::Event::KeyPressed)
	{
		if(event.key.code == sf::Keyboard::Escape) window.close();
		if (event.key.code == sf::Keyboard::D) gracz.shape.move(10.f, 0);
		if (event.key.code == sf::Keyboard::A) gracz.shape.move(-10.f, 0);
		if (event.key.code == sf::Keyboard::W) gracz.shape.move(0.f, -10.f);
		if (event.key.code == sf::Keyboard::S) gracz.shape.move(0.f, 10.f);
	}
}

Ładnie i pięknie, a jak dodasz jeszcze 20 klawiszy to nadal będzie przejrzyście.

2. Obsługę ruchu rób za pomocą funkcji isKeyPressed:

sf::Event event;
while (window.pollEvent(event))
{
	if (event.type == sf::Event::KeyPressed)
	{
		if(event.key.code == sf::Keyboard::Escape) window.close();
	}
}
// Caly kod bys wiedzial zeby nie umieszczac w petli z eventami
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) gracz.shape.move(0.f, -10.f);
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) gracz.shape.move(0.f, 10.f);
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) gracz.shape.move(-10.f, 0);
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) gracz.shape.move(10.f, 0);

Dzięki temu prostokąt zaczyna się poruszać od razu i ruch jest ciągły.

3. Obsługa czasu jest ważna by gra którą zrobisz chodziła wszędzie z tą samą szybkością. Proponuję zrobić taki mały prosty zabieg na sam początek przygody z SFML: Przed petlą główną gry:

sf::Clock clock;
float dt = 0;

Wewnątrz niej:

float speed = 200; // druga zaleta - maksymalna predkosc bedzie w miare logiczna - px/s - zawsze i wszedzie (powiedzmy)
sf::Vector2f velocity;

if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) velocity.y -= speed;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) velocity.y += speed;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) velocity.x -= speed;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) velocity.x += speed;
dt = clock.restart().asSeconds(); // mierzenie czasu pomiedzy framesami
gracz.shape.move(velocity*dt); // zmiana polozenia predkosc razy czas sama fizyka
window.clear();
...
komentarz 5 sierpnia 2017 przez PoetaKodu Stary wyjadacz (10,990 p.)
Nie powinno się restartować zegara w każdej klatce bo traci się bardzo dużo precyzji. Zamiast tego powinno się zapisywać poprzedni czas i odejmować go od aktualnego czasu.
komentarz 5 sierpnia 2017 przez niezalogowany
Masz rację. Po prostu chciałem lekko zwrócić uwagę na tę kwestię i dałem najprostszy przykład.

1 odpowiedź

+1 głos
odpowiedź 5 sierpnia 2017 przez PoetaKodu Stary wyjadacz (10,990 p.)
    return kolizja=false ;
else return kolizja=true;

Tak to nie działa. Po co zwracasz jakąkolwiek wartość skoro

  1. nie używasz jej dalej;
  2. masz do tego zmienną, która powinna to przechować;
  3. nie rozumiesz jak to działa?

Usuń returny z "isColision". Poza tym "kolizja" po angielsku piszemy przez dwa L - "collision".

Bonus: przy każdym wywołaniu isColision kopiujesz obiekt, który sprawdzasz:

bool Object::isColision(Object object)

Przekazujesz go poprzez wartość, przez co musi on zostać dosłownie skopiowany do argumentu 'object' w tej funkcji. Jeśli object będzie przechowywało więcej danych lub gdy samych obiektów będzie więcej odczujesz znaczny spadek wydajności. Zamiast tego powinieneś takie obiekty przekazywać przez const refa - zapobiegniesz wtedy możliwości zmiany tego obiektu (bo po co - potrzebny jest on do sprawdzenia a nie modyfikacji) przy czym nie będziesz go kopiował, tylko przekażesz samą referencję:

bool Object::isColision(const Object &object)

 

komentarz 5 sierpnia 2017 przez Programeł Gaduła (3,500 p.)
Ok dzięki za Bonus ale dalej nie wiem co mam zrobić aby ta kolizja działała :/
komentarz 5 sierpnia 2017 przez PoetaKodu Stary wyjadacz (10,990 p.)
Przeczytaj zdanie, które napisałem przed słowem "Bonus".

Podobne pytania

0 głosów
0 odpowiedzi 159 wizyt
pytanie zadane 14 marca 2018 w C i C++ przez zpawlo00 Początkujący (310 p.)
0 głosów
2 odpowiedzi 356 wizyt
pytanie zadane 5 stycznia 2017 w C i C++ przez Szedou Nowicjusz (200 p.)
+6 głosów
7 odpowiedzi 808 wizyt

92,573 zapytań

141,423 odpowiedzi

319,645 komentarzy

61,959 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

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

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!

...