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

Heksowa mapa - sześciokąty. Jak się za to zabrać? [allegro]

Ostatnio zmodyfikowano 2013-09-03 03:23
Autor Wiadomość
Tymianek
Temat założony przez niniejszego użytkownika
Heksowa mapa - sześciokąty. Jak się za to zabrać? [allegro]
» 2013-02-17 15:43:57
Jak w temacie.
Kiedy znudzą nam się kwadraty i szukamy jakiegoś urozmaicenia, powstaje pomysł stworzenia mapy złożonej z sześciokątów.
Takie rozwiązanie jest bardzo dobre do pisania różnych gier strategicznych. Ale nie jest to na pewno najprostszy sposób na zbudowanie dwuwymiarowej przestrzeni gry.
O ile nie mam problemu z tablicami, wyświetleniem zróżnicowanych terenów, to nie wiem jak sprawdzić nad którym heksem aktualnie znajduje się kursor.
więc,
Jak sprawdzić nad którym heksem aktualnie znajduje się kursor?
P-76448
DejaVu
» 2013-02-17 17:25:44
Frazy, które należy wpisać w wyszukiwarkę google:
hm... gdzieś był wątek na forum...
Frazy, które należy wpisać w wyszukiwarkę google:
Poszukaj opisów dot. myszy w rzucie izometrycznym. Do mapy heksowej (czy jak ona się zwie) można ten sam trick wykorzystać.
P-76451
Mr.J
» 2013-09-03 03:23:27
Witam, patrzac po dacie zalozenia tematu moja odpowiedz moze byc troche nieaktualna.

Jakis czas temu zrobilem taka mapke w ramach nauki(miala jeszcze opcje sprawdzania z ktorej strony heksa jest myszka) i wygladalo to mniej wiecej tak:

(zakladam ze mowa o figurze foremnej)

siec takich figur to zbior trzech rodzajow lini; dwie ukosne i jedna rownolegla do jakiejs osi...(w najprostszym przypadku)

stworzylem wiec klase line, z ktorej obiektow z kolei zbudowana byla klasa triangle, z kolej z jej obiektow byla zbudowana klasa hexagon
W zaleznosci od ustawienia tych szesciokatow obliczenie lini moze sie troche roznic, np w moim przypadku odleglosc pomiedzy najwyzszym a najnizszym wierzcholkiem w hex'ie byla rowna 2a, gdzie a to oczywiscie bok trojkata rownobocznego dlatego tez linie skosne byly ustawione pod katem 30 badz 150 stopni do osi x. Zeby sprawdzic czy mysz znajduje sie nad danym hexagonem musisz sprawdzic czy znajduje sie nad ktoryms z jej trojkatow,
dla kazdego bedzie sie to odbywalo troche inaczej bo sa ustawione pod roznym katem, ale sprawa wyglada tak ze x musi byc raz albo wiekszy od hex_center_x - a*sqrt(3)/2 i mniejszy od hex_center_x albo wiekszy od
hex_center_x i mniejszy od hex_center_x + a*sqrt(3)/2, natomiast y musi byc mniejsze albo wieksze(zalezy od lini i samego trojkata) od Ax+B(ze wzoru na prosta y=ax+b) gdzie A to tg 30(badz 150 tu pamietamy ze uklad wspolrzednych jest odbity wzgledem osi x ;) ) stopni a B to 0(linia przecinajaca srodek hexagonu) albo +- a(dlugosc boku trojkata).

Podsumowujac, ten problem nalezy rozwiazac bardziej matematycznie niz informatycznie bo z tego co pamietam to jak juz wszystko obliczylem na kartce to calosc napisalem w godzinke
(+ druga na naprawe kilku bledow z wyswietlaniem ;/ )

Wstawiam tez wszystko w postaci kodu(mam nadzieje ze wstawi sie caly)

Pozdrawiam
Mr.J

