64 lines
		
	
	
	
		
			2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			64 lines
		
	
	
	
		
			2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "lights.hpp"
 | |
| #include "constants.hpp"
 | |
| #include <vector>
 | |
| 
 | |
| using std::vector;
 | |
| 
 | |
| namespace lighting {
 | |
|   void LightRender::render_square_light(LightSource source, Point at, PointList &has_light) {
 | |
|     for(matrix::box it{$lightmap, at.x, at.y, (size_t)floor(source.radius)}; it.next();) {
 | |
|       if($paths.$paths[it.y][it.x] != WALL_PATH_LIMIT) {
 | |
|         $lightmap[it.y][it.x] = light_level(source.strength, it.distance(), it.x, it.y);
 | |
|         has_light.push_back({it.x, it.y});
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * NOTE: This really doesn't need to calculate light all the time. It doesn't
 | |
|    * change around the light source until the lightsource is changed, so the
 | |
|    * light levels could be placed in a Matrix inside LightSource, calculated once
 | |
|    * and then simply "applied" to the area where the entity is located.  The only
 | |
|    * thing that would need to be calculated each time is the walls.
 | |
|    */
 | |
|   void LightRender::render_light(LightSource source, Point at) {
 | |
|     Point min, max;
 | |
|     clear_light_target(at);
 | |
|     PointList has_light;
 | |
| 
 | |
|     render_square_light(source, at, has_light);
 | |
| 
 | |
|     for(auto point : has_light) {
 | |
|       for(matrix::compass it{$lightmap, point.x, point.y}; it.next();) {
 | |
|         if($paths.$paths[it.y][it.x] == WALL_PATH_LIMIT) {
 | |
|             $lightmap[it.y][it.x] = light_level(source.strength, 1.5f, point.x, point.y);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   int LightRender::light_level(int strength, float distance, size_t x, size_t y) {
 | |
|     int new_level = distance <= 1.0f ? strength : strength / sqrt(distance);
 | |
|     int cur_level = $lightmap[y][x];
 | |
|     return cur_level < new_level ? new_level : cur_level;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   void LightRender::reset_light() {
 | |
|     for(auto &row : $lightmap) {
 | |
|       row.assign(row.size(), lighting::MIN);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   void LightRender::clear_light_target(const Point &at) {
 | |
|     $paths.clear_target(at);
 | |
|   }
 | |
| 
 | |
|   void LightRender::set_light_target(const Point &at, int value) {
 | |
|     $paths.set_target(at, value);
 | |
|   }
 | |
| 
 | |
|   void LightRender::path_light(Matrix &walls) {
 | |
|     $paths.compute_paths(walls);
 | |
|   }
 | |
| }
 | 
