Trying a new 'glowing moss' texture to sort out how to make the raycaster alter the light of a surface that has its own light.

master
Zed A. Shaw 1 week ago
parent e361984c40
commit 9dcc2036aa
  1. 4
      Makefile
  2. 5
      assets/config.json
  3. BIN
      assets/glowing_moss_wall-256.png
  4. 7
      assets/tiles.json
  5. 38
      map.cpp
  6. 2
      map.hpp
  7. 2
      matrix.hpp
  8. 26
      shiterator.hpp
  9. 2
      tests/lighting.cpp
  10. 9
      tests/map.cpp
  11. 11
      tilemap.cpp
  12. 54
      worldbuilder.cpp

@ -26,7 +26,7 @@ tracy_build:
meson compile -j 10 -C builddir
test: build
./builddir/runtests "[mazes]"
./builddir/runtests
run: build test
ifeq '$(OS)' 'Windows_NT'
@ -49,7 +49,7 @@ clean:
meson compile --clean -C builddir
debug_test: build
gdb --nx -x .gdbinit --ex run --args builddir/runtests -e "[mazes]"
gdb --nx -x .gdbinit --ex run --args builddir/runtests -e
win_installer:
powershell 'start "C:\Program Files (x86)\solicus\InstallForge\bin\ifbuilderenvx86.exe" scripts\win_installer.ifp'