C/C++
float count_y( float arg_a, int arg_x, int arg_b )
{
    float y = 0;
    y = arg_a * arg_x + arg_b;
   
    return y;
}
class Line
{
private:
    // te zmienne sa ustalane wzgledem srodka trojkata dalszej klasy
    float arg_a;
    int arg_b;
    //
public:
    Line() { };
    void set_arguments( float a, int b );
    float get_y( int x, int b_offset );
};
/////////////////////////////////////////////
void Line::set_arguments( float a, int b )
{
    arg_a = a;
    arg_b = b;
}
/////////////////////////////////////////////
float Line::get_y( int x, int b_offset )
{
    float y = arg_a * static_cast < float >( x ) + static_cast < float >( arg_b ) + static_cast < float >( b_offset );
    return y;
}
/////////////////////////////////////////////
// trojkat rownoboczny
class Equilateral
{
private:
    Line line1; // przy liczeniu kolizji z myszka polozenie mouseY ma byc wieksze od line1 i mniejsze od line2
    Line line2;
    float A_side;
    int height;
    //numer trojkata(jego rodzaj/to pod jakim jest katem)
    int Enumber;
public:
    Equilateral();
    void set_triangle( int number );
    bool check_range( int x_offset, int b );
    int get_Aside();
    int get_H();
};
//////////////////////////////////////////////
Equilateral::Equilateral()
{
    height = 40;
    A_side = 2 * height / sqrt( 3 );
    Enumber = 0;
}
//////////////////////////////////////////////
int Equilateral::get_Aside()
{
    int tempA = static_cast < int >( A_side );
    return tempA;
}
//////////////////////////////////////////////
int Equilateral::get_H()
{
    int tempH = static_cast < int >( height );
    return tempH;
}
//////////////////////////////////////////////
void Equilateral::set_triangle( int number )
{
    // trojkaty mozna sobie zwizualizowac nastepujaco:
   
   
    //          6 1
    //         5   2
    //          4 3
   
   
   
    Enumber = number;
    switch( number )
    {
    case 1:
        line1.set_arguments( sqrt( 3 ) / 3, - A_side );
        line2.set_arguments( - sqrt( 3 ) / 3, 0 );
        break;
    case 2:
        line1.set_arguments( - sqrt( 3 ) / 3, 0 );
        line2.set_arguments( sqrt( 3 ) / 3, 0 );
        break;
    case 3:
        line1.set_arguments( sqrt( 3 ) / 3, 0 );
        line2.set_arguments( - sqrt( 3 ) / 3, A_side );
        break;
    case 4:
        line1.set_arguments( - sqrt( 3 ) / 3, 0 );
        line2.set_arguments( sqrt( 3 ) / 3, A_side );
        break;
    case 5:
        line1.set_arguments( sqrt( 3 ) / 3, 0 );
        line2.set_arguments( - sqrt( 3 ) / 3, 0 );
        break;
    case 6:
        line1.set_arguments( - sqrt( 3 ) / 3, - A_side );
        line2.set_arguments( sqrt( 3 ) / 3, 0 );
        break;
        default:
        break;
    }
}
///////////////////////////////////////
bool Equilateral::check_range( int x_offset, int b ) // sprawdzanie czy myszka jest w zakresie danego trojkata
{
    int x = 0;
    int y = 0;
   
    SDL_GetMouseState( & x, & y );
   
    if( Enumber == 1 )
    {
        if( y >= line1.get_y( x - x_offset, b ) && y < line2.get_y( x - x_offset, b ) && x >= x_offset && x <= x_offset + height )
        {
            return true;
        }
    }
    if( Enumber == 2 )
    {
        if( y >= line1.get_y( x - x_offset, b ) && y < line2.get_y( x - x_offset, b ) && x >= x_offset && x <= x_offset + height )
        {
            return true;
        }
    }
    if( Enumber == 3 )
    {
        if( y >= line1.get_y( x - x_offset, b ) && y < line2.get_y( x - x_offset, b ) && x >= x_offset && x <= x_offset + height )
        {
            return true;
        }
    }
    if( Enumber == 4 )
    {
        if( y >= line1.get_y( x - x_offset, b ) && y < line2.get_y( x - x_offset, b ) && x > x_offset - height && x < x_offset )
        {
            return true;
        }
    }
    if( Enumber == 5 )
    {
        if( y >= line1.get_y( x - x_offset, b ) && y < line2.get_y( x - x_offset, b ) && x > x_offset - height && x < x_offset )
        {
            return true;
        }
    }
    if( Enumber == 6 )
    {
        if( y >= line1.get_y( x - x_offset, b ) && y < line2.get_y( x - x_offset, b ) && x > x_offset - height && x < x_offset )
        {
            return true;
        }
    }
    // w razie jak cos by bylo nie tak to kolizja nie zachodzi
    return false;
}

