diff options
author | Florian Diebold <flodiebold@gmail.com> | 2011-04-11 13:06:27 +0200 |
---|---|---|
committer | Florian Diebold <flodiebold@gmail.com> | 2011-06-26 17:41:18 +0200 |
commit | 228770c101824ebc06384a2dc9bf0c27442c10e6 (patch) | |
tree | c7055c374cd68059fcf360848ff04cd78f00a56d /crawl-ref/source/tilecell.cc | |
parent | aa9fe6c8a5b138c1f5b65810d3fd63fbf218f6ad (diff) | |
download | crawl-ref-228770c101824ebc06384a2dc9bf0c27442c10e6.tar.gz crawl-ref-228770c101824ebc06384a2dc9bf0c27442c10e6.zip |
Move rendering logic to the client, make it more complete.
Diffstat (limited to 'crawl-ref/source/tilecell.cc')
-rw-r--r-- | crawl-ref/source/tilecell.cc | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/crawl-ref/source/tilecell.cc b/crawl-ref/source/tilecell.cc new file mode 100644 index 0000000000..54d39ccad8 --- /dev/null +++ b/crawl-ref/source/tilecell.cc @@ -0,0 +1,357 @@ +#include "AppHdr.h" + +#include "tilecell.h" + +#include "cloud.h" +#include "coord.h" +#include "coordit.h" +#include "env.h" +#include "terrain.h" +#include "tiledef-dngn.h" + +void packed_cell::clear() +{ + num_dngn_overlay = 0; + fg = 0; + bg = 0; + + is_bloody = false; + is_silenced = false; + is_haloed = false; + is_moldy = false; + is_sanctuary = false; + is_liquefied = false; + swamp_tree_water = false; +} + +bool packed_cell::operator ==(const packed_cell &other) const +{ + if (fg != other.fg) return false; + if (bg != other.bg) return false; + + if (is_bloody != other.is_bloody) return false; + if (is_silenced != other.is_silenced) return false; + if (is_haloed != other.is_haloed) return false; + if (is_moldy != other.is_moldy) return false; + if (is_sanctuary != other.is_sanctuary) return false; + if (is_liquefied != other.is_liquefied) return false; + if (swamp_tree_water != other.swamp_tree_water) return false; + + if (num_dngn_overlay != other.num_dngn_overlay) return false; + for (int i = 0; i < num_dngn_overlay; ++i) + { + if (dngn_overlay[i] != other.dngn_overlay[i]) return false; + } + return true; +} + +enum wave_type +{ + WV_NONE = 0, + WV_SHALLOW, + WV_DEEP, +}; + +static wave_type _get_wave_type(bool shallow) +{ + return (shallow ? WV_SHALLOW : WV_DEEP); +} + +static void _add_overlay(int tileidx, packed_cell *cell) +{ + cell->dngn_overlay[cell->num_dngn_overlay++] = tileidx; +} + +static void _pack_shoal_waves(const coord_def &gc, packed_cell *cell) +{ + // Add wave tiles on floor adjacent to shallow water. + const dungeon_feature_type feat = env.map_knowledge(gc).feat(); + const bool feat_has_ink = (cloud_type_at(coord_def(gc)) == CLOUD_INK); + + if (feat == DNGN_DEEP_WATER && feat_has_ink) + { + _add_overlay(TILE_WAVE_INK_FULL, cell); + return; + } + + if (feat != DNGN_FLOOR && feat != DNGN_UNDISCOVERED_TRAP + && feat != DNGN_SHALLOW_WATER && feat != DNGN_DEEP_WATER) + { + return; + } + + const bool ink_only = (feat == DNGN_DEEP_WATER); + + wave_type north = WV_NONE, south = WV_NONE, + east = WV_NONE, west = WV_NONE, + ne = WV_NONE, nw = WV_NONE, + se = WV_NONE, sw = WV_NONE; + + bool inkn = false, inks = false, inke = false, inkw = false, + inkne = false, inknw = false, inkse = false, inksw = false; + + for (radius_iterator ri(gc, 1, true, false, true); ri; ++ri) + { + if (!env.map_knowledge(*ri).seen() && !env.map_knowledge(*ri).mapped()) + continue; + + const bool ink = (cloud_type_at(coord_def(*ri)) == CLOUD_INK); + + bool shallow = false; + if (env.map_knowledge(*ri).feat() == DNGN_SHALLOW_WATER) + { + // Adjacent shallow water is only interesting for + // floor cells. + if (!ink && feat == DNGN_SHALLOW_WATER) + continue; + + shallow = true; + } + else if (env.map_knowledge(*ri).feat() != DNGN_DEEP_WATER) + continue; + + if (!ink_only) + { + if (ri->x == gc.x) // orthogonals + { + if (ri->y < gc.y) + north = _get_wave_type(shallow); + else + south = _get_wave_type(shallow); + } + else if (ri->y == gc.y) + { + if (ri->x < gc.x) + west = _get_wave_type(shallow); + else + east = _get_wave_type(shallow); + } + else // diagonals + { + if (ri->x < gc.x) + { + if (ri->y < gc.y) + nw = _get_wave_type(shallow); + else + sw = _get_wave_type(shallow); + } + else + { + if (ri->y < gc.y) + ne = _get_wave_type(shallow); + else + se = _get_wave_type(shallow); + } + } + } + if (!feat_has_ink && ink) + { + if (ri->x == gc.x) // orthogonals + { + if (ri->y < gc.y) + inkn = true; + else + inks = true; + } + else if (ri->y == gc.y) + { + if (ri->x < gc.x) + inkw = true; + else + inke = true; + } + else // diagonals + { + if (ri->x < gc.x) + { + if (ri->y < gc.y) + inknw = true; + else + inksw = true; + } + else + { + if (ri->y < gc.y) + inkne = true; + else + inkse = true; + } + } + } + } + + if (!ink_only) + { + // First check for shallow water. + if (north == WV_SHALLOW) + _add_overlay(TILE_WAVE_N, cell); + if (south == WV_SHALLOW) + _add_overlay(TILE_WAVE_S, cell); + if (east == WV_SHALLOW) + _add_overlay(TILE_WAVE_E, cell); + if (west == WV_SHALLOW) + _add_overlay(TILE_WAVE_W, cell); + + // Then check for deep water, overwriting shallow + // corner waves, if necessary. + if (north == WV_DEEP) + _add_overlay(TILE_WAVE_DEEP_N, cell); + if (south == WV_DEEP) + _add_overlay(TILE_WAVE_DEEP_S, cell); + if (east == WV_DEEP) + _add_overlay(TILE_WAVE_DEEP_E, cell); + if (west == WV_DEEP) + _add_overlay(TILE_WAVE_DEEP_W, cell); + + if (ne == WV_SHALLOW && !north && !east) + _add_overlay(TILE_WAVE_CORNER_NE, cell); + else if (ne == WV_DEEP && north != WV_DEEP && east != WV_DEEP) + _add_overlay(TILE_WAVE_DEEP_CORNER_NE, cell); + if (nw == WV_SHALLOW && !north && !west) + _add_overlay(TILE_WAVE_CORNER_NW, cell); + else if (nw == WV_DEEP && north != WV_DEEP && west != WV_DEEP) + _add_overlay(TILE_WAVE_DEEP_CORNER_NW, cell); + if (se == WV_SHALLOW && !south && !east) + _add_overlay(TILE_WAVE_CORNER_SE, cell); + else if (se == WV_DEEP && south != WV_DEEP && east != WV_DEEP) + _add_overlay(TILE_WAVE_DEEP_CORNER_SE, cell); + if (sw == WV_SHALLOW && !south && !west) + _add_overlay(TILE_WAVE_CORNER_SW, cell); + else if (sw == WV_DEEP && south != WV_DEEP && west != WV_DEEP) + _add_overlay(TILE_WAVE_DEEP_CORNER_SW, cell); + } + + // Overlay with ink sheen, if necessary. + if (feat_has_ink) + _add_overlay(TILE_WAVE_INK_FULL, cell); + else + { + if (inkn) + _add_overlay(TILE_WAVE_INK_N, cell); + if (inks) + _add_overlay(TILE_WAVE_INK_S, cell); + if (inke) + _add_overlay(TILE_WAVE_INK_E, cell); + if (inkw) + _add_overlay(TILE_WAVE_INK_W, cell); + if (inkne || inkn || inke) + _add_overlay(TILE_WAVE_INK_CORNER_NE, cell); + if (inknw || inkn || inkw) + _add_overlay(TILE_WAVE_INK_CORNER_NW, cell); + if (inkse || inks || inke) + _add_overlay(TILE_WAVE_INK_CORNER_SE, cell); + if (inksw || inks || inkw) + _add_overlay(TILE_WAVE_INK_CORNER_SW, cell); + } +} + +static dungeon_feature_type _safe_feat(coord_def gc) +{ + if (!map_bounds(gc)) + return (DNGN_UNSEEN); + + return (env.map_knowledge(gc).feat()); +} + +static bool _is_seen_land(coord_def gc) +{ + const dungeon_feature_type feat = _safe_feat(gc); + + return (feat != DNGN_UNSEEN && !feat_is_water(feat) && feat != DNGN_LAVA); +} + +static bool _is_seen_shallow(coord_def gc) +{ + const dungeon_feature_type feat = _safe_feat(gc); + + return (feat == DNGN_SHALLOW_WATER || feat == DNGN_SWAMP_TREE); +} + +static void _pack_default_waves(const coord_def &gc, packed_cell *cell) +{ + // Any tile on water with an adjacent solid tile will get an extra + // bit of shoreline. + dungeon_feature_type feat = env.map_knowledge(gc).feat(); + + // Treat trees in Swamp as though they were shallow water. + if (cell->swamp_tree_water && feat == DNGN_TREE) + feat = DNGN_SHALLOW_WATER; + + if (!feat_is_water(feat) && feat != DNGN_LAVA || env.grid_colours(gc)) + return; + + if (feat == DNGN_DEEP_WATER) + { + if (_is_seen_shallow(coord_def(gc.x, gc.y - 1))) + _add_overlay(TILE_DNGN_WAVE_N, cell); + if (_is_seen_shallow(coord_def(gc.x + 1, gc.y - 1))) + _add_overlay(TILE_DNGN_WAVE_NE, cell); + if (_is_seen_shallow(coord_def(gc.x + 1, gc.y))) + _add_overlay(TILE_DNGN_WAVE_E, cell); + if (_is_seen_shallow(coord_def(gc.x + 1, gc.y + 1))) + _add_overlay(TILE_DNGN_WAVE_SE, cell); + if (_is_seen_shallow(coord_def(gc.x, gc.y + 1))) + _add_overlay(TILE_DNGN_WAVE_S, cell); + if (_is_seen_shallow(coord_def(gc.x - 1, gc.y + 1))) + _add_overlay(TILE_DNGN_WAVE_SW, cell); + if (_is_seen_shallow(coord_def(gc.x - 1, gc.y))) + _add_overlay(TILE_DNGN_WAVE_W, cell); + if (_is_seen_shallow(coord_def(gc.x - 1, gc.y - 1))) + _add_overlay(TILE_DNGN_WAVE_NW, cell); + } + + + bool north = _is_seen_land(coord_def(gc.x, gc.y - 1)); + bool west = _is_seen_land(coord_def(gc.x - 1, gc.y)); + bool east = _is_seen_land(coord_def(gc.x + 1, gc.y)); + + if (north || west || east) + { + if (north) + _add_overlay(TILE_SHORE_N, cell); + if (west) + _add_overlay(TILE_SHORE_W, cell); + if (east) + _add_overlay(TILE_SHORE_E, cell); + if (north && west) + _add_overlay(TILE_SHORE_NW, cell); + if (north && east) + _add_overlay(TILE_SHORE_NE, cell); + } +} + +static bool _is_seen_wall(coord_def gc) +{ + dungeon_feature_type feat = _safe_feat(gc); + return (feat != DNGN_UNSEEN && feat <= DNGN_MAXWALL); +} + +static void _pack_wall_shadows(const coord_def &gc, packed_cell *cell) +{ + if (_is_seen_wall(gc)) + return; + + if (_is_seen_wall(coord_def(gc.x - 1, gc.y))) + _add_overlay(TILE_DNGN_WALL_SHADOW_W, cell); + if (_is_seen_wall(coord_def(gc.x - 1, gc.y - 1))) + _add_overlay(TILE_DNGN_WALL_SHADOW_NW, cell); + if (_is_seen_wall(coord_def(gc.x, gc.y - 1))) + _add_overlay(TILE_DNGN_WALL_SHADOW_N, cell); + if (_is_seen_wall(coord_def(gc.x + 1, gc.y - 1))) + _add_overlay(TILE_DNGN_WALL_SHADOW_NE, cell); + if (_is_seen_wall(coord_def(gc.x + 1, gc.y))) + _add_overlay(TILE_DNGN_WALL_SHADOW_E, cell); +} + +void pack_cell_overlays(const coord_def &gc, packed_cell *cell) +{ + if (player_in_branch(BRANCH_SHOALS)) + { + _pack_shoal_waves(gc, cell); + } + else + { + _pack_default_waves(gc, cell); + _pack_wall_shadows(gc, cell); + } +} |