Quick, dirty and ugly JavaScript tutorial for random generators (Part 4)

Random Generator Tutorial (part 4)

Quick, dirty and ugly JavaScript tutorial for random generators

Part 4

Welcome to the fourth part of my tutorial, you can find the first parte here, second part and third part here. Now we are going to repeat some of the initial advice of that part.

There are a lot of useful tools like Perchance and Chartopia available to create random generatos for your rpg but here we are going to make things old-school, tinkering with HTML and JavaScript.

You will need a basic knowledge of how a webpage is created using HTML and some minor programming experience in any programming language so you can grasp the JavaScript parts. The code and web page will be just as simple as possible and we'll try to avoid any advanced features (or even good modern practices).

Again we are going to do something new! We'll try to draw a random map.

And now for something completly different (bis)

There are several dungeon generatos that create beautiful maps like the incredible One Page Dungeon by Watabou or the ones in the donjon web.

We already know how to create tables to select the monster or treasures in it. So this time we'll focus on the map itself.

The idea is to generate a SVG image with our code and then draw rooms on it. A similar approach could be done using the HTML5 Canvas, but we will not cover it here.

First will start with a simple html page where we add the code for our little map parchment.

<!DOCTYPE html>
<html>
<head>
<title>My RPG Map Generator</title>
<script>
</script>
</head>
<body>
<h1>Ultimate Dungeon Map Generator</h1>
<p id="Random"> <svg width="640" height="320">
<rect x="5" y="5" width="630" height="310" style="stroke-width:1;fill:white;stroke:rgb(0,0,0)" /> </svg>
</p>
<button type="button" onclick="" >Run!</button>
</body>
</html>

We just added an SVG image with a rectangle in our HTML code as a example how we'll draw our dungeon. We are going to use a few rectanges starting from a give set of coordinates with length and wide values. The button is still disabled as we didn't have a proper function to generate things.

Ultimate Dungeon Map Generator

Before we start the code, we need to plan what we are going to generate. To keep it simple, lets say we are going to alternate rooms and corridors, with rooms sized as rectanges with 3x3 to 6x6 tiles and corridors with a length between 2 and 5 tiles. As expected our tiles are sized the standard 10'

The idea is to pick a corridor and room and repeat as long as we have space to draw it. Lets say we use 16 pixels per tile (variable named cs) and keep half tile as border around so we have 49x19 space! So we'll need to stop after reaching the tile 40 or more.

We need variables to keep count were we are going to put the next corridor after each iteration. And at last we'll also need a simple rectangle drawing function to draw our thing in our map.

var cs = 16;
function CreateRoom (x,y, w, h) {
 var RoomTxt = '<rect x="'+x+'" y="'+y+'" width="'+(w*cs)+'" height="'+(h*cs)+'" style="fill:white;stroke:black;stroke-width:2;" />';
 return RoomTxt;
};
function getDungeonMap () {
  var xTile = 1;
  var yTile = 10;
  var dungeon = "";
  var xW;
  var yH;
  while (xTile < 30) {
   xW = Math.floor( 2 + Math.random() * 4);
   yH = 1;
   dungeon = dungeon + CreateRoom(xTile*cs,yTile*cs,xW,yH);
   xTile = xTile + xW;
   xW = Math.floor( 4 + Math.random() * 3);
   yH = Math.floor( 4 + Math.random() * 3);
   yTile = yTile - yH + 1 + Math.floor( Math.random() * yH);
   dungeon = dungeon + CreateRoom(xTile*cs,yTile*cs,xW,yH);
   xTile = xTile + xW;
   yTile = yTile + Math.floor( Math.random() * yH);
  }
  document.getElementById("Random").innerHTML = ' <svg width="'+(640)+'" height="'+(20*cs)+'">' + dungeon + '</svg>';
}

Note the clever usage of " and ' to generate strings withing strings. We can use any of them to open our strings and the other inside safely to create our html code.

Ultimate Dungeon Map Generator

Now we have a very plain map, that sometimes gets a bit outside our boundaries. So will add nice dashed lines to split it in the 10'x10' tiles we all love and some clever use of maximum and minimun to keep our y coordinate safe.

