Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- void Platform::_render_tile(point2i at, point2i where) const
- {
- ISIS_ASSERT(safe_rect_.includes(at));
- ISIS_ASSERT(!(*this)[at].out_of_bounds);
- // TODO The whole call could be optimised out for empty tiles
- // if we were able to determine instantly that they have no neighbours.
- auto const& tile = (*this)[at];
- if (current_layer_ == CityLayer::Subterranean)
- {
- // Nothing to draw for empty.
- if (!tile.is_visible())
- return;
- uint frame = tile.is_empty() ? BEACON_UNDERGROUND : UNDERGROUND;
- tiles_.GoTo(frame);
- tiles_.RenderAt(where);
- return;
- }
- // NOTE: Empty tiles are allowed here now, so the stage can be negative (PLATFORM_STAGE_NONE).
- int shown_stage = tile.stage();
- if (current_layer_ == CityLayer::Platform)
- shown_stage = std::min(shown_stage, PLATFORM_MAX_STAGE_PLATFORM_LAYER);
- int level_here = PlatformTile::stage_to_level(shown_stage);
- // bool allows_for_mature_borders = !tile.is_present();
- if (shown_stage < PLATFORM_MIN_STAGE_NO_UPPER_BORDER)
- // if (!(allows_for_mature_borders && this->unchecked_has_mature(at + STEP_NORTH)))
- {
- // Render the upper neighbour's bottom.
- int level_above = this->_unchecked_get_shown_level(at + STEP_NORTH);
- ISIS_ASSERT(level_here < PLATFORM_TOTAL_LEVELS - 1);
- uint frame = (uint)(PLATFORM_TOTAL_LEVELS * level_here + level_above);
- bottoms_.GoTo(frame);
- bottoms_.RenderAt(where);
- }
- // The main sprite.
- // NOTE: Before the neighbours' sides.
- if (tile.is_visible())
- {
- uint main_tile = UINT_MAX;
- optional<int> tile_colour_variation_4bit;
- uint lights_tile = UINT_MAX;
- switch (shown_stage)
- {
- case -1:
- if (tile.order == PlatformTile::Order::Construction)
- {
- // Construction has not yet started - only a beacon is placed.
- if (random_[at].platform_beacon_blink_phase_4bit() == current_blink_phase_)
- main_tile = BEACON_ON;
- else
- main_tile = BEACON_OFF;
- }
- break;
- case 0: main_tile = STAGE_0; break;
- case 1: main_tile = STAGE_1; break;
- case 2: main_tile = STAGE_2; break;
- case 3: main_tile = STAGE_3; break;
- case 4: main_tile = STAGE_4; break;
- case 5:
- {
- // 01
- // 23
- constexpr uint NOT_SET = UINT_MAX;
- uint subtiles[4] = {NOT_SET, NOT_SET, NOT_SET, NOT_SET};
- // NOTE: Both actual and blueprint information is used.
- auto const& blueprint_tile = blueprint_[at];
- if (!blueprint_tile.power.is_empty())
- {
- if (blueprint_tile.power.hub)
- {
- subtiles[0] = STAGE_5_POWER_HUB_MAIN;
- subtiles[1] = STAGE_5_POWER_HUB_RIGHT;
- subtiles[2] = STAGE_5_POWER_HUB_BOTTOM;
- }
- else
- subtiles[0] = STAGE_5_POWER_GRID;
- }
- if (!blueprint_tile.data.is_empty())
- {
- if (blueprint_tile.data.hub)
- {
- subtiles[1] = STAGE_5_DATA_HUB_TOP;
- subtiles[2] = STAGE_5_DATA_HUB_LEFT;
- subtiles[3] = STAGE_5_DATA_HUB_MAIN;
- }
- else
- subtiles[3] = STAGE_5_DATA_GRID;
- }
- // NOTE: For proper combining, actual state is checked after the blueprint,
- // overriding subtiles if necessary.
- if (!tile.power.is_empty())
- {
- if (tile.power.hub)
- {
- subtiles[0] = STAGE_5_POWER_HUB_MAIN;
- subtiles[1] = STAGE_5_POWER_HUB_RIGHT;
- subtiles[2] = STAGE_5_POWER_HUB_BOTTOM;
- }
- else
- subtiles[0] = STAGE_5_POWER_GRID;
- }
- if (!tile.data.is_empty())
- {
- if (tile.data.hub)
- {
- subtiles[1] = STAGE_5_DATA_HUB_TOP;
- subtiles[2] = STAGE_5_DATA_HUB_LEFT;
- subtiles[3] = STAGE_5_DATA_HUB_MAIN;
- }
- else
- subtiles[3] = STAGE_5_DATA_GRID;
- }
- static constexpr uint random_subtiles[4] =
- {STAGE_5_RANDOM_0, STAGE_5_RANDOM_1, STAGE_5_RANDOM_2, STAGE_5_RANDOM_3};
- // TODO no need to do checks above?
- bool no_building = building_map_[at] == nullptr;
- for (uint i = 0; i < 4; ++i)
- {
- uint subtile = subtiles[i];
- if (subtile == NOT_SET)
- {
- if (no_building)
- subtile = STAGE_5_RANDOM_3;
- else
- subtile = random_subtiles[random_[at].platform_inside_random_tile_2bit(i)];
- }
- subtiles_.GoTo(subtile);
- // NOTE: sub-tiles are not shifted according to the level,
- // so need an explicit offset of 1 pixel down for stages 5 and 6.
- subtiles_.RenderAt(where + subtile_offset_by_index[i] + vec2i{0, 1});
- }
- }
- break;
- case 6:
- {
- // 01
- // 23
- constexpr uint NOT_SET = UINT_MAX;
- constexpr uint ALREADY_DRAWN = UINT_MAX - 1;
- uint subtiles[4] = {NOT_SET, NOT_SET, NOT_SET, NOT_SET};
- // NOTE: Draw planned features (from blueprint) as stage 5 tiles.
- // They also get overridden by the real features.
- auto const& blueprint_tile = blueprint_[at];
- if (!blueprint_tile.power.is_empty())
- {
- if (blueprint_tile.power.hub)
- {
- subtiles[0] = STAGE_5_POWER_HUB_MAIN;
- subtiles[1] = STAGE_5_POWER_HUB_RIGHT;
- subtiles[2] = STAGE_5_POWER_HUB_BOTTOM;
- }
- else
- subtiles[0] = STAGE_5_POWER_GRID;
- }
- if (!blueprint_tile.data.is_empty())
- {
- if (blueprint_tile.data.hub)
- {
- subtiles[1] = STAGE_5_DATA_HUB_TOP;
- subtiles[2] = STAGE_5_DATA_HUB_LEFT;
- subtiles[3] = STAGE_5_DATA_HUB_MAIN;
- }
- else
- subtiles[3] = STAGE_5_DATA_GRID;
- }
- // NOTE: Real data, if present, override 'planned' features.
- if (!tile.power.is_empty())
- {
- uint frame = tile.power.connection_mask();
- auto& anima = tile.power.socket ? power_intake_ :
- tile.power.hub ? power_hub_ : power_grid_;
- anima.GoTo(frame);
- anima.RenderAt(where + vec2i{0, 1});
- subtiles[0] = ALREADY_DRAWN;
- if (tile.power.hub)
- {
- subtiles[1] = STAGE_6_POWER_HUB_RIGHT;
- subtiles[2] = STAGE_6_POWER_HUB_BOTTOM;
- }
- }
- if (!tile.data.is_empty())
- {
- uint frame = tile.data.connection_mask();
- auto& anima = tile.data.socket ? data_terminal_ :
- tile.data.hub ? data_hub_ : data_grid_;
- anima.GoTo(frame);
- anima.RenderAt(where + subtile_offset_by_index[3] + vec2i{0, 1});
- subtiles[3] = ALREADY_DRAWN;
- if (tile.data.hub)
- {
- subtiles[1] = STAGE_6_DATA_HUB_TOP;
- subtiles[2] = STAGE_6_DATA_HUB_LEFT;
- }
- }
- static constexpr uint random_subtiles[4] =
- {STAGE_6_RANDOM_0, STAGE_6_RANDOM_1, STAGE_6_RANDOM_2, STAGE_6_RANDOM_3};
- bool no_building = building_map_[at] == nullptr;
- for (uint i = 0; i < 4; ++i)
- {
- uint subtile = subtiles[i];
- if (subtile == ALREADY_DRAWN)
- continue;
- if (subtile == NOT_SET)
- {
- if (no_building)
- subtile = STAGE_6_RANDOM_3;
- else
- subtile = random_subtiles[random_[at].platform_inside_random_tile_2bit(i)];
- }
- subtiles_.GoTo(subtile);
- subtiles_.RenderAt(where + subtile_offset_by_index[i] + vec2i{0, 1});
- }
- }
- break;
- case 7: main_tile = STAGE_7; break;
- case 8:
- {
- // No need to draw under a building.
- // TODO Not anymore: Does not work correctly with the new mature border.
- if (building_map_[at])
- break;
- auto& random_tile = random_[at];
- auto other_part_at = at + step((direction_4_t)random_tile.platform_double_tile_part);
- if (random_tile.platform_use_double_tile
- && this->_unchecked_has_constructed(other_part_at)
- && !building_map_[other_part_at])
- {
- switch ((direction_4_t)random_tile.platform_double_tile_part)
- {
- case direction_4::North:
- main_tile = random_tile.platform_use_alternative_set() ? STAGE_8_BOTTOM_V1 : STAGE_8_BOTTOM_V0;
- tile_colour_variation_4bit = random_[other_part_at].grid_colour_variation_4bit();
- break;
- case direction_4::East:
- main_tile = random_tile.platform_use_alternative_set() ? STAGE_8_LEFT_V1 : STAGE_8_LEFT_V0;
- tile_colour_variation_4bit = random_[at].grid_colour_variation_4bit();
- break;
- case direction_4::South:
- main_tile = random_tile.platform_use_alternative_set() ? STAGE_8_TOP_V1 : STAGE_8_TOP_V0;
- tile_colour_variation_4bit = random_[at].grid_colour_variation_4bit();
- break;
- case direction_4::West:
- main_tile = random_tile.platform_use_alternative_set() ? STAGE_8_RIGHT_V1 : STAGE_8_RIGHT_V0;
- tile_colour_variation_4bit = random_[other_part_at].grid_colour_variation_4bit();
- break;
- }
- }
- else
- {
- main_tile = random_tile.platform_use_alternative_set() ? STAGE_8_SINGLE_V1 : STAGE_8_SINGLE_V0;
- tile_colour_variation_4bit = random_[at].grid_colour_variation_4bit();
- }
- if (tile.is_powered()/* || tile.is_powerable()*/)
- lights_tile = main_tile - STAGE_8_SINGLE_V0; // Corresponds to the zeroeth tile of lights.
- }
- break;
- default: break;
- }
- if (main_tile < UINT_MAX)
- {
- Sprite main = tiles_[main_tile];
- if (tile_colour_variation_4bit)
- {
- // 0..0x0F * 2 = 0..1E;
- // 0..0x0F * 3 = 0..2D;
- // 0..0x0F * 4 = 0..3C;
- uint8 grey = (uint8)(0xFF - *tile_colour_variation_4bit * 3);
- main.setColour(argb32::Grey(grey));
- }
- main.RenderAt(where);
- }
- if (lights_tile < UINT_MAX)
- {
- Sprite lights = lights_[lights_tile];
- lights.setAlpha(tile.is_powered() ? 0.75f : 0.25f); // TODO
- lights.RenderAt(where);
- }
- // TODO To be re-implemented as gamefield overlay.
- // if (tile.order == PlatformTile::Order::Construction
- // || (tile.order == PlatformTile::Order::None
- // && tile.state == PlatformTile::State::Construction))
- // {
- // tiles_.GoTo(CONSTRUCTION_LIGHTS);
- // tiles_.RenderAt(where);
- // }
- // else if (tile.order == PlatformTile::Order::Destruction
- // || (tile.order == PlatformTile::Order::None
- // && tile.state == PlatformTile::State::Destruction))
- // {
- // tiles_.GoTo(DESTRUCTION_LIGHTS);
- // tiles_.RenderAt(where);
- // }
- // if (tile.state == PlatformTile::State::Construction)
- // {
- // tiles_.GoTo(CONSTRUCTION_LIGHTS);
- // tiles_.RenderAt(where);
- // }
- // else if (tile.state == PlatformTile::State::Destruction)
- // {
- // tiles_.GoTo(DESTRUCTION_LIGHTS);
- // tiles_.RenderAt(where);
- // }
- }
- // Side borders (also for empty tiles).
- if (shown_stage < PLATFORM_MIN_STAGE_NO_SIDE_BORDERS)
- {
- int level_n = this->_unchecked_get_shown_level(at + STEP_NORTH);
- int level_for_corners = std::max(level_n, level_here);
- // Left.
- int level_nw = this->_unchecked_get_shown_level(at + STEP_NW);
- int level_w = this->_unchecked_get_shown_level(at + STEP_WEST);
- if (level_w > level_here)
- // if (!(allow_for_mature_borders && this->unchecked_has_mature(at + STEP_WEST)))
- {
- // A straight side sprite if got a vertical wall, rounded block (or two) otherwise.
- auto& anima = (level_nw == level_w && level_n <= level_here) ? sides_ : rounded_sides_;
- uint frame = (uint)(PLATFORM_TOTAL_LEVELS * level_w + level_here);
- anima.GoTo(frame);
- anima.RenderAt(where);
- }
- if (level_nw > level_for_corners && level_nw != level_w)
- // if (!(allow_for_mature_borders && this->unchecked_has_mature(at + STEP_NW)))
- {
- auto& anima = corners_;
- uint frame = (uint)(PLATFORM_TOTAL_LEVELS * level_nw + level_for_corners);
- anima.GoTo(frame);
- anima.RenderAt(where);
- }
- // Right.
- int level_ne = this->_unchecked_get_shown_level(at + STEP_NE);
- int level_e = this->_unchecked_get_shown_level(at + STEP_EAST);
- if (level_e > level_here)
- // if (!(allow_for_mature_borders && this->unchecked_has_mature(at + STEP_EAST)))
- {
- // A straight side sprite if got a vertical wall, rounded block (or two) otherwise.
- auto& anima = (level_ne == level_e && level_n <= level_here) ? sides_ : rounded_sides_;
- uint frame = (uint)(PLATFORM_TOTAL_LEVELS * level_here + level_e);
- anima.GoTo(frame);
- anima.RenderAt(where + vec2i{TILE_SIZE - 8, 0});
- }
- if (level_ne > level_for_corners && level_ne != level_e)
- // if (!(allow_for_mature_borders && this->unchecked_has_mature(at + STEP_NE)))
- {
- auto& anima = corners_;
- uint frame = (uint)(PLATFORM_TOTAL_LEVELS * level_for_corners + level_ne);
- anima.GoTo(frame);
- anima.RenderAt(where + vec2i{TILE_SIZE - 8, 0});
- }
- }
- // if (allows_for_mature_borders)
- // this->_render_mature_border(at, where);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement