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

Kolizje sfml 2.X " Nie rozumiem jak to działa "

Ostatnio zmodyfikowano 2015-04-01 19:14
Autor Wiadomość
Crax
Temat założony przez niniejszego użytkownika
Kolizje sfml 2.X " Nie rozumiem jak to działa "
» 2015-03-30 17:30:08
Jestem na etapie tworzenie własnej gry ( typowej tibi ).
Mam problem z zrozumieniem jak działają kolizje, posiadam strzępki informacji zaczerpnięte z różnych stron ale brakuje mi dokładnego wytłumaczenia jak to działa.
Prosił bym o link, lub wytłumaczenie ( jak najprościej ).
Głownie chodzi mi o kolizje gracza z obiektem nie ruchomym i ruchomym.
Mapa kafelkowa, kafelka 32 x 32, wielkość okna 20 x 20.
P-129567
Brunon3
» 2015-03-30 17:34:23
Hm... Mam kod kolizji ze swojego silnika (nie mapa kafelkowa, ale to podobne). Możesz sobie przeanalizować. :)

C/C++
void App::Player_Collision( int x, int y, int w, int h ) {
    if( world.isScreenScroll ) {
        //RIGHT COLLISION ( object right wall, player left wall )
        if(( player.y <=(( y ) + h ) ) &&( player.y + player.h >=( y ) ) )
        {
            if(( player.x <=( x + w ) ) &&( player.x >= x + w / 2 ) ) {
                player.camera.x += 1 - world.speed;
            }
        }
        //LEFT COLLISION ( object left wall, player right wall )
        if(( player.y <=(( y ) + h ) ) &&( player.y + player.h >=( y ) ) )
        {
            if(( player.x + player.w ) >= x &&( player.x + player.w <= x + w / 2 ) ) {
                player.camera.x -= 1 - world.speed;
            }
        }
        //UP COLLISION ( object up wall, player down wall )
        if(( player.x <=( x + w ) &&( player.x + player.w >= x ) ) )
        {
            if((( player.y + player.h ) >= y ) &&( player.y + player.h <= y + h / 2 ) ) {
                player.y -= 1 - world.speed;
            }
        }
        //DOWN COLLISION ( object down wall, player up wall )
        if(( player.x <=( x + w ) ) &&( player.x + player.w >= x ) )
        {
            if( player.y <=( y + h ) && player.y >= y + h / 2 ) {
                player.y += 1 - world.speed;
            }
        }
    }
    else
    {
        //RIGHT COLLISION ( object right wall, player left wall )
        if(( player.y <=(( y ) + h ) ) &&( player.y + player.h >=( y ) ) )
        {
            if(( player.x <=( x + w ) ) &&( player.x >= x + w / 2 ) ) {
                player.x += 1 - world.speed;
            }
        }
        //LEFT COLLISION ( object left wall, player right wall )
        if(( player.y <=(( y ) + h ) ) &&( player.y + player.h >=( y ) ) )
        {
            if(( player.x + player.w ) >= x &&( player.x + player.w <= x + w / 2 ) ) {
                player.x -= 1 - world.speed;
            }
        }
        //UP COLLISION ( object up wall, player down wall )
        if(( player.x <=( x + w ) &&( player.x + player.w >= x ) ) )
        {
            if((( player.y + player.h ) >= y ) &&( player.y + player.h <= y + h / 2 ) ) {
                player.y -= 1 - world.speed;
            }
        }
        //DOWN COLLISION ( object down wall, player up wall )
        if(( player.x <=( x + w ) ) &&( player.x + player.w >= x ) )
        {
            if( player.y <=( y + h ) && player.y >= y + h / 2 ) {
                player.y += 1 - world.speed;
            }
        }
    }
}

Legenda:

App - moja autorska biblioteka; rozszerzenie Allegro 4; Allegro Plus Plus (Allegro++),

world.isScreenScroll - czy jest aktywne przewijanie ekranu,

