Sun Apr 28, 2013 11:29 pm by Lamp
kaen wrote:Here's a usage guide for minefield.lua, which was a central component to my Bebop and Ricochet submissions to the Wild West design contest. It periodically spawns mines in specified zones, allowing you to create minefield(s) with respawning and randomly placed mines.
The levelgen was meant to be used
without needing to edit it at all. In fact many different levels can use the same script file in different ways by simply changing the arguments you pass to it. When you type the name of the levelgen into the editor, you can pass it "arguments" (i.e. options) by typing things after the name. The general form is:
- Code:
minefield.lua [time] [min_mines] [max_mines] [zones]
"time" is in milliseconds (thousandths of a second), and is the time between each spawned wave of mines. min_mines and max_mines are the inclusive bounds for the number of mines to spawn, and zones is a lua table of zone ids. If you wanted to spawn 1 to 3 mines every ten seconds in zones 1, 2, and 3, you would type:
- Code:
minefield.lua 10000 1 3 {1,2,3}
These are also the default values, so the above is the same as simply typing:
Finally, the first three arguments can be mathematical expressions (or actually any valid lua) that includes a variable "t" which represents the number of milliseconds since the level started. For example, to lay a number of mines (every second) between 0 and the number of seconds which has passed since the level started, you could use:
- Code:
minefield.lua 1000 0 t/1000
Bugs:
- Bitfighter uses spaces to parse arguments to levelgens, so you must not put spaces into your expressions or zone lists. Cram it all together, but put a single space between each argument
- It uses the rectangular extents of zones, so your 16-sided curvilinear minefield will actually behave like the smallest axis-aligned rectangle which contains it. (tl;dr: use rectangular zones)
minefield.lua:
- Code:
-- minefield.lua [interval] [min_mines] [max_mines] [mine_zones]
-- interval - time in milliseconds between mine spawns
-- min/max_mines - inclusive bounds for the number of mines to spawn
-- mine_zones - a table (array) of ids of zones which are minefields
--
-- interval and min/max mines are processed using 'evaluate' below for each
-- invocation of mineEvent. This allows you to express these values in terms of
-- 't', which is the number of milliseconds since the level was loaded. For
-- instance, "minefield.lua 1000 1 1+t/1000" will spawn upto as many mines as
-- the number of full seconds since the level was loaded
START_TIME = getMachineTime()
-- find the value of the string at time t
function evaluate(str)
return loadstring("t = " .. (getMachineTime() - START_TIME) .. " ; return " .. str)()
end
-- pick a random point within extents
function randomPoint(extents)
return point.new(math.random(extents.minX, extents.maxX), math.random(extents.minY, extents.maxY))
end
-- return a well-labeled table of extents
function getExtents(zone)
minX, minY, maxX, maxY = math.huge, math.huge, -math.huge, -math.huge
for index, p in pairs(zone:getGeom()) do
minX = math.min(minX, p.x)
minY = math.min(minY, p.y)
maxX = math.max(maxX, p.x)
maxY = math.max(maxY, p.y)
end
extents = {}
extents.minX = minX
extents.maxX = maxX
extents.minY = minY
extents.maxY = maxY
return extents
end
-- lay some mines in the minefields
function layMines()
-- for each minefield
for index, id in pairs(MINE_FIELDS) do
-- lay between min and max mines
for i = 1, math.random(MINE_MIN, evaluate(MINE_MAX)) do
mineField = levelgen:findObjectById(id)
-- only if the minefield exists
if mineField ~= nil then
p = randomPoint(getExtents(mineField))
mine = Mine.new(p)
levelgen:addItem(mine)
end
end
end
end
function mineEvent()
layMines()
Timer:scheduleOnce(mineEvent, math.max(100, evaluate(MINE_INTERVAL)))
end
MINE_INTERVAL = 10000
MINE_MIN = 1
MINE_MAX = 3
MINE_FIELDS = {1, 2, 3}
function main()
MINE_INTERVAL = arg[1] or MINE_INTERVAL
MINE_MIN = arg[2] or MINE_MIN
MINE_MAX = arg[3] or MINE_MAX
MINE_FIELDS = loadstring("return " .. (arg[4] or "false"))() or MINE_FIELDS
mineEvent()
end