@ -95,6 +95,11 @@
"frame_width": 256,
"frame_height": 256
},
"wall":
{"path": "assets/glowing_moss_wall-256.png",
"frame_width": 256,
"frame_height": 256
},
"floor":
{"path": "assets/floor_tile_test-256.png",
"frame_width": 256,

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

@ -6,6 +6,13 @@
"collision": false,
"display": 10398
},
"WALL_MOSS": {
"texture": "assets/glowing_moss_wall-256.png",
"foreground": [230, 20, 30],
"background": [230, 20, 120],
"collision": true,
"display": 37
},
"WALL_PLAIN": {
"texture": "assets/wall_texture_test-256.png",
"foreground": [230, 20, 30],

@ -46,12 +46,8 @@ void Map::clear_target(const Point &at) {
bool Map::place_entity(size_t room_index, Point &out) {
dbc::check($dead_ends.size() != 0, "no dead ends?!");
if($rooms.size() == 0) {
out = $dead_ends.at(room_index % $dead_ends.size());
return true;
} else {
dbc::check(room_index < $rooms.size(), "room_index is out of bounds, not enough rooms");
if(room_index < $rooms.size()) {
Room &start = $rooms.at(room_index);
for(matrix::rando_rect it{$walls, start.x, start.y, start.width, start.height}; it.next();) {
@ -61,9 +57,10 @@ bool Map::place_entity(size_t room_index, Point &out) {
return true;
}
}
return false;
}
out = $dead_ends.at(room_index % $dead_ends.size());
return true;
}
bool Map::iswall(size_t x, size_t y) {
@ -151,23 +148,20 @@ void Map::load_tiles() {
$tiles.load($walls);
}
void Map::expand() {
// adjust width first
for(auto &row : $walls) {
row.insert(row.begin(), WALL_VALUE);
row.push_back(WALL_VALUE);
}
$width = matrix::width($walls);
void Map::enclose() {
std::array<Point, 4> starts{{
{0,0}, {$width-1, 0}, {$width-1, $height-1}, {0, $height-1}
}};
// then add two new rows top/bottom of that new width
$walls.insert($walls.begin(), matrix::Row($width, WALL_VALUE));
$walls.push_back(matrix::Row($width, WALL_VALUE));
// now we have the new height
$height = matrix::height($walls);
std::array<Point, 4> ends{{
{$width-1, 0}, {$width-1, $height-1}, {0, $height-1}, {0,0},
}};
// reset the pathing and tiles and done
$paths = Pathing($width, $height);
$tiles = TileMap($width, $height);
for(size_t i = 0; i < starts.size(); i++) {
for(matrix::line it{starts[i], ends[i]}; it.next();) {
$walls[it.y][it.x] = 1;
}
}
}
void Map::add_room(Room &room) {

@ -60,7 +60,7 @@ public:
Point map_to_camera(const Point &loc, const Point &cam_orig);
Point center_camera(const Point &around, size_t view_x, size_t view_y);
void expand();
void enclose();
void dump(int show_x=-1, int show_y=-1);
bool INVARIANT();

@ -27,6 +27,8 @@ namespace matrix {
using circle = shiterator::circle_t<Matrix>;
using rectangle = shiterator::rectangle_t<Matrix>;
using rando_rect = shiterator::rando_rect_t<Matrix>;
using rando_rect = shiterator::rando_rect_t<Matrix>;
using rando_box = shiterator::rando_box_t<Matrix>;
using line = shiterator::line;
void dump(const std::string &msg, Matrix &map, int show_x=-1, int show_y=-1);

@ -533,6 +533,32 @@ namespace shiterator { using std::vector, std::queue, std::array; using
}
};
/*
* Same as rando_rect_t but it uses a centered box.
*/
template<typename MAT>
struct rando_box_t {
size_t x;
size_t y;
size_t x_offset;
size_t y_offset;
box_t<MAT> it;
rando_box_t(MAT &mat, size_t start_x, size_t start_y, size_t size) :
it{mat, start_x, start_y, size}
{
x_offset = Random::uniform(size_t(0), it.right);
y_offset = Random::uniform(size_t(0), it.bottom);
}
bool next() {
bool done = it.next();
x = it.left + ((it.x + x_offset) % it.right);
y = it.top + ((it.y + y_offset) % it.bottom);
return done;
}
};
/*
* WIP: This one is used to place entities randomly but
* could be used for effects like random destruction of floors.

@ -17,7 +17,7 @@ TEST_CASE("lighting a map works", "[lighting]") {
Point light1, light2;
REQUIRE(map.place_entity(0, light1));
REQUIRE(map.place_entity(1, light1));
REQUIRE(map.place_entity(0, light1));
LightSource source1{6, 1.0};
LightSource source2{4,3};

@ -32,23 +32,18 @@ TEST_CASE("camera control", "[map]") {
}
TEST_CASE("map placement test", "[map:placement]") {
for(int i = 0; i < 50; i++) {
for(int i = 0; i < 20; i++) {
LevelManager levels;
GameLevel level = levels.current();
auto &map = *level.map;
for(size_t rnum = 0; rnum < map.room_count(); rnum++) {
Room &room = map.room(rnum);
Point pos;
REQUIRE(map.place_entity(rnum, pos));
// matrix::dump("ROOM PLACEMENT TEST", map.walls(), pos.x, pos.y);
REQUIRE(!map.iswall(pos.x, pos.y));
REQUIRE(pos.x >= room.x);
REQUIRE(pos.y >= room.y);
REQUIRE(pos.x <= room.x + room.width);
REQUIRE(pos.y <= room.y + room.height);
REQUIRE(map.inmap(pos.x, pos.y));
}
}
}

@ -39,15 +39,16 @@ void TileMap::dump(int show_x, int show_y) {
}
void TileMap::set_tile(size_t x, size_t y, string tile_name) {
json tile_conf = $config[tile_name];
auto tile = components::convert<Tile>(tile_conf);
$tile_ids[y][x] = tile.display;
$display[y][x] = tile;
json tile_conf = $config[tile_name];
auto tile = components::convert<Tile>(tile_conf);
$tile_ids[y][x] = tile.display;
$display[y][x] = tile;
}
void TileMap::load(matrix::Matrix &walls) {
for(matrix::each_cell it{walls}; it.next();) {
string tile_name = walls[it.y][it.x] == SPACE_VALUE ? "FLOOR_TILE" : "WALL_PLAIN";
string tile_name = walls[it.y][it.x] == SPACE_VALUE ? "FLOOR_TILE" : "WALL_MOSS";
set_tile(it.x, it.y, tile_name);
}
}

@ -22,22 +22,30 @@ void WorldBuilder::generate_map() {
maze.hunt_and_kill();
$map.expand();
$map.enclose();
$map.load_tiles();
}
bool WorldBuilder::find_open_spot(Point& pos_out) {
// NOTE: still spawning near a player but not sure if this is the place
// to solve that. Idea: Get the player, don't place anything too close.
for(matrix::rando_rect it{$map.walls(), pos_out.x, pos_out.y, 3}; it.next();) {
Point test{size_t(it.x), size_t(it.y)};
if($map.can_move(test) && !$collision.occupied(test)) {
pos_out = test;
return true;
size_t i = 0;
// horribly bad but I need to place things _somewhere_ so just fan out
for(i = 2; i < $map.width(); i++) {
// rando_rect starts at the top/left corner not center
for(matrix::rando_box it{$map.walls(), pos_out.x, pos_out.y, i}; it.next();) {
Point test{size_t(it.x), size_t(it.y)};
if($map.can_move(test) && !$collision.occupied(test)) {
pos_out = test;
return true;
}
}
}
matrix::dump("FAIL PLACE!", $map.walls(), pos_out.x, pos_out.y);
dbc::sentinel(fmt::format("failed to place entity in the entire map?: i={}; width={};", i, $map.width()));
return false;
}
@ -137,17 +145,26 @@ void WorldBuilder::configure_starting_items(DinkyECS::World &world) {
void WorldBuilder::place_entities(DinkyECS::World &world) {
auto &config = world.get_the<GameConfig>();
// configure a player as a fact of the world
Position player_pos{0,0};
if(world.has_the<Player>()) {
auto& player = world.get_the<Player>();
Point pos_out;
bool placed = $map.place_entity(0, pos_out);
dbc::check(placed, "failed to randomly place item in room");
world.set<Position>(player.entity, {pos_out.x+1, pos_out.y+1});
// first get a guess from the map
bool placed = $map.place_entity(0, player_pos.location);
dbc::check(placed, "map.place_entity failed to position player");
// then use the collision map to place the player safely
placed = find_open_spot(player_pos.location);
dbc::check(placed, "WorldBuild.find_open_spot also failed to position player");
world.set<Position>(player.entity, player_pos);
} else {
auto player_data = config.enemies["PLAYER_TILE"];
auto player_ent = configure_entity_in_room(world, player_data, 0);
player_pos = world.get<Position>(player_ent);
// configure player in the world
Player player{player_ent};
world.set_the<Player>(player);
@ -158,6 +175,17 @@ void WorldBuilder::place_entities(DinkyECS::World &world) {
world.make_constant(player.entity);
}
dbc::check(player_pos.location.x != 0 && player_pos.location.y != 0,
"failed to place the player correctly");
// make a dead zone around the player
auto& player = world.get_the<Player>();
for(matrix::box it{$map.walls(), player_pos.location.x, player_pos.location.y, 2};
it.next();)
{
$collision.insert({it.x, it.y}, player.entity);
}
randomize_entities(world, config);
place_stairs(world, config);
}

Loading…
Cancel
Save