world.speed - anty-prędkość gry, odejmuję od niej wszystko co się porusza,

player.camera.x - pozycja kamery gracza; dla przewijania ekranu; odejmuję od niej wszystkie inne pozycje gdy jest aktywne przewijanie ekranu.

No więc sprawdzam pozycję, czy gracz z której strony nie zachodzi na obiekt; jeżeli tak: cofam go odpowiednio. ;)

--

Oj, to SFML. :D
Ale tam chyba jest podobnie (chyba, jeżeli nie to przepraszam).

-BD.
P-129568
Quirinnos
» 2015-03-30 18:43:33
Najprościej jak można. Jeśli któraś ze stron gracza, przecina się z którąś ze stron obiektu, to jest kolizja xD.
Kiedyś pisałem na blogu o prostym systemie kolizji w SFML, może Ci się przyda.
SFML - Kolizje
P-129570
Crax
Temat założony przez niniejszego użytkownika
» 2015-03-30 19:54:14
C/C++
#include <SFML/Graphics.hpp>

using namespace std;
using namespace sf;

int main()
{
   
    RenderWindow oknoAplikacji( VideoMode( 256, 256, 32 ), "xxx" );
   
    Texture water, water_grass, gras, spider, players;
    Sprite spr0, spr1, spr2R, spr2D, spr2L, spr2U, spr3, player;
   
    water.loadFromFile( "C:\\Users\\Maciek\\Documents\\Visual Studio 2010\\Projects\\sfml\\Debug\\graph\\water.png" );
    spr0.setTexture( water );
   
    gras.loadFromFile( "C:\\Users\\Maciek\\Documents\\Visual Studio 2010\\Projects\\sfml\\Debug\\graph\\gras.png" );
    spr1.setTexture( gras );
   
    water_grass.loadFromFile( "C:\\Users\\Maciek\\Documents\\Visual Studio 2010\\Projects\\sfml\\Debug\\graph\\water_grassU.png" );
    spr2U.setTexture( water_grass );
   
    spr2R.setTexture( water_grass );
    spr2R.setOrigin( 32, 0 );
    spr2R.setRotation( 270 );
   
    spr2D.setTexture( water_grass );
    spr2D.setOrigin( 32, 32 );
    spr2D.setRotation( 180 );
   
    spr2L.setTexture( water_grass );
    spr2L.setOrigin( 0, 32 );
    spr2L.setRotation( 90 );
   
    spider.loadFromFile( "C:\\Users\\Maciek\\Documents\\Visual Studio 2010\\Projects\\sfml\\Debug\\graph\\xxx.png" );
    spr3.setTexture( spider );
    spr3.setOrigin( 16, 16 );
   
    players.loadFromFile( "C:\\Users\\Maciek\\Documents\\Visual Studio 2010\\Projects\\sfml\\Debug\\graph\\players.png" );
    player.setTexture( players );
    player.setOrigin( 16, 16 );
    player.setPosition( 80, 80 );
   
    int mapa[ 8 ][ 8 ] =
    {
        { 0, 1, 1, 1, 1, 1, 1, 0 },
        { 2, 5, 5, 5, 5, 5, 5, 4 },
        { 2, 5, 5, 5, 5, 5, 5, 4 },
        { 2, 5, 5, 5, 5, 5, 5, 4 },
        { 2, 5, 5, 5, 5, 5, 5, 4 },
        { 2, 5, 5, 5, 5, 5, 5, 4 },
        { 2, 5, 5, 5, 5, 5, 5, 4 },
        { 0, 3, 3, 3, 3, 3, 3, 0 }
    };
   
    while( oknoAplikacji.isOpen() )
    {
       
        Event zdarzenie;
        while( oknoAplikacji.pollEvent( zdarzenie ) )
        {
            if( zdarzenie.type == Event::Closed )
            {
                oknoAplikacji.close();
            }
           
            if( zdarzenie.type == Event::KeyPressed && zdarzenie.key.code == Keyboard::Escape )
            {
                oknoAplikacji.close();
            }
           
            if( zdarzenie.type == Event::KeyPressed && zdarzenie.key.code == Keyboard::Up )
            {
                player.move( 0, - 32 );
                player.setRotation( 360 );
            }
           
            if( zdarzenie.type == Event::KeyPressed && zdarzenie.key.code == Keyboard::Down )
            {
                player.move( 0, 32 );
                player.setRotation( 180 );
            }
           
            if( zdarzenie.type == Event::KeyPressed && zdarzenie.key.code == Keyboard::Left )
            {
                player.move( - 32, 0 );
                player.setRotation( 270 );
            }
           
            if( zdarzenie.type == Event::KeyPressed && zdarzenie.key.code == Keyboard::Right )
            {
                player.move( 32, 0 );
                player.setRotation( 90 );
            }
        }
       
        oknoAplikacji.clear( Color::Black );
       
        for( int i = 0; i < 8; i++ )
        {
            for( int j = 0; j < 8; j++ )
            {
                if( mapa[ j ][ i ] == 0 )
                {
                    spr0.setPosition( i * 32, j * 32 );
                    oknoAplikacji.draw( spr0 );
                }
               
                if( mapa[ j ][ i ] == 1 )
                {
                    spr2U.setPosition( i * 32, j * 32 );
                    oknoAplikacji.draw( spr2U );
                }
               
                if( mapa[ j ][ i ] == 2 )
                {
                    spr2R.setPosition( i * 32, j * 32 );
                    oknoAplikacji.draw( spr2R );
                }
                if( mapa[ j ][ i ] == 3 )
                {
                    spr2D.setPosition( i * 32, j * 32 );
                    oknoAplikacji.draw( spr2D );
                }
                if( mapa[ j ][ i ] == 4 )
                {
                    spr2L.setPosition( i * 32, j * 32 );
                    oknoAplikacji.draw( spr2L );
                }
                if( mapa[ j ][ i ] == 5 )
                {
                    spr1.setPosition( i * 32, j * 32 );
                    oknoAplikacji.draw( spr1 );
                }
            }
        }
       
        oknoAplikacji.draw( spr3 );
        spr3.setPosition( 48, 48 );
       
        oknoAplikacji.draw( player );
       
        oknoAplikacji.display();
    }
   
    return 0;
   
}



