Skip to content

Commit

Permalink
Simplify foliage rendering
Browse files Browse the repository at this point in the history
During `ReencodeDungeonCels`, extracts floor tile foliage into
a triangle with the floor frame and a separate 16-px tall `TransparentSquare`.

This means that the floor frames are now always triangles and
the foliage can be rendered directly without masking.

Dungeon graphics sizes:

Map  | Frames | Foliage frames | Byte size  | Before PR | After PR
-----|--------|---------------:|-----------:|----------:|----------:
Town |  3,803 |             41 | 2,317,832  | 2,242,056 | 2,242,190
L1   |  1,119 |             11 |   738,836  |   721,604 |   721,110
L4   |  1,091 |              6 |   603,140  |   584,500 |   584,242

RG99 binary size reduced by ~4 KiB: 2,426,380 bytes -> 2,421,388 bytes
  • Loading branch information
glebm committed Aug 26, 2024
1 parent 71650f9 commit 6a5a7d4
Show file tree
Hide file tree
Showing 9 changed files with 259 additions and 182 deletions.
5 changes: 2 additions & 3 deletions Source/diablo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2857,6 +2857,8 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir)
IncProgress();
LoadTrns();
MakeLightTable();
LoadLevelSOLData();
IncProgress();
LoadLvlGFX();
SetDungeonMicros();
ClearClxDrawCache();
Expand Down Expand Up @@ -2911,7 +2913,6 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir)
if (!setlevel) {
CreateLevel(lvldir);
IncProgress();
LoadLevelSOLData();
SetRndSeed(DungeonSeeds[currlevel]);

if (leveltype != DTYPE_TOWN) {
Expand Down Expand Up @@ -3039,8 +3040,6 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir)
}
InitCorpses();
IncProgress();
LoadLevelSOLData();
IncProgress();

if (lvldir == ENTRY_WARPLVL)
GetPortalLvlPos();
Expand Down
54 changes: 11 additions & 43 deletions Source/engine/render/dun_render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,11 @@ constexpr int_fast16_t TriangleUpperHeight = DunFrameHeight / 2 - 1;
/** Height of the upper rectangle of a trapezoid tile. */
constexpr int_fast16_t TrapezoidUpperHeight = DunFrameHeight / 2;

constexpr int_fast16_t TriangleHeight = LowerHeight + TriangleUpperHeight;
constexpr int_fast16_t TriangleHeight = DunFrameTriangleHeight;

/** For triangles, for each pixel drawn vertically, this many pixels are drawn horizontally. */
constexpr int_fast16_t XStep = 2;

int_fast16_t GetTileHeight(TileType tile)
{
if (tile == TileType::LeftTriangle || tile == TileType::RightTriangle)
return TriangleHeight;
return Height;
}

