X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fcollision.cpp;h=143b559fa7e427e3e7a3078e9f2ddc82a370da86;hb=91e88196c7c0e7ee87c1fd4783b3999710510a65;hp=09a7df7c2c069265c36ba4a1245fb9ec480cb472;hpb=1575448b1a71dd029a8d135d2aff9096483a9953;p=oweals%2Fminetest.git diff --git a/src/collision.cpp b/src/collision.cpp index 09a7df7c2..143b559fa 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -211,6 +211,8 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, std::vector cboxes; std::vector is_unloaded; std::vector is_step_up; + std::vector bouncy_values; + std::vector node_positions; { //TimeTaker tt2("collisionMoveSimple collect boxes"); ScopeProfiler sp(g_profiler, "collisionMoveSimple collect boxes avg", SPT_AVG); @@ -228,11 +230,14 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, for(s16 y = min_y; y <= max_y; y++) for(s16 z = min_z; z <= max_z; z++) { + v3s16 p(x,y,z); try{ // Object collides into walkable nodes - MapNode n = map->getNode(v3s16(x,y,z)); - if(gamedef->getNodeDefManager()->get(n).walkable == false) + MapNode n = map->getNode(p); + const ContentFeatures &f = gamedef->getNodeDefManager()->get(n); + if(f.walkable == false) continue; + int n_bouncy_value = itemgroup_get(f.groups, "bouncy"); std::vector nodeboxes = n.getNodeBoxes(gamedef->ndef()); for(std::vector::iterator @@ -245,21 +250,27 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, cboxes.push_back(box); is_unloaded.push_back(false); is_step_up.push_back(false); + bouncy_values.push_back(n_bouncy_value); + node_positions.push_back(p); } } catch(InvalidPositionException &e) { // Collide with unloaded nodes - aabb3f box = getNodeBox(v3s16(x,y,z), BS); + aabb3f box = getNodeBox(p, BS); cboxes.push_back(box); is_unloaded.push_back(true); is_step_up.push_back(false); + bouncy_values.push_back(0); + node_positions.push_back(p); } } } // tt2 assert(cboxes.size() == is_unloaded.size()); assert(cboxes.size() == is_step_up.size()); + assert(cboxes.size() == bouncy_values.size()); + assert(cboxes.size() == node_positions.size()); /* Collision detection @@ -342,6 +353,10 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, cbox.MaxEdge.Y - movingbox.MinEdge.Y, d)); + // Get bounce multiplier + bool bouncy = (bouncy_values[nearest_boxindex] >= 1); + float bounce = -(float)bouncy_values[nearest_boxindex] / 100.0; + // Move to the point of collision and reduce dtime by nearest_dtime if(nearest_dtime < 0) { @@ -361,30 +376,58 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, pos_f += speed_f * nearest_dtime; dtime -= nearest_dtime; } + + bool is_collision = true; + if(is_unloaded[nearest_boxindex]) + is_collision = false; + + CollisionInfo info; + info.type = COLLISION_NODE; + info.node_p = node_positions[nearest_boxindex]; + info.bouncy = bouncy; + info.old_speed = speed_f; // Set the speed component that caused the collision to zero if(step_up) { // Special case: Handle stairs is_step_up[nearest_boxindex] = true; + is_collision = false; } else if(nearest_collided == 0) // X { - speed_f.X = 0; + if(fabs(speed_f.X) > BS*3) + speed_f.X *= bounce; + else + speed_f.X = 0; result.collides = true; result.collides_xz = true; } else if(nearest_collided == 1) // Y { - speed_f.Y = 0; + if(fabs(speed_f.Y) > BS*3) + speed_f.Y *= bounce; + else + speed_f.Y = 0; result.collides = true; } else if(nearest_collided == 2) // Z { - speed_f.Z = 0; + if(fabs(speed_f.Z) > BS*3) + speed_f.Z *= bounce; + else + speed_f.Z = 0; result.collides = true; result.collides_xz = true; } + + info.new_speed = speed_f; + if(info.new_speed.getDistanceFrom(info.old_speed) < 0.1*BS) + is_collision = false; + + if(is_collision){ + result.collisions.push_back(info); + } } }