dgcor / DGEngine

An implementation of the Diablo 1 game engine
Other
243 stars 30 forks source link

Understanding Flare's level object's drawing offsets #23

Closed ghost closed 5 years ago

ghost commented 5 years ago

Currently, DGEngine is loading Flare's animations using the original texture rects and offsets converted to DGEngine's format.

examples:

Warrior animation:

https://github.com/dgengin/DGEngine/blob/master/gamefilesflare/level/player/Warrior/cel.json https://github.com/clintbellanger/flare-game/blob/branch1.08/mods/fantasycore/animations/enemies/skeleton.txt

item drop textures:

https://github.com/dgengin/DGEngine/blob/master/gamefilesflare/level/item/dropTextures.json https://github.com/clintbellanger/flare-game/blob/branch1.08/mods/fantasycore/animations/loot/

Town tileset:

https://github.com/dgengin/DGEngine/blob/master/gamefilesflare/level/data/grassland.json https://github.com/clintbellanger/flare-game/blob/branch1.08/mods/fantasycore/tilesetdefs/tileset_grassland.txt

Level tilesets are rendered correctly with the same code that draws Diablo's tilesets.

Level objects aren't. The reason is simply that I don't quite understand how they're applied in Flare so that I can figure out the best way to update DGEngine's code to support it.

Flare's drawing code is in (I think):

https://github.com/clintbellanger/flare-engine/blob/branch1.08/src/MapRenderer.cpp

One difference between Flare and DGEngine is that we add offsets and they subtract offsets. I added the following property to invert the offsets when loading Flare's resources so as to keep the code the same for both:

"invertOffsets": true

DGEngine's code that positions level objects is here:

https://github.com/dgengin/DGEngine/blob/master/src/Game/LevelObject.cpp

void LevelObject::updateDrawPosition(const LevelMap& map, const sf::Vector2f& drawPos)
{
    basePosition.x = drawPos.x + map.DefaultBlockWidth();
    basePosition.y = drawPos.y + map.DefaultBlockHeight();

    const auto& texSize = sprite.getTextureRect();

    originalPosition.x = basePosition.x - (texSize.width / 2);
    originalPosition.y = drawPos.y - texSize.height + map.DefaultTileHeight();

    sprite.setPosition(originalPosition + positionOffset);
}

This code will make it closer to what I think flare is doing:

void LevelObject::updateDrawPosition(const LevelMap& map, const sf::Vector2f& drawPos)
{
    basePosition.x = drawPos.x + map.DefaultBlockWidth();
    basePosition.y = drawPos.y + map.DefaultBlockHeight();

    const auto& texSize = sprite.getTextureRect();

    originalPosition = basePosition;

    //originalPosition.x = basePosition.x - (texSize.width / 2);
    //originalPosition.y = drawPos.y - texSize.height + map.DefaultTileHeight();

    sprite.setPosition(originalPosition + positionOffset);
}

This issue is to help figure out how the above function should be changed to make flare's game objects animate correctly.

With the correct code in place, the Skeleton's feet shouldn't move when animating the player.

mewmew commented 5 years ago

@dgengin Just a quick notice, the upstream repository for FLARE is now located at https://github.com/flareteam rather than https://github.com/clintbellanger. So, for the future pull from https://github.com/flareteam/flare-game

Edit regarding the issue with the offsets, I'm not sure exactly how it works. But, at least for drawing the Stairs assets of Flare, we got it working before, and the Stairs have offset x=0, y=48.

From https://github.com/mewspring/tmx/blob/23dfe64d6070aef2b31eb6aac1dc21ab2860bf92/testdata/test_csv.tmx#L6:

 <tileset firstgid="241" name="stairs" tilewidth="256" tileheight="256">
  <tileoffset x="0" y="48"/>
  <image source="stairs.png" width="1024" height="256"/>
 </tileset>

We handle offsets as follows.

From https://github.com/mewspring/tmx/blob/23dfe64d6070aef2b31eb6aac1dc21ab2860bf92/examples/mapview/view.go#L163:


// Draw draws the image representation of the map to the view image.
func (view *View) Draw() {
    for _, layer := range view.layers {
        if layer.Name == "collision" {
            continue
        }
        for row := 0; row < view.rows; row++ {
            for col := 0; col < view.cols; col++ {
                gid := layer.GetGID(col, row)
                tile, ok := view.tileset[gid]
                if !ok {
                    continue
                }
                sr := tile.Bounds()
                tileRect := view.GetTileRect(col, row, sr)
                tileRect = tileRect.Add(tile.Offset) // <<< --- here the offset of the tile is added to the target drawing rectangle.
                tileRect = tileRect.Add(image.Pt(0, view.delta))
                draw.Draw(view, tileRect, tile, sr.Min, draw.Over)
            }
        }
    }
}

For an example see https://github.com/mewspring/tmx#examples

Screenshot - tmxview

ghost commented 5 years ago

Thanks, it turns out the offsets weren't being updated on each texture update and that's why they were wrong. It's fixed now.