Skip to content
Snippets Groups Projects
Commit 134aa9b8 authored by dg's avatar dg
Browse files

heightmaps

git-svn-id: http://svn.net-core.org/repos/t-engine4@254 51575b47-30f0-44d4-a5cc-537603b46e54
parent 18730ef9
No related branches found
No related tags found
No related merge requests found
require "engine.class"
--- Heightmap fractal generator
-- This can be used to create rooms, levels, world maps, whatever
module(..., package.seeall, class.make)
_M.max = 100000
_M.min = 0
--- Creates the fractal generator for the specified heightmap size
function _M:init(w, h, roughness)
self.w = w
self.h = h
self.roughness = roughness or 1.2
self.hmap = {}
print("Making heightmap", w, h)
-- Init the hmap to 0
for i = 1, w do
self.hmap[i] = {}
for j = 1, h do
self.hmap[i][j] = 0
end
end
end
--- Actually creates the heightmap
function _M:generate()
local rects = {}
-- Init the four corners
-- self.hmap[1][1] = rng.range(self.min, self.max / 10)
-- self.hmap[1][self.h] = rng.range(self.min, self.max / 10)
-- self.hmap[self.w][1] = rng.range(self.min, self.max / 10)
-- self.hmap[self.w][self.h] = rng.range(self.min, self.max / 10)
-- self.hmap[1][1] = rng.range(self.min, self.max)
-- self.hmap[1][self.h] = rng.range(self.min, self.max)
-- self.hmap[self.w][1] = rng.range(self.min, self.max)
-- self.hmap[self.w][self.h] = rng.range(self.min, self.max)
-- self.hmap[1][1] = 0
-- self.hmap[1][self.h] = 0
-- self.hmap[self.w][1] = 0
-- self.hmap[self.w][self.h] = 0
self.hmap[1][1] = self.max
self.hmap[1][self.h] = self.max
self.hmap[self.w][1] = self.max
self.hmap[self.w][self.h] = self.max
rects[#rects+1] = {1, 1, self.w, self.h, force_middle=0}
-- While we have subzones to handle, handle them
while #rects > 0 do
local r = table.remove(rects, 1)
-- print("Doing rect", r[1], r[2], "::", r[3], r[3])
local w = r[3] - r[1]
local h = r[4] - r[2]
if w > 1 or h > 1 then
local nw = math.floor(w / 2)
local nh = math.floor(h / 2)
-- Compute "displacement" random value
local d = (w + h) / (self.w + self.h) * self.roughness
d = (rng.range(0, self.max) - self.max / 2) * d
-- Compute middles
self.hmap[r[1] + nw][r[2]] = (self.hmap[r[1]][r[2]] + self.hmap[r[3]][r[2]]) / 2
self.hmap[r[1] + nw][r[4]] = (self.hmap[r[1]][r[4]] + self.hmap[r[3]][r[4]]) / 2
self.hmap[r[1]][r[2] + nh] = (self.hmap[r[1]][r[2]] + self.hmap[r[1]][r[4]]) / 2
self.hmap[r[3]][r[2] + nh] = (self.hmap[r[3]][r[2]] + self.hmap[r[3]][r[4]]) / 2
if r.force_middle then
self.hmap[r[1] + nw][r[2] + nh] = r.force_middle
else
self.hmap[r[1] + nw][r[2] + nh] = (self.hmap[r[1]][r[2]] + self.hmap[r[1]][r[4]] + self.hmap[r[3]][r[2]] + self.hmap[r[3]][r[4]]) / 4 + d
end
-- Assign new rects
if nw > 1 or nh > 1 then rects[#rects+1] = {r[1], r[2], r[1] + nw, r[2] + nh} end
if r[3] - r[1] - nw > 1 or nh > 1 then rects[#rects+1] = {r[1] + nw, r[2], r[3], r[2] + nh} end
if nw > 1 or r[4] - r[2] - nh > 1 then rects[#rects+1] = {r[1], r[2] + nh, r[1] + nw, r[4]} end
if r[3] - r[1] - nw > 1 or r[4] - r[2] - nh > 1 then rects[#rects+1] = {r[1] + nw, r[2] + nh, r[3], r[4]} end
end
end
return self.hmap
end
function _M:displayDebug(symbs)
symbs = symbs or "abcdefghijklmnopqrstwxyzABCDEFGHIJKLMNOPQRSTWXYZ"
print("Dispalying heightmap", self.w, self.h)
for j = 1, self.h do
local str = ""
for i = 1, self.w do
local c = util.bound((math.floor(self.hmap[i][j] / self.max * symbs:len()) + 1), 1, symbs:len())
str = str..symbs:sub(c, c)
end
print(str)
end
end
......@@ -34,6 +34,12 @@ function _M:loadRoom(file)
local ret, err = f()
if not ret and err then error(err) end
-- We got a room generator function, save it for later
if type(ret) == "function" then
print("loaded room generator",file,ret)
return ret
end
-- Init the room with name and size
local t = { name=file, w=ret[1]:len(), h=#ret }
......@@ -64,6 +70,10 @@ end
--- Make up a room
function _M:roomAlloc(room, id)
if type(room) == 'function' then
print("room generator", room, "is making a room")
room = room(self, id)
end
print("alloc", room.name)
local tries = 100
......@@ -82,19 +92,23 @@ function _M:roomAlloc(room, id)
if ok then
local is_lit = rng.percent(self.data.lite_room_chance)
-- ok alloc it
for i = 1, room.w do
for j = 1, room.h do
self.room_map[i-1+x][j-1+y].room = id
local c = room[i][j]
if c == '!' then
self.room_map[i-1+x][j-1+y].room = nil
self.room_map[i-1+x][j-1+y].can_open = true
self.map(i-1+x, j-1+y, Map.TERRAIN, self.grid_list[self:resolve('#')])
else
self.map(i-1+x, j-1+y, Map.TERRAIN, self.grid_list[self:resolve(c)])
-- ok alloc it using the default generator or a specific one
if room.generator then
room:generator(x, y, is_lit)
else
for i = 1, room.w do
for j = 1, room.h do
self.room_map[i-1+x][j-1+y].room = id
local c = room[i][j]
if c == '!' then
self.room_map[i-1+x][j-1+y].room = nil
self.room_map[i-1+x][j-1+y].can_open = true
self.map(i-1+x, j-1+y, Map.TERRAIN, self.grid_list[self:resolve('#')])
else
self.map(i-1+x, j-1+y, Map.TERRAIN, self.grid_list[self:resolve(c)])
end
if is_lit then self.map.lites(i-1+x, j-1+y, true) end
end
if is_lit then self.map.lites(i-1+x, j-1+y, true) end
end
end
print("room allocated at", x, y,"with center",math.floor(x+(room.w-1)/2), math.floor(y+(room.h-1)/2))
......
......@@ -48,6 +48,15 @@ key:setCurrent()
-- Load the game module
game = false
require "engine.Heightmap"
do
local f = engine.Heightmap.new(10,10,3.5)
f:generate()
f:displayDebug(" #")
os.exit()
end
engine.Game:setResolution(config.settings.window.size)
util.showMainMenu()
return function(gen, id)
local w = rng.range(5, 12)
local h = rng.range(5, 12)
return { name="forest_clearing"..w.."x"..h, w=w, h=h, generator = function(self, x, y, is_lit)
for i = 1, self.w do
for j = 1, self.h do
if i == 1 or i == self.w or j == 1 or j == self.h then
gen.room_map[i-1+x][j-1+y].can_open = true
gen.map(i-1+x, j-1+y, Map.TERRAIN, gen.grid_list[gen:resolve('#')])
else
gen.room_map[i-1+x][j-1+y].room = id
gen.map(i-1+x, j-1+y, Map.TERRAIN, gen.grid_list[gen:resolve('.')])
end
if is_lit then gen.map.lites(i-1+x, j-1+y, true) end
end
end
end}
end
--[[
return function(self, gen)
return { name=self.name, w = rng.range(6, 15), h = rng.range(6, 15), generator = function(self, gen, x, y, id)
return function(gen, id)
local w = rng.range(5, 12)
local h = rng.range(5, 12)
return { name="simple"..w.."x"..h, w=w, h=h, generator = function(self, x, y, is_lit)
for i = 1, self.w do
for j = 1, self.h do
gen.room_map[i-1+x][j-1+y].room = id
if i == 1 or i == self.w or j == 1 or j == self.h then
gen.room_map[i-1+x][j-1+y].can_open = true
gen.map(i-1+x, j-1+y, Map.TERRAIN, gen.grid_list[gen:resolve('#')])
else
gen.room_map[i-1+x][j-1+y].room = id
gen.map(i-1+x, j-1+y, Map.TERRAIN, gen.grid_list[gen:resolve('.')])
end
if is_lit then gen.map.lites(i-1+x, j-1+y, true) end
end
end
end}
end
-- ]]
-- [=[
return {
[[#!!!!!!!!!!#]],
[[!..........!]],
[[!..........!]],
[[!..........!]],
[[!..........!]],
[[!..........!]],
[[#!!!!!!!!!!#]],
}
-- ]=]
......@@ -11,6 +11,7 @@ return {
map = {
class = "engine.generator.map.Roomer",
nb_rooms = 10,
edge_entrances = {6,4},
rooms = {"simple", "pilar"},
['.'] = "GRASS_DARK1",
['#'] = "TREE_DARK1",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment