Lighting is working way better and now for world generation work.

main
Zed A. Shaw 1 week ago
parent 9c03e850b5
commit 194cc6664b
  1. 44
      assets/tiles.json
  2. 1
      constants.hpp
  3. 9
      lights.cpp
  4. 22
      lights.hpp
  5. 6
      main.cpp
  6. 19
      systems.cpp
  7. 4
      tests/lighting.cpp
  8. 15
      worldbuilder.cpp

@ -1,57 +1,57 @@
{
"WALL_TILE": {
"foreground": [230, 20, 0],
"background": [230, 20, 2],
"foreground": [230, 20, 30],
"background": [230, 20, 120],
"display": "\ua5b8"
},
"FLOOR_TILE": {
"foreground": [40, 15, 0],
"background": [200, 15, 2],
"foreground": [40, 15, 125],
"background": [200, 15, 75],
"display":"\u289e"
},
"MOSAIC_TILE_1": {
"foreground": [40, 15, 0],
"background": [200, 29, 2],
"foreground": [40, 15, 125],
"background": [200, 29, 75],
"display":"\u19f0"
},
"MOSAIC_TILE_2": {
"foreground": [40, 15, 0],
"background": [200, 29, 2],
"foreground": [40, 15, 125],
"background": [200, 29, 75],
"display":"\u16de"
},
"MOSAIC_TILE_3": {
"foreground": [40, 15, 0],
"background": [200, 29, 2],
"foreground": [40, 15, 125],
"background": [200, 29, 75],
"display":"\u1378"
},
"PLAYER_TILE": {
"foreground": [255, 200, 0],
"background": [30, 20, 2],
"foreground": [255, 200, 125],
"background": [30, 20, 75],
"display":"\ua66b"
},
"ENEMY_TILE": {
"foreground": [255, 200, 0],
"background": [30, 20, 2],
"foreground": [255, 200, 125],
"background": [30, 20, 75],
"display":"\u1d5c"
},
"BG_TILE": {
"foreground": [230, 20, 0],
"background": [230, 20, 2],
"foreground": [230, 20, 125],
"background": [230, 20, 125],
"display":"█"
},
"WATER_TILE": {
"foreground": [132, 200, 0],
"background": [147, 220, 2],
"foreground": [132, 200, 180],
"background": [147, 220, 100],
"display":"\u098c"
},
"SAND_TILE": {
"foreground": [24, 106, 0],
"background": [24, 123, 2],
"foreground": [24, 106, 180],
"background": [24, 123, 100],
"display":"\u17f6"
},
"GRASS_TILE": {
"foreground": [41, 180, 0],
"background": [75, 100, 2],
"foreground": [41, 180, 180],
"background": [75, 100, 100],
"display":"\u0799"
}
}

@ -17,5 +17,6 @@ const int MAX_FONT_SIZE = 140;
const int MIN_FONT_SIZE = 20;
const int SCREEN_WIDTH = 40;
const int SCREEN_HEIGHT = 30;
const float PERCENT = 0.01f;
#define FONT_FILE_NAME "./assets/text.otf"
#define TILE_MAP_CONFIG "./assets/tiles.json"