#ifdef DEBUG_STR
std::pair<std::string_view, UiFlags> GetTileDebugStr(TileType tile)
{
Expand Down Expand Up @@ -322,10 +315,12 @@ DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderSquare(uint8_t *DVL_RESTRICT dst,
}

template <LightType Light, bool OpaquePrefix, int8_t PrefixIncrement>
DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTransparentSquareFull(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl)
DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTransparentSquareFull(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, unsigned height)
{
int8_t prefix = InitPrefix<PrefixIncrement>();
for (auto i = 0; i < Height; ++i, dst -= dstPitch + Width) {
DVL_ASSUME(height >= 16);
DVL_ASSUME(height <= 32);
for (unsigned i = 0; i < height; ++i, dst -= dstPitch + Width) {
uint_fast8_t drawWidth = Width;
while (drawWidth > 0) {
auto v = static_cast<int8_t>(*src++);
Expand Down Expand Up @@ -427,8 +422,8 @@ DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTransparentSquareClipped(uint8_t
template <LightType Light, bool OpaquePrefix, int8_t PrefixIncrement = 0>
DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTransparentSquare(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, Clip clip)
{
if (clip.width == Width && clip.height == Height) {
RenderTransparentSquareFull<Light, OpaquePrefix, PrefixIncrement>(dst, dstPitch, src, tbl);
if (clip.width == Width && clip.bottom == 0 && clip.top == 0) {
RenderTransparentSquareFull<Light, OpaquePrefix, PrefixIncrement>(dst, dstPitch, src, tbl, clip.height);
} else {
RenderTransparentSquareClipped<Light, OpaquePrefix, PrefixIncrement>(dst, dstPitch, src, tbl, clip);
}
Expand Down Expand Up @@ -972,18 +967,6 @@ DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTileType(TileType tile, uint8_t *
}
}

template <bool OpaquePrefix, int8_t PrefixIncrement>
DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTransparentSquareDispatch(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, Clip clip)
{
if (IsFullyDark(tbl)) {
RenderTransparentSquare<LightType::FullyDark, OpaquePrefix, PrefixIncrement>(dst, dstPitch, src, tbl, clip);
} else if (IsFullyLit(tbl)) {
RenderTransparentSquare<LightType::FullyLit, OpaquePrefix, PrefixIncrement>(dst, dstPitch, src, tbl, clip);
} else {
RenderTransparentSquare<LightType::PartiallyLit, OpaquePrefix, PrefixIncrement>(dst, dstPitch, src, tbl, clip);
}
}

template <LightType Light, bool OpaquePrefix, int8_t PrefixIncrement>
DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTrapezoidOrTransparentSquare(TileType tile, uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, Clip clip)
{
Expand Down Expand Up @@ -1086,27 +1069,18 @@ std::string_view MaskTypeToString(MaskType maskType)
}
#endif

void RenderTile(const Surface &out, Point position,
LevelCelBlock levelCelBlock, MaskType maskType, const uint8_t *tbl)
void DVL_ATTRIBUTE_HOT RenderTileFrame(const Surface &out, const Point &position, TileType tile, const uint8_t *src, int_fast16_t height,
MaskType maskType, const uint8_t *tbl)
{
const TileType tile = levelCelBlock.type();

#ifdef DEBUG_RENDER_OFFSET_X
position.x += DEBUG_RENDER_OFFSET_X;
#endif
#ifdef DEBUG_RENDER_OFFSET_Y
position.y += DEBUG_RENDER_OFFSET_Y;
#endif
#ifdef DEBUG_RENDER_COLOR
DBGCOLOR = GetTileDebugColor(tile);
#endif

const Clip clip = CalculateClip(position.x, position.y, Width, GetTileHeight(tile), out);
if (clip.width <= 0 || clip.height <= 0)
return;
const Clip clip = CalculateClip(position.x, position.y, DunFrameWidth, height, out);
if (clip.width <= 0 || clip.height <= 0) return;

const auto *pFrameTable = reinterpret_cast<const uint32_t *>(pDungeonCels.get());
const auto *src = reinterpret_cast<const uint8_t *>(&pDungeonCels[SDL_SwapLE32(pFrameTable[levelCelBlock.frame()])]);
uint8_t *dst = out.at(static_cast<int>(position.x + clip.left), static_cast<int>(position.y - clip.bottom));
const uint16_t dstPitch = out.pitch();

Expand All @@ -1127,12 +1101,6 @@ void RenderTile(const Surface &out, Point position,
case MaskType::Right:
RenderRightTrapezoidOrTransparentSquareDispatch</*OpaquePrefix=*/true, /*PrefixIncrement=*/-2>(tile, dst, dstPitch, src, tbl, clip);
break;
case MaskType::LeftFoliage:
RenderTransparentSquareDispatch</*OpaquePrefix=*/true, /*PrefixIncrement=*/2>(dst, dstPitch, src, tbl, clip);
break;
case MaskType::RightFoliage:
RenderTransparentSquareDispatch</*OpaquePrefix=*/false, /*PrefixIncrement=*/-2>(dst, dstPitch, src, tbl, clip);
break;
}

#ifdef DEBUG_STR
Expand Down
86 changes: 28 additions & 58 deletions Source/engine/render/dun_render.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

#include <cstdint>

#include <SDL_endian.h>

#include "engine/point.hpp"
#include "engine/surface.hpp"
#include "levels/dun_tile.hpp"
#include "levels/gendung.h"
#include "utils/attributes.h"

// #define DUN_RENDER_STATS
#ifdef DUN_RENDER_STATS
Expand Down Expand Up @@ -85,60 +85,6 @@ enum class MaskType : uint8_t {
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
*/
Left,

/**
* @brief Only the upper-left triangle is rendered.
*
* Can only be used with `TileType::TransparentSquare`.
*
* The lower 16 rows are skipped.
* The upper 16 rows are arranged like this (🮆 = opaque, 🮐 = not rendered):
*
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆
*/
RightFoliage,

/**
* @brief Only the upper right triangle is rendered.
*
* Can only be used with `TileType::TransparentSquare`.
*
* The lower 16 rows are skipped.
* The upper 16 rows are arranged like this (🮆 = opaque, 🮐 = not rendered):
*
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
*/
LeftFoliage,
};

#ifdef DUN_RENDER_STATS
Expand All @@ -163,6 +109,12 @@ std::string_view TileTypeToString(TileType tileType);
std::string_view MaskTypeToString(MaskType maskType);
#endif

/**
* @brief Low-level tile rendering function.
*/
void RenderTileFrame(const Surface &out, const Point &position, TileType tile, const uint8_t *src, int_fast16_t height,
MaskType maskType, const uint8_t *tbl);

/**
* @brief Blit current world CEL to the given buffer
* @param out Target buffer
Expand All @@ -171,8 +123,26 @@ std::string_view MaskTypeToString(MaskType maskType);
* @param maskType The mask to use,
* @param tbl LightTable or TRN for a tile.
*/
void RenderTile(const Surface &out, Point position,
LevelCelBlock levelCelBlock, MaskType maskType, const uint8_t *tbl);
DVL_ALWAYS_INLINE void RenderTile(const Surface &out, const Point &position,
LevelCelBlock levelCelBlock, MaskType maskType, const uint8_t *tbl)
{
const TileType tileType = levelCelBlock.type();
RenderTileFrame(out, position, tileType,
GetDunFrame(levelCelBlock.frame()),
(tileType == TileType::LeftTriangle || tileType == TileType::RightTriangle)
? DunFrameTriangleHeight
: DunFrameHeight,
maskType, tbl);
}

/**
* @brief Renders a floor foliage tile.
*/
DVL_ALWAYS_INLINE void RenderTileFoliage(const Surface &out, const Point &position, LevelCelBlock levelCelBlock, const uint8_t *tbl)
{
RenderTileFrame(out, Point { position.x, position.y - 16 }, TileType::TransparentSquare,
GetDunFrameFoliage(levelCelBlock.frame()), /*height=*/16, MaskType::Solid, tbl);
}

/**
* @brief Render a black 64x31 tile ◆
Expand Down
58 changes: 25 additions & 33 deletions Source/engine/render/scrollrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "hwcursor.hpp"
#include "init.h"
#include "inv.h"
#include "levels/dun_tile.hpp"
#include "levels/gendung.h"
#include "lighting.h"
#include "lua/lua.hpp"
Expand Down Expand Up @@ -481,7 +482,6 @@ void DrawCell(const Surface &out, Point tilePosition, Point targetBufferPosition
if ((SDL_GetModState() & KMOD_ALT) != 0)
transparency = false;
#endif
const bool foliage = IsFloor(tilePosition);

const auto getFirstTileMaskLeft = [=](TileType tile) -> MaskType {
if (transparency) {
Expand All @@ -497,8 +497,6 @@ void DrawCell(const Surface &out, Point tilePosition, Point targetBufferPosition
return MaskType::Transparent;
}
}
if (foliage)
return MaskType::LeftFoliage;
return MaskType::Solid;
};

Expand All @@ -516,40 +514,34 @@ void DrawCell(const Surface &out, Point tilePosition, Point targetBufferPosition
return MaskType::Transparent;
}
}
if (foliage)
return MaskType::RightFoliage;
return MaskType::Solid;
};

// The first micro tile may be rendered with a foliage mask.
// Only `TransparentSquare` tiles are rendered when `foliage` is true.
{
{
const LevelCelBlock levelCelBlock { pMap->mt[0] };
const TileType tileType = levelCelBlock.type();
const MaskType maskType = getFirstTileMaskLeft(tileType);
if (levelCelBlock.hasValue()) {
if (maskType != MaskType::LeftFoliage || tileType == TileType::TransparentSquare) {
RenderTile(out, targetBufferPosition,
levelCelBlock, maskType, tbl);
}
// If the first micro tile is a floor tile, it may be followed
// by foliage which should be rendered now.
const bool isFloor = IsFloor(tilePosition);
if (const LevelCelBlock levelCelBlock { pMap->mt[0] }; levelCelBlock.hasValue()) {
const TileType tileType = levelCelBlock.type();
if (!isFloor || tileType == TileType::TransparentSquare) {
if (isFloor && tileType == TileType::TransparentSquare) {
RenderTileFoliage(out, targetBufferPosition, levelCelBlock, tbl);
} else {
RenderTile(out, targetBufferPosition, levelCelBlock, getFirstTileMaskLeft(tileType), tbl);
}
}
{
const LevelCelBlock levelCelBlock { pMap->mt[1] };
const TileType tileType = levelCelBlock.type();
const MaskType maskType = getFirstTileMaskRight(tileType);
if (levelCelBlock.hasValue()) {
if (transparency || !foliage || levelCelBlock.type() == TileType::TransparentSquare) {
if (maskType != MaskType::RightFoliage || tileType == TileType::TransparentSquare) {
RenderTile(out, targetBufferPosition + Displacement { TILE_WIDTH / 2, 0 },
levelCelBlock, maskType, tbl);
}
}
}
if (const LevelCelBlock levelCelBlock { pMap->mt[1] }; levelCelBlock.hasValue()) {
const TileType tileType = levelCelBlock.type();
if (!isFloor || tileType == TileType::TransparentSquare) {
if (isFloor && tileType == TileType::TransparentSquare) {
RenderTileFoliage(out, targetBufferPosition + Displacement { TILE_WIDTH / 2, 0 }, levelCelBlock, tbl);
} else {
RenderTile(out, targetBufferPosition + Displacement { TILE_WIDTH / 2, 0 },
levelCelBlock, getFirstTileMaskRight(tileType), tbl);
}
}
targetBufferPosition.y -= TILE_HEIGHT;
}
targetBufferPosition.y -= TILE_HEIGHT;

for (uint_fast8_t i = 2, n = MicroTileLen; i < n; i += 2) {
{
Expand Down Expand Up @@ -592,15 +584,15 @@ void DrawFloorTile(const Surface &out, Point tilePosition, Point targetBufferPos
{
const LevelCelBlock levelCelBlock { DPieceMicros[levelPieceId].mt[0] };
if (levelCelBlock.hasValue()) {
RenderTile(out, targetBufferPosition,
levelCelBlock, MaskType::Solid, tbl);
RenderTileFrame(out, targetBufferPosition, TileType::LeftTriangle,
GetDunFrame(levelCelBlock.frame()), DunFrameTriangleHeight, MaskType::Solid, tbl);
}
}
{
const LevelCelBlock levelCelBlock { DPieceMicros[levelPieceId].mt[1] };
if (levelCelBlock.hasValue()) {
RenderTile(out, targetBufferPosition + Displacement { TILE_WIDTH / 2, 0 },
levelCelBlock, MaskType::Solid, tbl);
RenderTileFrame(out, targetBufferPosition + Displacement { TILE_WIDTH / 2, 0 }, TileType::RightTriangle,
GetDunFrame(levelCelBlock.frame()), DunFrameTriangleHeight, MaskType::Solid, tbl);
}
}
}
Expand Down
22 changes: 22 additions & 0 deletions Source/levels/dun_tile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <cstdint>

#include "utils/enum_traits.h"

#define TILE_WIDTH 64
#define TILE_HEIGHT 32

Expand Down Expand Up @@ -100,10 +102,30 @@ struct LevelCelBlock {
}
};

enum class TileProperties : uint8_t {
// clang-format off
None = 0,
Solid = 1 << 0,
BlockLight = 1 << 1,
BlockMissile = 1 << 2,
Transparent = 1 << 3,
TransparentLeft = 1 << 4,
TransparentRight = 1 << 5,
Trap = 1 << 7,
// clang-format on
};
use_enum_as_flags(TileProperties);

struct MICROS {
LevelCelBlock mt[16];
};

/** Width of a tile rendering primitive. */
constexpr int_fast16_t DunFrameWidth = TILE_WIDTH / 2;

/** Height of a tile rendering primitive (except triangles). */
constexpr int_fast16_t DunFrameHeight = TILE_HEIGHT;

constexpr int_fast16_t DunFrameTriangleHeight = 31;

} // namespace devilution
Loading

0 comments on commit 6a5a7d4

Please sign in to comment.