var cs = 16;
function CreateRoom (x,y, w, h) {
 var RoomTxt = '<rect x="'+x+'" y="'+y+'" width="'+(w*cs)+'" height="'+(h*cs)+'" style="fill:white;stroke:black;stroke-width:2;" />';
 RoomTxt = RoomTxt + '<g stroke="black" stroke-width="1">';
 for (var i = 1; i < w; i++ ) {
  RoomTxt = RoomTxt + '<path stroke-dasharray="3,3" d="M'+(x+i*cs)+' '+y+' '+(x+i*cs)+' '+(y+h*cs)+'" />';
 };
 for (var i = 1; i < h; i++ ) {
  RoomTxt = RoomTxt + '<path stroke-dasharray="3,3" d="M'+(x)+' '+(y+i*cs)+' '+(x+w*cs)+' '+(y+i*cs)+'" />';
 };
 RoomTxt = RoomTxt + '</g>';
 return RoomTxt;
};
function getDungeonMap () {
  var xTile = 1;
  var yTile = 10;
  var dungeon = "";
  var xW;
  var yH;
  while (xTile < 30) {
   xW = Math.floor( 2 + Math.random() * 4);
   yH = 1;
   dungeon = dungeon + CreateRoom(xTile*cs,yTile*cs,xW,yH);
   xTile = xTile + xW;
   xW = Math.floor( 4 + Math.random() * 3);
   yH = Math.floor( 4 + Math.random() * 3);
   yTile = yTile - yH + 1 + Math.floor( Math.random() * yH);
   dungeon = dungeon + CreateRoom(xTile*cs,yTile*cs,xW,yH);
   xTile = xTile + xW;
   yTile = yTile + Math.floor( Math.random() * yH);
   yTile = Math.min(18,Math.max(2,yTile));
  }
  document.getElementById("Random").innerHTML = ' <svg width="'+(640)+'" height="'+(20*cs)+'">' + dungeon + '</svg>';
}

Ultimate Dungeon Map Generator

And for finishing touches we can add extra decor at the lines at the corners and you can try to add doors too.

var cs = 16;
function CreateRoom (x,y, w, h) {
 var RoomTxt = '<rect x="'+x+'" y="'+y+'" width="'+(w*cs)+'" height="'+(h*cs)+'" style="fill:white;stroke:black;stroke-width:2;" />';
 RoomTxt = RoomTxt + '<g stroke="black" stroke-width="1">';
 for (var i = 1; i < w; i++ ) {
  RoomTxt = RoomTxt + '<path stroke-dasharray="3,3" d="M'+(x+i*cs)+' '+y+' '+(x+i*cs)+' '+(y+h*cs)+'" />';
 };
 for (var i = 1; i < h; i++ ) {
  RoomTxt = RoomTxt + '<path stroke-dasharray="3,3" d="M'+(x)+' '+(y+i*cs)+' '+(x+w*cs)+' '+(y+i*cs)+'" />';
 };
 RoomTxt = RoomTxt + '</g>'+
  '<g fill="none" stroke="black" stroke-width="2">'+
  '<path d="M'+(x+4)+' '+(y+4)+' '+(x+10)+' '+(y+4)+'" />'+
  '<path d="M'+(x+4)+' '+(y+4)+' '+(x+4)+' '+(y+10)+'" />'+
  '<path d="M'+(x+w*cs-4)+' '+(y+4)+' '+(x+w*cs-10)+' '+(y+4)+'" />'+
  '<path d="M'+(x+w*cs-4)+' '+(y+4)+' '+(x+w*cs-4)+' '+(y+10)+'" />'+
  '<path d="M'+(x+4)+' '+(y+h*cs-4)+' '+(x+10)+' '+(y+h*cs-4)+'" />'+
  '<path d="M'+(x+4)+' '+(y+h*cs-4)+' '+(x+4)+' '+(y+h*cs-10)+'" />'+
  '<path d="M'+(x+w*cs-4)+' '+(y+h*cs-4)+' '+(x+w*cs-10)+' '+(y+h*cs-4)+'" />'+
  '<path d="M'+(x+w*cs-4)+' '+(y+h*cs-4)+' '+(x+w*cs-4)+' '+(y+h*cs-10)+'" />'+
  '</g>';
 return RoomTxt;
};

Ultimate Dungeon Map Generator

See you in part five!.

Comments

Post a Comment

Popular posts from this blog

Random Character Generator for Warhammer Rolepaying Game 4th edition

WFRP4 NPC Generator

Treasure Generator