@ -8,6 +8,9 @@ namespace lighting {
void LightRender::render_square_light(LightSource source, Point at, PointList &has_light) {
for(matrix::in_box it{$lightmap, at.x, at.y, (size_t)floor(source.radius)}; it.next();) {
if($paths.$paths[it.y][it.x] != WALL_PATH_LIMIT) {
if(it.x == at.x && it.y == at.y) {
println("distance at center: {}", it.distance());
}
$lightmap[it.y][it.x] = light_level(source.strength, it.distance(), it.x, it.y);
has_light.push_back({it.x, it.y});
}
@ -33,10 +36,10 @@ namespace lighting {
}
}
int LightRender::light_level(int level, float distance, size_t x, size_t y) {
size_t at = level + ceil(distance);
int LightRender::light_level(int strength, float distance, size_t x, size_t y) {
int cur_level = $lightmap[y][x];
int new_level = at < lighting::LEVELS.size() ? lighting::LEVELS[at] : lighting::MIN;
int new_level = strength / sqrt(distance + 0.6f);
return cur_level < new_level ? new_level : cur_level;
}

@ -9,26 +9,12 @@
namespace lighting {
struct LightSource {
int strength = 0; // lower is better
float radius = 1.0f; // higher is farther, in squares
int strength = 0;
float radius = 1.0f;
};
const int MIN = 50;
const int MAX = 170;
const int MID = 130;
const std::array<int, 10> LEVELS{
MAX,
160,
150,
140,
MID,
120,
110,
90,
70,
MIN,
};
const int MIN = 35;
const int MAX = 95;
class LightRender {
public:

@ -33,7 +33,7 @@ void configure_world(DinkyECS::World &world, Map &game_map) {
world.set<Combat>(player.entity, {100, 10});
world.set<Tile>(player.entity, {config.PLAYER_TILE});
world.set<Inventory>(player.entity, {5});
world.set<LightSource>(player.entity, {6,1.0});
world.set<LightSource>(player.entity, {70,1.0});
auto enemy = world.entity();
world.set<Position>(enemy, {game_map.place_entity(1)});
@ -46,7 +46,7 @@ void configure_world(DinkyECS::World &world, Map &game_map) {
world.set<Motion>(enemy2, {0,0});
world.set<Combat>(enemy2, {20, 10});
world.set<Tile>(enemy2, {"*"});
world.set<LightSource>(enemy2, {7,0});
world.set<LightSource>(enemy2, {60,0.2f});
auto gold = world.entity();
world.set<Position>(gold, {game_map.place_entity(3)});
@ -55,7 +55,7 @@ void configure_world(DinkyECS::World &world, Map &game_map) {
auto wall_torch = world.entity();
world.set<Position>(wall_torch, {game_map.place_entity(4)});
world.set<LightSource>(wall_torch, {4,3});
world.set<LightSource>(wall_torch, {90,3.0f});
world.set<Tile>(wall_torch, {""});
}

@ -143,7 +143,7 @@ void System::collision(DinkyECS::World &world, Player &player) {
world.send<Events::GUI>(Events::GUI::LOOT, entity, loot);
inventory.gold += loot.amount;
light.strength = 5;
light.strength = 70;
light.radius = 2;
collider.remove(loot_pos.location);
} else {
@ -162,13 +162,13 @@ void System::draw_entities(DinkyECS::World &world, Map &game_map, const Matrix &
&& pos.location.y >= cam_orig.y && pos.location.y <= cam_orig.y + view_y) {
Point loc = game_map.map_to_camera(pos.location, cam_orig);
int light_value = lighting[pos.location.y][pos.location.x];
float light_value = lighting[pos.location.y][pos.location.x] * PERCENT;
const TileCell& cell = tiles.at(pos.location.x, pos.location.y);
// the 2 and 4 are from ftxui::Canvas since it does a kind of "subpixel" drawing
canvas.DrawText(loc.x*2, loc.y*4, tile.chr, [light_value, cell](auto &pixel) {
pixel.foreground_color = Color::HSV(255, 200, light_value + 20);
pixel.background_color = Color::HSV(cell.bg_h, cell.bg_s, light_value / cell.bg_v);
pixel.foreground_color = Color::HSV(255, 200, 180 * light_value);
pixel.background_color = Color::HSV(cell.bg_h, cell.bg_s, cell.bg_v * light_value);
});
}
});
@ -188,20 +188,21 @@ void System::draw_map(DinkyECS::World &world, Map &game_map, const Matrix &light
for(size_t y = 0; y < end_y; ++y) {
for(size_t x = 0; x < end_x; ++x) {
const TileCell& tile = tiles.at(start.x+x, start.y+y);
int light_value = debug.LIGHT ? 160 : lighting[start.y+y][start.x+x];
// light value is an integer that's a percent
float light_value = debug.LIGHT ? 80 * PERCENT : lighting[start.y+y][start.x+x] * PERCENT;
int dnum = debug.PATHS ? paths[start.y+y][start.x+x] : WALL_PATH_LIMIT;
if(debug.PATHS && dnum != WALL_PATH_LIMIT) {
string num = dnum > 15 ? "*" : format("{:x}", dnum);
canvas.DrawText(x * 2, y * 4, num, [dnum, light_value](auto &pixel) {
canvas.DrawText(x * 2, y * 4, num, [dnum, tile, light_value](auto &pixel) {
pixel.foreground_color = Color::HSV(dnum * 20, 150, 200);
pixel.background_color = Color::HSV(30, 20, light_value / 2);
pixel.background_color = Color::HSV(30, 20, tile.bg_v * 50 * PERCENT);
});
} else {
canvas.DrawText(x * 2, y * 4, tile.display, [tile, light_value](auto &pixel) {
pixel.foreground_color = Color::HSV(tile.fg_h, tile.fg_s, light_value - tile.fg_v);
pixel.background_color = Color::HSV(tile.bg_h, tile.bg_s, light_value / tile.bg_v);
pixel.foreground_color = Color::HSV(tile.fg_h, tile.fg_s, tile.fg_v * light_value);
pixel.background_color = Color::HSV(tile.bg_h, tile.bg_s, tile.bg_v * light_value);
});
}
}

@ -40,8 +40,4 @@ TEST_CASE("lighting a map works", "[lighting]") {
matrix::dump("PATHS=====", lr.paths(), light1.x, light1.y);
matrix::dump("LIGHTING 1", lighting, light1.x, light1.y);
matrix::dump("LIGHTING 2", lighting, light2.x, light2.y);
// confirm light is set at least at and around the two points
REQUIRE(lighting[light1.y][light1.x] == lighting::LEVELS[source1.strength]);
REQUIRE(lighting[light2.y][light2.x] == lighting::LEVELS[source2.strength]);
}

@ -153,10 +153,17 @@ void WorldBuilder::generate() {
}
$map.load_tiles();
stylize_room(3, "WATER_TILE", 2.5);
stylize_room(2, "SAND_TILE", 4.5);
stylize_room(4, "MOSAIC_TILE_2", 7.0);
stylize_room(1, "GRASS_TILE", 3.4);
std::array<string, 6> room_types{
"WATER_TILE", "SAND_TILE", "MOSAIC_TILE_1",
"MOSAIC_TILE_2", "MOSAIC_TILE_3", "GRASS_TILE"
};
for(size_t i = 0; i < $map.$rooms.size() - 1; i++) {
size_t room_type = Random::uniform<size_t>(0, room_types.size() - 1);
int room_size = Random::uniform<int>(100, 800);
stylize_room(i, room_types[room_type], room_size * 0.01f);
}
}
void WorldBuilder::make_room(size_t origin_x, size_t origin_y, size_t w, size_t h) {

Loading…
Cancel
Save