lychees's picture
Upload 569 files
87b3b3a
<h2>Hex support</h2>
<p>Hexagonal cell layout is supported in several parts of the toolkit, most notably in <a href="#display">Console display</a>, <a href="#map/cellular">Cellular generator</a>, <a href="#fov">FOV</a> and <a href="#path">Pathfinding</a>. This page explains how to uses hexes with rot.js.</p>
<p>While hexagonal cells provide several advantages over the traditional square/rectangular topologies, there is one big complication associated with their usage: there is no canonical way to index individual hexes. A <a href="#hex/indexing">hexagonal indexing comparison</a> document is available for reference; rot.js is using the third variant, called <em>double width</em>.
<h3>Displaying hexes</h3>
<p>There is a very trivial trick to display a rudimentary hexagonal layout: skip even/odd cells in odd/even rows. No special adjustments are necessary. The result will look good as long as the font aspect ratio is close to <code>1:&radic;3</code> &ndash; which is the case for most monospaced fonts.</p>
<div class="example">
var display = new ROT.Display({width:8, height:5});
SHOW(display.getContainer());
for (var y = 0; y &lt; 5; y++) {
for (var x = y%2; x &lt; 8; x += 2) {
display.draw(x, y, "&bull;");
}
}
</div>
<p>For more advanced hexagonal stuff, switch the display to "hex" layout. This has the following advantages:</p>
<ul>
<li>Precisely computed positioning</li>
<li>Filled background hexes</li>
</ul>
<div class="example">
var display = new ROT.Display({width:8, height:5, layout:"hex"});
SHOW(display.getContainer());
for (var y = 0; y &lt; 5; y++) {
for (var x = y%2; x &lt; 8; x += 2) {
var bg = ["#333", "#666", "#999", "#ccc", "#fff"].random();
display.draw(x, y, "&bull;", "#000", bg);
}
}
</div>
<h2>Cellular dungeon generator</h2>
<p>Pass the <code>topology:6</code> option to the <code>ROT.Map.Cellular</code> constructor to operate in hexagonal mode.</p>
<div class="example">
var w = 100, h = 50;
var display = new ROT.Display({width:w, height:h, fontSize:10, layout:"hex"});
SHOW(display.getContainer());
/* hexagonal map and rules */
var map = new ROT.Map.Cellular(w, h, {
topology: 6,
born: [4, 5, 6],
survive: [3, 4, 5, 6]
});
/* initialize with irregularly random values */
for (var i=0; i&lt;w; i++) {
for (var j=0; j&lt;h; j++) {
var dx = i/w - 0.5;
var dy = j/h - 0.5;
var dist = Math.pow(dx*dx+dy*dy, 0.3);
if (ROT.RNG.getUniform() &lt; dist) { map.set(i, j, 1); }
}
}
/* generate four iterations, show the last one */
for (var i=4; i&gt;=0; i--) {
map.create(i ? null : display.DEBUG);
}
</div>
<h2>Pathfinding</h2>
<p>All pathfinding algorithms accept the <code>topology:6</code> option as well.</p>
<div class="example">
var w = 150, h = 80;
ROT.RNG.setSeed(12345);
var display = new ROT.Display({width:w, height:h, fontSize:6, layout:"hex"});
SHOW(display.getContainer());
/* generate map and store its data */
var data = {};
var map = new ROT.Map.Cellular(w, h, {
topology: 6,
born: [4, 5, 6],
survive: [3, 4, 5, 6]
});
map.randomize(0.48);
map.create(); /* two iterations */
map.create(function(x, y, value) {
data[x+","+y] = value;
display.DEBUG(x, y, value);
});
/* input callback informs about map structure */
var passableCallback = function(x, y) {
return (data[x+","+y] === 0);
}
/* prepare path to given coords */
var dijkstra = new ROT.Path.Dijkstra(120, 64, passableCallback, {topology:6});
/* compute from given coords */
dijkstra.compute(30, 16, function(x, y) {
display.draw(x, y, "", "", "#800");
});
/* highlight */
display.draw(30, 16, "", "", "#3f3");
display.draw(120, 64, "", "", "#f33");
</div>
<h3>Field of View</h3>
<p>Precise Shadowcasting works in hexagonal topology as well.</p>
<div class="example">
ROT.RNG.setSeed(12345);
ROT.DEFAULT_WIDTH = 44;
ROT.DEFAULT_HEIGHT = 28;
var display = new ROT.Display({fontSize:12, layout:"hex"});
SHOW(display.getContainer());
/* generate map and store its data */
var data = {};
var map = new ROT.Map.Cellular(null, null, {
topology: 6,
born: [4, 5, 6],
survive: [3, 4, 5, 6]
});
map.randomize(0.4);
map.create(function(x, y, value) {
data[x+","+y] = value;
display.DEBUG(x, y, value);
});
/* input callback */
var lightPasses = function(x, y) {
var key = x+","+y;
if (key in data) { return (data[key] == 0); }
return false;
}
var fov = new ROT.FOV.PreciseShadowcasting(lightPasses, {topology:6});
/* output callback */
fov.compute(20, 14, 6, function(x, y, r, vis) {
var ch = (r ? "" : "@");
var color = (data[x+","+y] ? "#aa0": "#660");
display.draw(x, y, ch, "#fff", color);
});
</div>