Exemple #1
0
/** A small helper function to initialize the terrain */
static void TgenSetTileHeight(TileIndex tile, int height)
{
	SetTileHeight(tile, height);

	/* Only clear the tiles within the map area. */
	if (IsInnerTile(tile)) {
		MakeClear(tile, CLEAR_GRASS, 3);
	}
}
Exemple #2
0
/**
 * Return the slope of a given tile inside the map.
 * @param tile Tile to compute slope of
 * @param h    If not \c NULL, pointer to storage of z height
 * @return Slope of the tile, except for the HALFTILE part
 */
Slope GetTileSlope(TileIndex tile, int *h)
{
	assert(tile < MapSize());

	if (!IsInnerTile(tile)) {
		if (h != NULL) *h = TileHeight(tile);
		return SLOPE_FLAT;
	}

	int hnorth = TileHeight(tile);                    // Height of the North corner.
	int hwest  = TileHeight(tile + TileDiffXY(1, 0)); // Height of the West corner.
	int heast  = TileHeight(tile + TileDiffXY(0, 1)); // Height of the East corner.
	int hsouth = TileHeight(tile + TileDiffXY(1, 1)); // Height of the South corner.

	return GetTileSlopeGivenHeight(hnorth, hwest, heast, hsouth, h);
}
Exemple #3
0
/**
 * Check if a given tile is flat
 * @param tile Tile to check
 * @param h If not \c NULL, pointer to storage of z height (only if tile is flat)
 * @return Whether the tile is flat
 */
bool IsTileFlat(TileIndex tile, int *h)
{
	assert(tile < MapSize());

	if (!IsInnerTile(tile)) {
		if (h != NULL) *h = TileHeight(tile);
		return true;
	}

	uint z = TileHeight(tile);
	if (TileHeight(tile + TileDiffXY(1, 0)) != z) return false;
	if (TileHeight(tile + TileDiffXY(0, 1)) != z) return false;
	if (TileHeight(tile + TileDiffXY(1, 1)) != z) return false;

	if (h != NULL) *h = z;
	return true;
}
Exemple #4
0
/**
 * Converts a given grayscale map to something that fits in OTTD map system
 * and create a map of that data.
 * @param img_width  the with of the image in pixels/tiles
 * @param img_height the height of the image in pixels/tiles
 * @param map        the input map
 */
static void GrayscaleToMapHeights(uint img_width, uint img_height, byte *map)
{
	/* Defines the detail of the aspect ratio (to avoid doubles) */
	const uint num_div = 16384;

	uint width, height;
	uint row, col;
	uint row_pad = 0, col_pad = 0;
	uint img_scale;
	uint img_row, img_col;
	TileIndex tile;

	/* Get map size and calculate scale and padding values */
	switch (_settings_game.game_creation.heightmap_rotation) {
		default: NOT_REACHED();
		case HM_COUNTER_CLOCKWISE:
			width   = MapSizeX();
			height  = MapSizeY();
			break;
		case HM_CLOCKWISE:
			width   = MapSizeY();
			height  = MapSizeX();
			break;
	}

	if ((img_width * num_div) / img_height > ((width * num_div) / height)) {
		/* Image is wider than map - center vertically */
		img_scale = (width * num_div) / img_width;
		row_pad = (1 + height - ((img_height * img_scale) / num_div)) / 2;
	} else {
		/* Image is taller than map - center horizontally */
		img_scale = (height * num_div) / img_height;
		col_pad = (1 + width - ((img_width * img_scale) / num_div)) / 2;
	}

	if (_settings_game.construction.freeform_edges) {
		for (uint x = 0; x < MapSizeX(); x++) MakeVoid(TileXY(x, 0));
		for (uint y = 0; y < MapSizeY(); y++) MakeVoid(TileXY(0, y));
	}

	/* Form the landscape */
	for (row = 0; row < height; row++) {
		for (col = 0; col < width; col++) {
			switch (_settings_game.game_creation.heightmap_rotation) {
				default: NOT_REACHED();
				case HM_COUNTER_CLOCKWISE: tile = TileXY(col, row); break;
				case HM_CLOCKWISE:         tile = TileXY(row, col); break;
			}

			/* Check if current tile is within the 1-pixel map edge or padding regions */
			if ((!_settings_game.construction.freeform_edges && DistanceFromEdge(tile) <= 1) ||
					(row < row_pad) || (row >= (height - row_pad - (_settings_game.construction.freeform_edges ? 0 : 1))) ||
					(col < col_pad) || (col >= (width  - col_pad - (_settings_game.construction.freeform_edges ? 0 : 1)))) {
				SetTileHeight(tile, 0);
			} else {
				/* Use nearest neighbour resizing to scale map data.
				 *  We rotate the map 45 degrees (counter)clockwise */
				img_row = (((row - row_pad) * num_div) / img_scale);
				switch (_settings_game.game_creation.heightmap_rotation) {
					default: NOT_REACHED();
					case HM_COUNTER_CLOCKWISE:
						img_col = (((width - 1 - col - col_pad) * num_div) / img_scale);
						break;
					case HM_CLOCKWISE:
						img_col = (((col - col_pad) * num_div) / img_scale);
						break;
				}

				assert(img_row < img_height);
				assert(img_col < img_width);

				uint heightmap_height = map[img_row * img_width + img_col];

				if (heightmap_height > 0) {
					/* 0 is sea level.
					 * Other grey scales are scaled evenly to the available height levels > 0.
					 * (The coastline is independent from the number of height levels) */
					heightmap_height = 1 + (heightmap_height - 1) * _settings_game.construction.max_heightlevel / 255;
				}

				SetTileHeight(tile, heightmap_height);
			}
			/* Only clear the tiles within the map area. */
			if (IsInnerTile(tile)) {
				MakeClear(tile, CLEAR_GRASS, 3);
			}
		}
	}
}