[Cavity] Simple procedural cave building in Lua!

Showcase your libraries, tools and other projects that help your fellow love users.
Post Reply
User avatar
Lightcycler
Prole
Posts: 18
Joined: Sun Dec 16, 2012 4:31 pm

[Cavity] Simple procedural cave building in Lua!

Post by Lightcycler » Thu Dec 11, 2014 1:10 am

Hey folks,

the past days I've been working on a small script to build 2d tile based maps that look like caves. (Actually, it's been a few weeks, but only because one in retrospect friggin simple problem kept bugging around.)

UPDATES
What's new?
-one new function: cavity.forge(): which tiles touch the map? Good for memory savings, e.g. with collision detection. It's used automatically, if you don't want that you have to comment it out in the lib (line 362).
-improved cavity.sprinkle: add a counter to prevent an infinite loop.
-new feature: add a function to the initial noise to make new patterns
-new value: cavity.wallcount: the amout of wall on the map
-some bug fixes

Download:
cavity_new.love
0.0.2
(4.38 KiB) Downloaded 132 times
What can it do?
You hand it some arguments and it spits out a nice tilemap like this:

Code: Select all

map={
{cell1,cell2,cell3},
{cell4,cell5,cell6},
...
}
Of course, depending on the x/y input.
Careful: When you're reading the table, mind the y-coordinate is the first. The tile at (4/10) would be map[10][4].
The map consists of "space"-tiles and "wall"-tiles.
New: "fence"-tiles. Use them for collision detection and what not.

Code: Select all

if map[5][5] == cavity.space then print("Yay!") end
Functions
There are two main functions: cavity.makemap(...) and cavity.sprinkle(...).

cavity.makemap(args)
Returns: the map (e.g. "level = cavity.makemap(...)")
Args: width, height, lowest percentage of open space, amount of initial wall(44 or nil works best), random seed, growing iterations, smoothing iterations, noise function, start of noise func, end of noise func
If no args are handed in, cavity has built in some standard values, so you don't have to set the lets say smoothing iterations each time you make a map. In most cases, you can ignore anything beyond height.

Code: Select all

level = cavity.makemap(50,60,40,44,1337,2,3)
makes a 50 by 60 tiles map with at least 40% of free space. Initially, 44% of all tiles were walls. The seed is 1337 and the growing algorithm is called two times, while the smoothing algorithm is called three times.

NEW:

Code: Select all

genfunc = function(a) return math.pow(math.sin(a),2) end
startv = 0
endv = 2*math.pi

level = cavity.makemap(50,60,40,70,1337,2,3,genfunc,startv,endv)
makes a map with the same parameters as above, but the initial noise fluctuates.
Note: the function should stay between 0 and 1. Also, the "wallseed" value might be changed to get a nice result.

Image

Another example:

Code: Select all

genfunc = function(a) return math.exp(a) end
startv = -1
endv =0

level = cavity.makemap(50,60,40,60,1337,2,3,genfunc,startv,endv)
Image

cavity.sprinkle(args)
Returns: the amount of sprinkles. Not kidding. Also the amount of unchanged tiles.
Args: map, tiletype 1, tiletype 2, x, y, probability, list of tiles
This function takes tiletype 2 and sprinkles it everywhere where tiletype 1 is.
Let's say, we want 10 percent of our free space in "level" to be a coin.

Code: Select all

probability = cavity.roomcount*(10/100) -- 10 percent; cavity.roomcount is the number of non wall tiles.
coincount,cavity.roomcount = cavity.sprinkle(level,cavity.space,"coin",50,60,probability,cavity.roomcount)
probability is the amount of tiles we want to change, in this case 10% of all the space-tiles; 50 and 60 are the map-dimensions.
Now the function checks for every "space"-tile in "level" and changes it to "coin". Coincount is the amount of coins.
cavity.roomcount here makes sure you have enough tiles to sprinkle on.

Values
There are multiple values you can ask for.

cavity.roomcount
We had that one already. It's the amount of free tiles on the map.

cavity.room
The amount of all tiles. (Actually just x*y. But... It looks tidier in functions like this.)

cavity.wallcount
The amount of wall on the map.

cavity.seed
The seed the current map was made with. Nice if you want to reproduce a map later.

How does it work?
Cellular automaton. In the beginning, there was noise. And then the walls and the spaces grow. And then the script smooths them to look organic. Basically it checks the Moore-neighborhood and if there is enough surrounding wall, the current cell petrifies, otherwise it becomes free space. The growing and smoothing algorithms are quite similiar, both have just different parameters. (And since a few hours different approaches how they iterate through the map.)
Sadly, this can result in multiple little caves, so the third algorithm (which somehow made me chew my nerves sore) evaluates the area inside a cave and if this is smaller than the threshold (the third argument of makemap()), it looks if there are bigger ones. If not, the map is discarded and a new one is made. If the algorithm finds a suitable spot o' land, it settles down and makes everything else to wall, easy as that. This ensures that the whole accessible space is connected.

Can we have a picture?
Of course!
Image

Same map with sprinkles:
Image

How can we use this?
Do whatever you want with it. Sell it, eat it, bake it, snort it. Have fun!

How does the example work?
This generates a new map if you press return; press space to sprinkle tiles.

Please tell me what you think! I highly appreciate feedback.

Greetings :3
Attachments
cavity.love
(3.09 KiB) Downloaded 104 times
Last edited by Lightcycler on Fri Jan 16, 2015 6:46 pm, edited 4 times in total.

User avatar
undef
Party member
Posts: 438
Joined: Mon Jun 10, 2013 3:09 pm
Location: Berlin
Contact:

Re: [Cavity] Simple procedural cave building in Lua!

Post by undef » Fri Dec 12, 2014 1:50 pm

Works fine, well done. :)
twitter | steam | indieDB

Check out quadrant on Steam!

User avatar
Lightcycler
Prole
Posts: 18
Joined: Sun Dec 16, 2012 4:31 pm

Re: [Cavity] Simple procedural cave building in Lua!

Post by Lightcycler » Fri Dec 12, 2014 4:35 pm

Thank you ^^ I've updated it and improved some parts.

User avatar
drunken_thor
Citizen
Posts: 75
Joined: Wed Oct 01, 2014 12:14 am
Location: Toronto, Canada
Contact:

Re: [Cavity] Simple procedural cave building in Lua!

Post by drunken_thor » Fri Dec 12, 2014 7:56 pm

Really cool work, did you make this with anything in mind?
Light_world.lua for all your lighting needs
Github
twitter

User avatar
Lightcycler
Prole
Posts: 18
Joined: Sun Dec 16, 2012 4:31 pm

Re: [Cavity] Simple procedural cave building in Lua!

Post by Lightcycler » Fri Dec 12, 2014 11:57 pm

drunken_thor wrote:Really cool work, did you make this with anything in mind?
Thank you :3 Well, I needed a level generator for another project and I thought, hey, make it easy to use. :D

If y'all got some ideas for features, feel free to tell me ^^

Post Reply

Who is online

Users browsing this forum: No registered users and 13 guests