From 40967784a36338023ada0e99b97511e289ad80a9 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sun, 23 Jul 2017 16:22:04 +0100 Subject: [PATCH] Add parameter to skip the callback on the first tile. For example if you are going from tile 1,1 to 1,2 you would get two notifications if parInclFirst==true, one for 1,1 and one for 1,2. If parInclFirst==false, then you will only get a notification for 1,2. Note that if the segment passed to to for_each_voxel_under_segment() is too short and doesn't span over the initial tile, passing parInclFirst==false will discard the only callback you would normally get. Effectively this can be used for a sort of "on tile changed" notification. --- src/gamelib/character.cpp | 2 +- src/gamelib/grid_raytrace.cpp | 16 ++++++++++++++-- src/gamelib/grid_raytrace.hpp | 9 ++++++++- test/unit/grid_raytrace.cpp | 3 ++- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/gamelib/character.cpp b/src/gamelib/character.cpp index b2dbcc7..1fad99b 100644 --- a/src/gamelib/character.cpp +++ b/src/gamelib/character.cpp @@ -93,7 +93,7 @@ namespace curry { return true; //wtp.property->walkable; }; - for_each_voxel_under_segment(old_pos, this->position(), width_height(), *m_world, is_walkable); + for_each_voxel_under_segment(old_pos, this->position(), width_height(), *m_world, is_walkable, false); //for (auto tile_vec : crossed_tiles(old_pos, this->position(), m_world->tile_size())) { // const TileIndex* const tile = m_world->tile(tile_vec); // for (uint16_t z = 0; z < m_world->layer_count(); ++z) { diff --git a/src/gamelib/grid_raytrace.cpp b/src/gamelib/grid_raytrace.cpp index 1641c31..a5b472a 100644 --- a/src/gamelib/grid_raytrace.cpp +++ b/src/gamelib/grid_raytrace.cpp @@ -93,7 +93,14 @@ namespace curry { //see: //http://stackoverflow.com/questions/24679963/precise-subpixel-line-drawing-algorithm-rasterization-algorithm - void for_each_voxel_under_segment (const vec2f& parFrom, const vec2f& parTo, vec2us parObjSize, const WorldGrid& parWorld, std::function parFunc) { + void for_each_voxel_under_segment ( + const vec2f& parFrom, + const vec2f& parTo, + vec2us parObjSize, + const WorldGrid& parWorld, + std::function parFunc, + bool parInclFirst + ) { const vec2f tile_size = vector_cast(parWorld.tile_size()); //in this simplified case everything should be part of the world grid assert(parFrom >= vec2f(0.0f)); @@ -129,7 +136,12 @@ namespace curry { vec2us curr_tile = pixel_to_world_tile(parWorld, u); const vec2us last_tile = pixel_to_world_tile(parWorld, parTo); - while (parFunc(curr_tile) and last_tile != curr_tile) { + bool& do_callback = parInclFirst; + while ( + ((do_callback and parFunc(curr_tile)) or not do_callback) + and last_tile != curr_tile + ) { + do_callback = true; if (max.x() < max.y()) { assert(step.x()); assert( diff --git a/src/gamelib/grid_raytrace.hpp b/src/gamelib/grid_raytrace.hpp index 017e5a7..92809b1 100644 --- a/src/gamelib/grid_raytrace.hpp +++ b/src/gamelib/grid_raytrace.hpp @@ -30,5 +30,12 @@ namespace curry { float segment_intersection (const vec2f& parA, const vec2f& parDirA, const vec2f& parB, const vec2f& parDirB); #endif - void for_each_voxel_under_segment ( const vec2f& parFrom, const vec2f& parTo, vec2us parObjSize, const WorldGrid& parWorld, std::function parFunc ); + void for_each_voxel_under_segment ( + const vec2f& parFrom, + const vec2f& parTo, + vec2us parObjSize, + const WorldGrid& parWorld, + std::function parFunc, + bool parInclFirst + ); } //namespace curry diff --git a/test/unit/grid_raytrace.cpp b/test/unit/grid_raytrace.cpp index ac6032d..438a738 100644 --- a/test/unit/grid_raytrace.cpp +++ b/test/unit/grid_raytrace.cpp @@ -54,7 +54,8 @@ TEST_CASE ("Check that 2D raytracing works", "[raytracing][geometry]") { vec2f(639.0f, 639.0f), //to vec2us(1, 1), //objsize world, //world - [&diagonal](vec2us wtp) mutable {diagonal.push_back(wtp); return true;} + [&diagonal](vec2us wtp) mutable {diagonal.push_back(wtp); return true;}, + true ); const auto* tile_prop = &world.tile_property(world.tile(vec2us(0)));