RuneScape Wiki
Advertisement

Documentation for this module may be created at Module:TileMap/doc

-- <pre>
-- IMPORTANT: This module should be considered UNSTABLE and not be used widely
-- until further testing/bugfixing
--[[----------------------------------------------------------------------------
	Module:TileMap
		Used to create a static map made up from tiles.

		This is a metamodule for use in other LUA modules, and should not be
		invoked. If you're looking for an invokable module, you probably want
		Module:CoordinateMap instead.

-- Usage -----------------------------------------------------------------------
	LUA FUNCTIONS:
		.create(left, top, width, height, mapid)
			left - leftmost X position the map should show
			top - topmost Y position the map should show
			width - width the map should be
			height - height the map should be
			mapdata - table of map data containing the following values:
				tilesx = total number of tiles horizontally
				tilesy = total number of tiles vertically
				tilewidth = width of each tile
				tileheight = height of each tile
				blanktiles = table of tiles which are solid color e.g. sea tiles
					e.g. {12,134,155}
				blankcolor = color of the blank tiles
				(See Module:CoordinateMap/data for examples)

		Returns a TileMap object with the following functions:
			:getTileCoords(x, y)
				x - x coord in pixels
				y - y coord in pixels
			Returns the local col,row of a map tile based on the pixel values

			:getTileId(x, y)
				x - x coordy (col) of tile
				y - y coordy (row) of tile
			Returns the id of the tile based on local x,y coords

			:isTileBlank(id)
				id - id of the tile
			Returns true if the tile is blank or out of bounds, false otherwise

		TileMap object also has the following properties:
			data = data loaded from Module:TileMap/data based on mapid
			width = width of map
			height = height of map
			xoffset = map's local X offset
			yoffset = map's local Y offset
			left = leftmost relevant tile column
			top = topmost relevant tile row
			right = rightmost relevant tile column
			bottom = bottommost relevant tile row
			container = map container
			map = inner map container

		Calling tostring() on a TileMap object will return the TileMap
		container's HTML.

		Examples:
			local TileMap = require('Module:TileMap')
			local tmap = TileMap.create(
				200, 400, --left, top
				500, 500, --width, height
				mapdata -- var containing map data
			)
			tmap.container:addClass('tright') -- align right
			return tmap -- return a 500x500 map of keldagrim starting at 200,400
			(See Module:CoordinateMap for a real example of this module in use)
----------------------------------------------------------------------------]]--

-- Private functions -----------------------------------------------------------
-- Convert S -> Spx
local function px(s)
	return string.format('%spx', tostring(s))
end

-- Public TileMap class --------------------------------------------------------
local TileMap = {}
TileMap.__index = TileMap

-- Constructor
function TileMap.create(left, top, width, height, mapdata)
	local self = setmetatable({}, TileMap)
	self.data = mapdata
	self.width = width
	self.height = height
	self.xoffset = -(left % self.data.tilewidth)
	self.yoffset = -(top % self.data.tileheight)
	self.left, self.top = self:getTileCoords(left, top)
	self.right, self.bottom =
		self:getTileCoords(left + self.width, top + self.height)
	self.container = mw.html.create('div')
		:addClass('tilemap-container')
		:css({
			['position'] = 'relative',
			['overflow'] = 'hidden',
			['background-color'] = '#000',
			['width'] = px(self.width),
			['height'] = px(self.height)
		})
	self.map = self.container:tag('div')
		:addClass('tilemap')
		:css({
			['position'] = 'absolute',
			['width'] = px((self.right - self.left + 1) * self.data.tilewidth),
			['left'] = px(self.xoffset),
			['top'] = px(self.yoffset)
		})
	-- Main loop
	for row = self.top, self.bottom do -- Loop through relevant rows
		for col = self.left, self.right do -- Loop through relevant columns
			if self:isTileBlank(col, row) then -- Tile is out of bounds/blank
				self.map:tag('div')
					:addClass('tilemap-spacer')
					:css({
						['display'] = 'inline-block',
						['vertical-align'] = 'middle',
						['background-color'] = self.data.blankcolor or 'black',
						['width'] = px(self.data.tilewidth),
						['height'] = px(self.data.tileheight)
					})
			else -- Tile is in bounds and not blank, add it
				self.map:wikitext(string.format(
					'[[File:%s %d.png|%dx%dpx|link=|alt=]]',
					self.data.name, self:getTileId(col, row),
					self.data.tilewidth, self.data.tileheight)
				)
			end
		end
	end
	return self
end

function TileMap:__tostring()
	return tostring(self.container)
end

-- Get tile coords from pixel coords
function TileMap:getTileCoords(x, y)
	return math.floor(x / self.data.tilewidth),
		math.floor(y / self.data.tileheight)
end

-- Get tile number from coords
function TileMap:getTileId(col, row)
	return (row * self.data.tilesx) + col
end

-- Is a tile blank?
function TileMap:isTileBlank(col, row)
	if row < 0 or col < 0 or
		row >= self.data.tilesy or col >= self.data.tilesx
	then
		return true
	end
	local id = self:getTileId(col, row)
	for _, v in ipairs(self.data.blanktiles) do
		if v == id then return true end
	end
	return false
end

return TileMap
Advertisement