1 /*-------------------------------------------------------------------------------
2
3 BARONY
4 File: light.cpp
5 Desc: light spawning code
6
7 Copyright 2013-2016 (c) Turning Wheel LLC, all rights reserved.
8 See LICENSE for details.
9
10 -------------------------------------------------------------------------------*/
11
12 #include "main.hpp"
13 #include "light.hpp"
14
15 /*-------------------------------------------------------------------------------
16
17 lightSphereShadow
18
19 Adds a circle of light to the lightmap at x and y with the supplied
20 radius and intensity; casts shadows against walls
21
22 intensity can be from -255 to 255
23
24 -------------------------------------------------------------------------------*/
25
lightSphereShadow(Sint32 x,Sint32 y,Sint32 radius,Sint32 intensity)26 light_t* lightSphereShadow(Sint32 x, Sint32 y, Sint32 radius, Sint32 intensity)
27 {
28 light_t* light;
29 Sint32 i;
30 Sint32 u, v, u2, v2;
31 double a, b;
32 Sint32 dx, dy;
33 Sint32 dxabs, dyabs;
34 bool wallhit;
35 int index, z;
36
37 if ( intensity == 0 )
38 {
39 return NULL;
40 }
41 light = newLight(x, y, radius, intensity);
42 intensity = std::min(std::max(-255, intensity), 255);
43
44 for ( v = y - radius; v <= y + radius; v++ )
45 {
46 for ( u = x - radius; u <= x + radius; u++ )
47 {
48 if ( u >= 0 && v >= 0 && u < map.width && v < map.height )
49 {
50 dx = u - x;
51 dy = v - y;
52 dxabs = abs(dx);
53 dyabs = abs(dy);
54 a = dyabs * .5;
55 b = dxabs * .5;
56 u2 = u;
57 v2 = v;
58 wallhit = true;
59 index = v * MAPLAYERS + u * MAPLAYERS * map.height;
60 for ( z = 0; z < MAPLAYERS; z++ )
61 {
62 if ( !map.tiles[index + z] )
63 {
64 wallhit = false;
65 break;
66 }
67 }
68 if ( wallhit == true )
69 {
70 continue;
71 }
72 if ( dxabs >= dyabs ) // the line is more horizontal than vertical
73 {
74 for ( i = 0; i < dxabs; i++ )
75 {
76 u2 -= sgn(dx);
77 b += dyabs;
78 if ( b >= dxabs )
79 {
80 b -= dxabs;
81 v2 -= sgn(dy);
82 }
83 if ( u2 >= 0 && u2 < map.width && v2 >= 0 && v2 < map.height )
84 {
85 if ( map.tiles[OBSTACLELAYER + v2 * MAPLAYERS + u2 * MAPLAYERS * map.height] )
86 {
87 wallhit = true;
88 break;
89 }
90 }
91 }
92 }
93 else // the line is more vertical than horizontal
94 {
95 for ( i = 0; i < dyabs; i++ )
96 {
97 v2 -= sgn(dy);
98 a += dxabs;
99 if ( a >= dyabs )
100 {
101 a -= dyabs;
102 u2 -= sgn(dx);
103 }
104 if ( u2 >= 0 && u2 < map.width && v2 >= 0 && v2 < map.height )
105 {
106 if ( map.tiles[OBSTACLELAYER + v2 * MAPLAYERS + u2 * MAPLAYERS * map.height] )
107 {
108 wallhit = true;
109 break;
110 }
111 }
112 }
113 }
114 if ( wallhit == false || (wallhit == true && u2 == u && v2 == v) )
115 {
116 light->tiles[(dy + radius) + (dx + radius) * (radius * 2 + 1)] = intensity - intensity * std::min<float>(sqrtf(dx * dx + dy * dy) / radius, 1.0f);
117 lightmap[v + u * map.height] += light->tiles[(dy + radius) + (dx + radius) * (radius * 2 + 1)];
118 }
119 }
120 }
121 }
122 return light;
123 }
124
125 /*-------------------------------------------------------------------------------
126
127 lightSphere
128
129 Adds a circle of light to the lightmap at x and y with the supplied
130 radius and intensity; casts no shadows
131
132 intensity can be from -255 to 255
133
134 -------------------------------------------------------------------------------*/
135
lightSphere(Sint32 x,Sint32 y,Sint32 radius,Sint32 intensity)136 light_t* lightSphere(Sint32 x, Sint32 y, Sint32 radius, Sint32 intensity)
137 {
138 light_t* light;
139 Sint32 u, v;
140 Sint32 dx, dy;
141
142 if ( intensity == 0 )
143 {
144 return NULL;
145 }
146 light = newLight(x, y, radius, intensity);
147 intensity = std::min(std::max(-255, intensity), 255);
148
149 for ( v = y - radius; v <= y + radius; v++ )
150 {
151 for ( u = x - radius; u <= x + radius; u++ )
152 {
153 if ( u >= 0 && v >= 0 && u < map.width && v < map.height )
154 {
155 dx = u - x;
156 dy = v - y;
157 light->tiles[(dy + radius) + (dx + radius) * (radius * 2 + 1)] = intensity - intensity * std::min<float>(sqrtf(dx * dx + dy * dy) / radius, 1.0f);
158 lightmap[v + u * map.height] += light->tiles[(dy + radius) + (dx + radius) * (radius * 2 + 1)];
159 }
160 }
161 }
162 return light;
163 }
164