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:&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>