Skip to content

Instantly share code, notes, and snippets.

@polm
Forked from anonymous/gist.html
Created November 11, 2011 09:42
Show Gist options
  • Save polm/1357620 to your computer and use it in GitHub Desktop.
Save polm/1357620 to your computer and use it in GitHub Desktop.
World Generator with d3

World Generator

This code creates a Voronoi Diagram of a low-resolution space, generating an approximation of regional divisions of an overworld map typical of the first Legend of Zelda or Link's Awakening. The white squares are randomly generated "centers".

http://en.wikipedia.org/wiki/Voronoi_diagram

<html>
<head>
<title>World Generator</title>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js"></script>
</head>
<body>
<div id="viz" ></div>
<script type="text/javascript">
function worldgen(x,y,bc){
//Initialize the array
var world = new Array(x);
for(i=0;i<world.length;i++){world[i]=new Array(y);}
//Generate some biomes!
var biomes = [ "G", "M", "B", "W", "F", "D", "S" ];
var centers = new Array(bc);
for(count=0; count<bc; count++){
var cx = parseInt(Math.random() * (x-1));
var cy = parseInt(Math.random() * (y-1));
//No overwriting
if (world[cx][cy] != null) {count--; continue;}
else {
var nb = biomes[parseInt(Math.random() * (biomes.length -1))];
world[cx][cy] = nb;
centers.push([cx, cy, world[cx][cy].toLowerCase()]);
}
}
//OK, that was the centers.
//Now to fill.
//Strategy:
//Pick a square.
//Find the closest center (capital letter).
//Fill all squares from the square in question to the capital letter with lowercase.
//continue to next blank square.
for(i=0;i<x;i++){
for(j=0;j<y;j++){
//We only modify empties
if(world[i][j] != null) continue;
//Find the closest center - n^2 but we don't care!
var mindist = x * y * 100;
centers.forEach(function(c){
var dist = Math.sqrt( Math.pow((c[0] - i),2) + Math.pow((c[1] - j),2));
if (dist < mindist){
mindist = dist;
world[i][j] = c[2];
}
});
}
}
//And output it!
var newworld = new Array(0);
for(i=0;i<x;i++){
var row = "";
for(j=0;j<y;j++){
row = row + world[i][j];
newworld.push([i, j, world[i][j]]);
}
console.log(row);
}
return newworld;
}
var map = worldgen(96, 50, 30);
var w = 960, h = 500;
var v = d3.select("#viz")
.append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("class", "wrapper");
v.selectAll("g.box").data(map).enter()
.append("svg:rect")
.attr("x", function(d){ return 10 * d[0];})
.attr("y", function(d){return 10 * d[1];})
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d){switch (d[2]){
case "w": return "blue";
case "f": return "darkgreen";
case "g": return "green";
case "b": return "orange";
case "d": return "yellow";
case "s": return "purple";
case "m": return "brown";
default: return "white";
}})
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment