(svn r11263) -Codechange: Reduce code duplication between DrawBridgePillars and HasFoundation{NW|NE}. Patch by frosch.

This commit is contained in:
rubidium 2007-10-14 20:16:44 +00:00
parent 64a6d3daad
commit 69605afdf2
3 changed files with 90 additions and 43 deletions

View File

@ -206,6 +206,32 @@ uint GetSlopeZ(int x, int y)
return _tile_type_procs[GetTileType(tile)]->get_slope_z_proc(tile, x, y);
}
/**
* Determine the Z height of the corners of a specific tile edge
*
* @pre z1 and z2 must be initialized (typ. with TileZ). The corner heights just get added.
*
* @param tileh The slope of the tile.
* @param edge The edge of interest.
* @param z1 Gets incremented by the height of the first corner of the edge. (near corner wrt. the camera)
* @param z2 Gets incremented by the height of the second corner of the edge. (far corner wrt. the camera)
*/
void GetSlopeZOnEdge(Slope tileh, DiagDirection edge, int *z1, int *z2)
{
static const Slope corners[4][4] = {
/* corner | steep slope
* z1 z2 | z1 z2 */
{SLOPE_E, SLOPE_N, SLOPE_STEEP_E, SLOPE_STEEP_N}, // DIAGDIR_NE, z1 = E, z2 = N
{SLOPE_S, SLOPE_E, SLOPE_STEEP_S, SLOPE_STEEP_E}, // DIAGDIR_SE, z1 = S, z2 = E
{SLOPE_S, SLOPE_W, SLOPE_STEEP_S, SLOPE_STEEP_W}, // DIAGDIR_SW, z1 = S, z2 = W
{SLOPE_W, SLOPE_N, SLOPE_STEEP_W, SLOPE_STEEP_N}, // DIAGDIR_NW, z1 = W, z2 = N
};
if ((tileh & corners[edge][0]) != 0) *z1 += TILE_HEIGHT; // z1 is raised
if ((tileh & corners[edge][1]) != 0) *z2 += TILE_HEIGHT; // z2 is raised
if (tileh == corners[edge][2]) *z1 += TILE_HEIGHT; // z1 is highest corner of a steep slope
if (tileh == corners[edge][3]) *z2 += TILE_HEIGHT; // z2 is highest corner of a steep slope
}
static Slope GetFoundationSlope(TileIndex tile, uint* z)
{
@ -219,32 +245,34 @@ static Slope GetFoundationSlope(TileIndex tile, uint* z)
static bool HasFoundationNW(TileIndex tile, Slope slope_here, uint z_here)
{
uint z;
Slope slope = GetFoundationSlope(TILE_ADDXY(tile, 0, -1), &z);
return
(
z_here + (slope_here & SLOPE_N ? TILE_HEIGHT : 0) + (slope_here == SLOPE_STEEP_N ? TILE_HEIGHT : 0) >
z + (slope & SLOPE_E ? TILE_HEIGHT : 0) + (slope == SLOPE_STEEP_E ? TILE_HEIGHT : 0)
) || (
z_here + (slope_here & SLOPE_W ? TILE_HEIGHT : 0) + (slope_here == SLOPE_STEEP_W ? TILE_HEIGHT : 0) >
z + (slope & SLOPE_S ? TILE_HEIGHT : 0) + (slope == SLOPE_STEEP_S ? TILE_HEIGHT : 0)
);
int z_W_here = z_here;
int z_N_here = z_here;
GetSlopeZOnEdge(slope_here, DIAGDIR_NW, &z_W_here, &z_N_here);
Slope slope = GetFoundationSlope(TILE_ADDXY(tile, 0, -1), &z);
int z_W = z;
int z_N = z;
GetSlopeZOnEdge(slope, DIAGDIR_SE, &z_W, &z_N);
return (z_N_here > z_N) || (z_W_here > z_W);
}
static bool HasFoundationNE(TileIndex tile, Slope slope_here, uint z_here)
{
uint z;
Slope slope = GetFoundationSlope(TILE_ADDXY(tile, -1, 0), &z);
return
(
z_here + (slope_here & SLOPE_N ? TILE_HEIGHT : 0) + (slope_here == SLOPE_STEEP_N ? TILE_HEIGHT : 0) >
z + (slope & SLOPE_W ? TILE_HEIGHT : 0) + (slope == SLOPE_STEEP_W ? TILE_HEIGHT : 0)
) || (
z_here + (slope_here & SLOPE_E ? TILE_HEIGHT : 0) + (slope_here == SLOPE_STEEP_E ? TILE_HEIGHT : 0) >
z + (slope & SLOPE_S ? TILE_HEIGHT : 0) + (slope == SLOPE_STEEP_S ? TILE_HEIGHT : 0)
);
int z_E_here = z_here;
int z_N_here = z_here;
GetSlopeZOnEdge(slope_here, DIAGDIR_NE, &z_E_here, &z_N_here);
Slope slope = GetFoundationSlope(TILE_ADDXY(tile, -1, 0), &z);
int z_E = z;
int z_N = z;
GetSlopeZOnEdge(slope, DIAGDIR_SW, &z_E, &z_N);
return (z_N_here > z_N) || (z_E_here > z_E);
}

View File

@ -25,6 +25,7 @@ bool IsValidTile(TileIndex tile);
uint GetPartialZ(int x, int y, Slope corners);
uint GetSlopeZ(int x, int y);
void GetSlopeZOnEdge(Slope tileh, DiagDirection edge, int *z1, int *z2);
static inline Point RemapCoords(int x, int y, int z)
{

View File

@ -812,41 +812,59 @@ CommandCost DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec
}
static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo* ti, Axis axis, uint type, int x, int y, int z)
/**
* Draws the pillars under high bridges.
*
* @param psid Image and palette of a bridge pillar.
* @param ti #TileInfo of current bridge-middle-tile.
* @param axis Orientation of bridge.
* @param type Bridge type.
* @param x Sprite X position of front pillar.
* @param y Sprite Y position of front pillar.
* @param z_bridge Absolute height of bridge bottom.
*/
static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo* ti, Axis axis, uint type, int x, int y, int z_bridge)
{
SpriteID image = psid->sprite;
if (image != 0) {
bool drawfarpillar = !HASBIT(GetBridgeFlags(type), 0);
int back_height, front_height;
int i = z;
const byte *p;
static const byte _tileh_bits[4][8] = {
{ 2, 1, 8, 4, 16, 2, 0, 9 },
{ 1, 8, 4, 2, 2, 16, 9, 0 },
{ 4, 8, 1, 2, 16, 2, 0, 9 },
{ 2, 4, 8, 1, 2, 16, 9, 0 }
};
/* "side" specifies the side the pillars stand on.
* The length of the pillars is then set to the height of the bridge over the corners of this edge.
*
* axis==AXIS_X axis==AXIS_Y
* side==false SW NW
* side==true NE SE
*
* I have no clue, why this was done this way.
*/
bool side = HASBIT(image, 0);
p = _tileh_bits[(image & 1) * 2 + (axis == AXIS_X ? 0 : 1)];
front_height = ti->z + (ti->tileh & p[0] ? TILE_HEIGHT : 0);
back_height = ti->z + (ti->tileh & p[1] ? TILE_HEIGHT : 0);
/* "dir" means the edge the pillars stand on */
DiagDirection dir = AxisToDiagDir(axis);
if (side != (axis == AXIS_Y)) dir = ReverseDiagDir(dir);
if (IsSteepSlope(ti->tileh)) {
if (!(ti->tileh & p[2])) front_height += TILE_HEIGHT;
if (!(ti->tileh & p[3])) back_height += TILE_HEIGHT;
}
/* Determine ground height under pillars */
int front_height = ti->z;
int back_height = ti->z;
GetSlopeZOnEdge(ti->tileh, dir, &front_height, &back_height);
for (; z >= front_height || z >= back_height; z -= TILE_HEIGHT) {
/* HACK set height of the BB of pillars to 1, because the origin of the
* sprites is at the top
*/
if (z >= front_height) { // front facing pillar
AddSortableSpriteToDraw(image, psid->pal, x, y, p[4], p[5], BB_HEIGHT_UNDER_BRIDGE - 5, z, HASBIT(_transparent_opt, TO_BRIDGES), 0, 0, -5);
/* x and y size of bounding-box of pillars */
int w = (axis == AXIS_X ? 16 : 2);
int h = (axis == AXIS_X ? 2 : 16);
/* sprite position of back facing pillar */
int x_back = x - (axis == AXIS_X ? 0 : 9);
int y_back = y - (axis == AXIS_X ? 9 : 0);
for (int cur_z = z_bridge; cur_z >= front_height || cur_z >= back_height; cur_z -= TILE_HEIGHT) {
/* Draw front facing pillar */
if (cur_z >= front_height) {
AddSortableSpriteToDraw(image, psid->pal, x, y, w, h, BB_HEIGHT_UNDER_BRIDGE - 5, cur_z, HASBIT(_transparent_opt, TO_BRIDGES), 0, 0, -5);
}
if (drawfarpillar && z >= back_height && z < i - TILE_HEIGHT) { // back facing pillar
AddSortableSpriteToDraw(image, psid->pal, x - p[6], y - p[7], p[4], p[5], BB_HEIGHT_UNDER_BRIDGE - 5, z, HASBIT(_transparent_opt, TO_BRIDGES), 0, 0, -5);
/* Draw back facing pillar, but not the highest part directly under the bridge-floor */
if (drawfarpillar && cur_z >= back_height && cur_z < z_bridge - TILE_HEIGHT) {
AddSortableSpriteToDraw(image, psid->pal, x_back, y_back, w, h, BB_HEIGHT_UNDER_BRIDGE - 5, cur_z, HASBIT(_transparent_opt, TO_BRIDGES), 0, 0, -5);
}
}
}