Możecie zaproponować jakieś rozwiązanie?
P-129587
RazzorFlame
» 2015-03-31 11:47:12
Jeżeli zamierzasz ograniczyć poruszanie się do takiego jak jest w Tibii, to nawet nie ma sensu pisać kolizji. Wystarczy, że sprawdzisz czy kafelek, na który chcesz wejść nie jest przypadkiem przeszkodą.
P-129612
Quirinnos
» 2015-03-31 12:00:32
Dokładnie, to co kolega wyżej napisał.
Nie przesuwasz gracza od razu, tylko zapisujesz gdzieś, gdzie on chciałby się poruszyć. Potem sprawdzasz, czy miejsce na które chcę się przemieści jest dozwolone. Jeśli jest, poruszasz. Jeśli nie - nie ;)
P-129615
Brunon3
» 2015-03-31 14:08:08
Tak, ale takie rozwiązanie jak podano wyżej jest bardzo nie uniwersalne i IMHO lepiej jest się nauczyć takich kolizji jak ja podałem. ;)

-BD.
P-129621
RazzorFlame
» 2015-03-31 15:19:32
Głupotą jest pisać w ten sposób wykrywanie kolizji. Prawdziwy silnik fizyczny powinien posiadać takie 3 zaimplementowane kroki:
1. Collision Detection
2. Collision Collision analyzer
3. Collision responser

Poza tym po co pisać silnik fizyczny do czegoś co nie będzie go używało. Możesz i tak przecież użyć jakiegoś gotowego silnika fizycznego. Na obliczanie tracisz czas i wydajność.
P-129627
« 1 » 2 3 4
  Strona 1 z 4 Następna strona