Forked from
tome / Tales of MajEyal
14975 commits behind the upstream repository.
-
dg authored
git-svn-id: http://svn.net-core.org/repos/t-engine4@129 51575b47-30f0-44d4-a5cc-537603b46e54
dg authoredgit-svn-id: http://svn.net-core.org/repos/t-engine4@129 51575b47-30f0-44d4-a5cc-537603b46e54
TileSet.lua 4.60 KiB
require "engine.class"
local Map = require "engine.Map"
require "engine.Generator"
module(..., package.seeall, class.inherit(engine.Generator))
function _M:init(map, grid_list, data)
engine.Generator.init(self, map)
self.data = data
self.grid_list = grid_list
self.tiles, self.raw = self:loadTiles(data.tileset)
self.block = self.raw.base
self.cols = math.floor(self.map.w / self.block.w)
self.rows = math.floor(self.map.h / self.block.h)
self.room_map = {}
for i = 0, self.cols do
self.room_map[i] = {}
for j = 0, self.rows do
self.room_map[i][j] = false
end
end
end
function _M:loadTiles(tileset)
local f = loadfile("/data/tilesets/"..tileset..".lua")
local d = {}
setfenv(f, d)
local ret, err = f()
if not ret and err then error(err) end
local tiles = {}
for idx, ts in ipairs(d.tiles) do
local t = { id=idx, openings={} }
tiles[idx] = t
for j, line in ipairs(ts) do
local i = 1
for c in line:gmatch(".") do
t[i] = t[i] or {}
t[i][j] = c
-- Find edge openings
local mx, my = line:len(), #ts
if c == '.' and (i == 1 or i == mx or j == 1 or j == my) then
if i == 1 and j == 1 then
table.insert(t.openings, {i, j, 7})
elseif i == 1 and j == my then
table.insert(t.openings, {i, j, 1})
elseif i == mx and j == my then
table.insert(t.openings, {i, j, 3})
elseif i == mx and j == 1 then
table.insert(t.openings, {i, j, 9})
elseif i == 1 then
table.insert(t.openings, {i, j, 4})
elseif i == mx then
table.insert(t.openings, {i, j, 6})
elseif j == 1 then
table.insert(t.openings, {i, j, 8})
elseif j == my then
table.insert(t.openings, {i, j, 2})
end
end
i = i + 1
end
end
end
return tiles, d
end
function _M:roomAlloc(bx, by, bw, bh, rid)
print("trying room at", bx,by,bw,bh)
if bx + bw - 1 > self.cols or by + bh - 1 > self.rows then return false end
if bx < 0 or by < 0 then return false end
-- Do we stomp ?
for i = bx, bx + bw - 1 do
for j = by, by + bh - 1 do
if self.room_map[i][j] then return false end
end
end
-- ok alloc it
for i = bx, bx + bw - 1 do
for j = by, by + bh - 1 do
self.room_map[i][j] = true
end
end
print("room allocated at", bx,by,bw,bh)
return true
end
function _M:matchTile(t1, t2)
return self.raw.matcher(t1, t2)
end
function _M:findMatchingTiles(st, dir)
local m = {}
for _, dt in ipairs(self.tiles) do
local ok = true
if dir == 8 then
for i = 1, self.block.w do
if not self:matchTile(st[i][1], dt[i][self.block.h]) then ok = false end
end
elseif dir == 2 then
for i = 1, self.block.w do
if not self:matchTile(st[i][self.block.h], dt[i][1]) then ok = false end
end
elseif dir == 4 then
for j = 1, self.block.h do
if not self:matchTile(st[1][j], dt[self.block.w][j]) then ok = false end
end
elseif dir == 6 then
for j = 1, self.block.h do
if not self:matchTile(st[self.block.w][j], dt[1][j]) then ok = false end
end
end
if ok then
m[#m+1] = dt
print("found matching tile in dir", dir, "from", st.id, "to", dt.id)
end
end
return m
end
function _M:resolve(c)
local res = self.data[c]
if type(res) == "function" then
return res()
elseif type(res) == "table" then
return res[rng.range(1, #res)]
else
return res
end
end
function _M:buildTile(tile, bx, by, rid)
local bw, bh = 1, 1
if not self:roomAlloc(bx, by, bw, bh, rid) then return false end
for i = 1, self.block.w do
for j = 1, self.block.h do
self.map(bx * self.block.w + i - 1, by * self.block.h + j - 1, Map.TERRAIN, self.grid_list[self:resolve(tile[i][j])])
end
end
local opens = {}
for i, o in ipairs(tile.openings) do
local coord = dir_to_coord[o[3]]
local mts = self:findMatchingTiles(tile, o[3])
opens[#opens+1] = {bx + coord[1], by + coord[2], tile=mts[rng.range(1, #mts)]}
print("room at ",bx,by,"opens to",o[3],"::",bx + coord[1], by + coord[2])
end
return opens
end
function _M:generate()
for i = 0, self.map.w - 1 do for j = 0, self.map.h - 1 do
self.map(i, j, Map.TERRAIN, self.grid_list[self:resolve("#")])
end end
local first = true
local process = {}
local id = 1
process[#process+1] = {math.floor(self.cols / 2), math.floor(self.rows / 2), tile=self.tiles[rng.range(1, #self.tiles)]}
while #process > 0 do
local b = table.remove(process)
local type = "room"
if not first and rng.percent(70) then type = "tunnel" end
first = false
local opens = self:buildTile(b.tile, b[1], b[2], id)
if opens then
id = id + 1
-- Add openings
for i, o in ipairs(opens) do process[#process+1] = o end
end
end
-- Always starts at 1, 1
self.map(1, 1, Map.TERRAIN, self.up)
return 1, 1
end