Spaces:
Running
Running
File size: 4,584 Bytes
87b3b3a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
<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:√3</code> – 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 < 5; y++) {
for (var x = y%2; x < 8; x += 2) {
display.draw(x, y, "•");
}
}
</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 < 5; y++) {
for (var x = y%2; x < 8; x += 2) {
var bg = ["#333", "#666", "#999", "#ccc", "#fff"].random();
display.draw(x, y, "•", "#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<w; i++) {
for (var j=0; j<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() < dist) { map.set(i, j, 1); }
}
}
/* generate four iterations, show the last one */
for (var i=4; i>=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>
|