UNPKG

rot-js

Version:

A roguelike toolkit in JavaScript

173 lines (137 loc) 5.23 kB
<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 = ROT.RNG.getItem(["#333", "#666", "#999", "#ccc", "#fff"]); display.draw(x, y, "&bull;", "#000", bg); } } </div> <p>If you <strong>absolutely</strong> need inverted hex layout ("flat-tops"), you can force transposed rendering by passing the <code>transpose:true</code> option to the <code>ROT.Display</code> constructor. Please note that this inverts the x-y values of all display-related functions and operations.</p> <div class="example"> var display = new ROT.Display({ width:10, height:4, spacing:2.5, layout:"hex", transpose:true }); SHOW(display.getContainer()); for (var y = 0; y &lt; 4; y++) { for (var x = y%2; x &lt; 10; x += 2) { var bg = ROT.RNG.getItem(["#333", "#666", "#999", "#ccc", "#fff"]); display.draw(x, y, 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&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); var W = 44; var H = 28; var display = new ROT.Display({fontSize:12, layout:"hex", width:W, height:H}); 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.4); map.create(function(x, y, value) { data[x+","+y] = value; display.DEBUG(x, y, value); }); /* input callback */ function lightPasses(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>