FOnline Development > Share Your Work

Working on intrface style...

<< < (3/3)

Wire:
https://www.youtube.com/watch?v=iFOfSlDCwYw

adumbperson:

--- Quote from: Wipe on June 07, 2019, 06:00:12 pm ---
Zoom level is just an argument to one of engine's draw functions, so scaling minimap up/down is trivial and doesn't need rebuilding/caching different data for different zoom levels. For a first version, it's good enough i think.

--- End quote ---

Impressive! where do I find this nice prototype?


--- Quote from: Wire on June 08, 2019, 01:19:02 am ---https://www.youtube.com/watch?v=iFOfSlDCwYw

--- End quote ---

WHY?

Wipe:

--- Quote from: adumbperson on June 08, 2019, 10:44:55 am ---where do I find this nice prototype?

--- End quote ---

On my HDD only at the moment ;D
I'll throw a link here some rainy day (need to fix/finish few things first)... but i'm honestly not sure if it would be that useful. It's easy to get lost in UI stuff and comments barely exists at this moment, so better to extract the essence of a whole thing if anyone wants. While everything below is in C++, it should be possible to recreate everything in r412 dlls (and maaany older revs), or even ported to scripts.


TL;DR:
- GetCoords() (FOHexMap.cs)
- GetField() (FOClassic.h/FOnline.h/HexManager.h)
- PrepPoint, PointVec (SpriteManager.h)
- DrawPoints() (SpriteManager.cpp)


We start with small function to deal with hexes. It's simplified version of GetCoords() - converts hx,hy to 2d space resizing each hex to 2x1, where left part is a place for pixel, and right part is a null space for hexes above/below.


--- Code: ---H H H H H
 H H H H
H H H H H

--- End code ---

--- Code: (c++) ---void FOC::Hex2D( uint16& hexX, uint16& hexY, uint16 mapWidth )
{
    const uint16 hx = hexX, hy = hexY;

    Hex2D( hx, hy, hexX, hexY, mapWidth );
}

void FOC::Hex2D( uint16 hexX, uint16 hexY, uint16& x2d, uint16& y2d, uint16 mapWidth )
{
    int x = hexY - hexX * 2;
    int y = hexY + hexX / 2;
    if( hexX > 1 )
        x += hexX / 2;
    x += mapWidth;

    x2d = x;
    y2d = y;
}

--- End code ---

As any FOnline map should look like this, after conversion to 2d we have a huge area outside scrollblockers which we need to get rid of.


--- Code: (c++) ---    // define minimap bounds

    uint16 minPX = uint16( -1 ), maxPX = 0, minPY = uint16( -1 ), maxPY = 0;
    for( uint16 hexX = 0; hexX < mapWidth; hexX++ )
    {
        for( uint16 hexY = 0; hexY < mapHeight; hexY++ )
        {
            bool show = false;
            uint dummy = 0;

            // check if current hex is going to be part of minimap
            if( GetHex( hexX, hexY, show, dummy ) && show )
            {
                // convert hex position to 2d position
                uint16 px = hexX, py = hexY;
                Hex2D( px, py, mapWidth );

                // update bounds
                minPX = std::min( minPX, px );
                maxPX = std::max( maxPX, px );
                minPY = std::min( minPY, py );
                maxPY = std::max( maxPY, py );
            }
        }
    }

--- End code ---

Here GetHex() function is checking if there's anything interesting at specified position - will there be pixel placed for current hex or not? At this point it doesn't matter what it's going to be. For test purposes i checked for scrollblockers, as seen in previous post.


--- Code: (c++) ---    Field* mapField = (Field*)(GameOpt.ClientMap);
    // ...
    Field& field = mapField[hexY * mapWidth + hexX];

    if( field.ScrollBlock )
        // ...

--- End code ---

Once bounds are set, we process the map one more time and prepare draw data.


--- Code: (c++) ---    // process map

    PointVec minimap;

    for( uint16 hexX = 0; hexX < mapWidth; hexX++ )
    {
        for( uint16 hexY = 0; hexY < mapHeight; hexY++ )
        {
            // convert hex position to 2d position
            uint16 px = hexX, py = hexY;
            Hex2D( px, py, mapWidth );

            // ignore everything outside bounds
            if( px < minPX || px > maxPX || py < minPY || py > maxPY )
                continue;

            bool show = false;
            uint color = 0;

            if( !GetHex( hexX, hexY, show, color ) || !show )
                continue;

            // adjust position
            px -= minPX;
            py -= minPY;

            minimap.push_back( PrepPoint( px, py, color ) );
        }
    }

--- End code ---

Here, GetHex() is used fully and tells if given hex is part of minimap, and if it is - what color should be used for a pixel. In hardcoded minimap, it's done by FOClient::LmapPrepareMap(); GetHex() does similiar thing, except it works with single hex, and returns info only, without changing anything.
Anyway, once we process whole map, all what's left is to finally draw a whole thing.

Our BFF now is SpriteManager::DrawPoint(), which is also used internally after calling DrawPrimitive() from scripts. DrawPoints() accepts two tasty arguments, which sadly are not available for scripts in clean r412 - offset and zoom. That plus minimap bounds calculated earlier, allows to easily get pixel-size of minimap, resize, and move it around/stick to corner/etc without rebuilding whole thing.


--- Code: (c++) ---SprMngr.DrawPoints( DRAW_PRIMITIVE_POINTLIST, minimap );

--- End code ---

tada.wav

Obviously, doing all above every cycle is waste of CPU time, as majority of minimap does not change as long sceneries/walls doesn't. So if minimap should include critters/items/any other dynamic elements, they can be put into separate PointVec (updated every time) which will be drawn after the one with walls.


...wrote waaay more than i initially planned, but oh well. Majority is probably boring/obvious stuff, but maybe some detail would push someone in right direction.

adumbperson:

--- Quote from: Wipe on June 09, 2019, 04:38:21 am ---On my HDD only at the moment ;D
I'll throw a link here some rainy day (need to fix/finish few things first)... but i'm honestly not sure if it would be that useful. It's easy to get lost in UI stuff and comments barely exists at this moment, so better to extract the essence of a whole thing if anyone wants. While everything below is in C++, it should be possible to recreate everything in r412 dlls (and maaany older revs), or even ported to scripts.

--- End quote ---

To be sincere with you, my skill doesn't make me able to do advanced UI authoring. I'm mainly grinding (hardly) the mechanism by examples...
Can't wait to read your proto!


--- Quote from: Wipe on June 09, 2019, 04:38:21 am ---TL;DR:
- GetCoords() (FOHexMap.cs)
- GetField() (FOClassic.h/FOnline.h/HexManager.h)
- PrepPoint, PointVec (SpriteManager.h)
- DrawPoints() (SpriteManager.cpp)


We start with small function to deal with hexes. It's simplified version of GetCoords() - converts hx,hy to 2d space resizing each hex to 2x1, where left part is a place for pixel, and right part is a null space for hexes above/below.

...

...wrote waaay more than i initially planned, but oh well. Majority is probably boring/obvious stuff, but maybe some detail would push someone in right direction.

--- End quote ---

Thanks a lot for instructions.

Navigation

[0] Message Index

[*] Previous page

Go to full version