File size: 3,185 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
<h2>Global lighting</h2>

<p>Lighting module is one of the most convoluted parts of <code>rot.js</code>: it is a mix of various concepts introduced in simpler components. <code>ROT.Lighting</code> is used to compute how multiple light sources mix and reflect in a cellular map (using a highly simplified radiosity-like algorithm).</p>

<p>To compute a lighting, you need the following:</p>
<ul>
	<li>a <code>ROT.FOV</code> instance, which is used to compute the areas lit by light sources;</li>
	<li>a <code>lightingCallback</code> which notifies you about the resulting light for a given coordinates;</li>
	<li>a set of lights, defined by their position (x, y) and color.</li>
</ul>

<p>If you decide to use a <em>two-pass</em> lighting (more light, more realistic light spread, more computation time), you also need:</p>
<ul>
	<li>a <code>reflectivityCallback</code> which is used to return how much individual map cells reflect incoming light. Please note that wall cells should not reflect any light for the purpose of lighting computation.</li>
</ul>

<p>Finally, the <code>ROT.Lighting</code> function accepts an optional configuration object as its second argument. This object may contain:</p>
<ul>
	<li><code>range</code> &ndash; maximum range for the most powerful light source</li>
	<li><code>passes</code> &ndash; number of computation passes (1: no reflectivity used, 2: reflectivity used)</li>
	<li><code>emissionThreshold</code> &ndash; minimal amount of light at a cell to be re-emited (only for passes>1)</li>
</ul>

<div class="example">
ROT.RNG.setSeed(12345);

ROT.DEFAULT_WIDTH = 60;
ROT.DEFAULT_HEIGHT = 40;
var mapData = {};
var lightData = {};

/* build a map */
var map = new ROT.Map.Cellular().randomize(0.5);
var createCallback = function(x, y, value) {
	mapData[x+","+y] = value;
}
for (var i=0; i&lt;4; i++) { 
	map.create(createCallback);
}

/* prepare a FOV algorithm */
var lightPasses = function(x, y) { 
	return (mapData[x+","+y] == 1);
}
var fov = new ROT.FOV.PreciseShadowcasting(lightPasses, {topology:4});

/* prepare a lighting algorithm */
var reflectivity = function(x, y) {
	return (mapData[x+","+y] == 1 ? 0.3 : 0);
}
var lighting = new ROT.Lighting(reflectivity, {range:12, passes:2});
lighting.setFOV(fov);
lighting.setLight(12, 12, [240, 240, 30]);
lighting.setLight(20, 20, [240, 60, 60]);
lighting.setLight(45, 25, [200, 200, 200]);

var lightingCallback = function(x, y, color) {
	lightData[x+","+y] = color;
}
lighting.compute(lightingCallback);

/* draw the resulting mix of mapData and lightData */
var display = new ROT.Display({fontSize:8});
SHOW(display.getContainer());

/* all cells are lit by ambient light; some are also lit by light sources */
var ambientLight = [100, 100, 100];
for (var id in mapData) {
	var parts = id.split(",");
	var x = parseInt(parts[0]);
	var y = parseInt(parts[1]);

	var baseColor = (mapData[id] ? [100, 100, 100] : [50, 50, 50]);
	var light = ambientLight;

	if (id in lightData) { /* add light from our computation */
		light = ROT.Color.add(light, lightData[id]);
	}

	var finalColor = ROT.Color.multiply(baseColor, light);
	display.draw(x, y, null, null, ROT.Color.toRGB(finalColor));
}
</div>