////////////////////////////////////////
class WarTile
{
private:
    Equilateral triangle[ 6 ]; // tutaj przechowuje trojkaty
    int x_coordinates;
    int y_coordinates;
    bool occupied; // czy na danym kafelku jest jakis obiekt
public:
    WarTile();
    void set_position( int x, int y );
    int get_x();
    int get_y();
    void show( int row_number, int x_offset, int y_offset, int spaceing, SDL_Surface * thisSurface );
    int check_mouse( int row_number, int x_offset, int y_offset, int spaceing );
};
///////////////////////////////////////
WarTile::WarTile()
{
    triangle[ 0 ].set_triangle( 1 );
    triangle[ 1 ].set_triangle( 2 );
    triangle[ 2 ].set_triangle( 3 );
    triangle[ 3 ].set_triangle( 4 );
    triangle[ 4 ].set_triangle( 5 );
    triangle[ 5 ].set_triangle( 6 );
    occupied = false;
}
////////////////////////////////////////
void WarTile::set_position( int x, int y )
{
    x_coordinates = x;
    y_coordinates = y;
}
////////////////////////////////////////
int WarTile::get_x()
{
    return x_coordinates;
}
////////////////////////////////////////
int WarTile::get_y()
{
    return y_coordinates;
}
////////////////////////////////////////
// tutaj w ramach testu stworzylem funkcje wyswietlajaca mi obrazek hexagonu
// w testerze mojej gry wyswietlalo mi numer trojkata {1,2,3,4,5,6} w odpowiednim miejscu jak najechalem na dany punkt hexagonu
void WarTile::show( int row_number, int x_offset, int y_offset, int spaceing, SDL_Surface * thisSurface )
{
    if( occupied == false )
    {
        int H = triangle[ 0 ].get_H();
        int A = triangle[ 0 ].get_Aside();
       
        if( row_number == 0 || row_number % 2 == 0 )
        {
            apply_surface( x_offset + spaceing + H - 40 /*wymiary obrazka*/, y_offset + row_number *( 3 * A ) / 2 - 46 /*wymiary obrazka*/, thisSurface, screen );
        }
        if( row_number % 2 == 1 )
        {
            apply_surface( x_offset + spaceing - 40 /*wymiary obrazka*/, y_offset + row_number *( 3 * A ) / 2 - 46 /*wymiary obrazka*/, thisSurface, screen );
        }
    }
}
////////////////////////////////////////
// nie dopracowalem jeszcze mapy kafelkowej opartej na hexagonach dlatego narazie ta funkcja musi przyjmowac dane o numerze rzedu
int WarTile::check_mouse( int row_number, int x_offset, int y_offset, int spaceing ) //zwraca numer kafelka nad ktorym jest, 0 oznacza ze nie jest nad zadnym
{
    int A = triangle[ 0 ].get_Aside();
    int H = triangle[ 0 ].get_H();
   
    if( row_number == 0 || row_number % 2 == 0 )
    {
        for( int i = 0; i < 6; i++ )
        {
            if( triangle[ i ].check_range( x_offset + spaceing + H, y_offset + y_coordinates *( 3 * A ) / 2 ) == true )
            {
                return i + 1;
            }
        }
    }
    if( row_number % 2 == 1 )
    {
        for( int i = 0; i < 6; i++ )
        {
            if( triangle[ i ].check_range( x_offset + spaceing, y_offset + y_coordinates *( 3 * A ) / 2 ) == true )
            {
                return i + 1;
            }
        }
    }
    return 0;
}
////////////////////////////////////////
P-91466
« 1 »
  Strona 1 z 1