mirror of
https://github.com/minetest/minetest.git
synced 2024-12-24 15:12:23 +01:00
Relatively snappy object-ground collision detection
This commit is contained in:
parent
94feb62b08
commit
290e921920
@ -651,8 +651,7 @@ end
|
|||||||
|
|
||||||
local TNT = {
|
local TNT = {
|
||||||
-- Static definition
|
-- Static definition
|
||||||
-- Maybe handle gravity and collision this way? dunno
|
physical = true, -- Collides with things
|
||||||
-- physical = true,
|
|
||||||
-- weight = 5,
|
-- weight = 5,
|
||||||
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
|
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
|
||||||
visual = "cube",
|
visual = "cube",
|
||||||
@ -662,17 +661,14 @@ local TNT = {
|
|||||||
-- Initial value for our timer
|
-- Initial value for our timer
|
||||||
timer = 0,
|
timer = 0,
|
||||||
-- Number of punches required to defuse
|
-- Number of punches required to defuse
|
||||||
health = 3,
|
health = 1,
|
||||||
-- List names of state variables, for serializing object state
|
|
||||||
-- (NOTE: not implemented and implementation will not be like this)
|
|
||||||
-- state_variables = {"timer"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Called when a TNT object is created
|
-- Called when a TNT object is created
|
||||||
function TNT:on_activate(staticdata)
|
function TNT:on_activate(staticdata)
|
||||||
print("TNT:on_activate()")
|
print("TNT:on_activate()")
|
||||||
self.object:setvelocity({x=0, y=1, z=0})
|
self.object:setvelocity({x=0, y=2, z=0})
|
||||||
self.object:setacceleration({x=0, y=-5, z=0})
|
self.object:setacceleration({x=0, y=-10, z=0})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Called periodically
|
-- Called periodically
|
||||||
@ -709,6 +705,7 @@ minetest.register_entity("TNT", TNT)
|
|||||||
function register_falling_node(nodename, texture)
|
function register_falling_node(nodename, texture)
|
||||||
minetest.register_entity("falling_"..nodename, {
|
minetest.register_entity("falling_"..nodename, {
|
||||||
-- Static definition
|
-- Static definition
|
||||||
|
physical = true,
|
||||||
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
|
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
|
||||||
visual = "cube",
|
visual = "cube",
|
||||||
textures = {texture,texture,texture,texture,texture,texture},
|
textures = {texture,texture,texture,texture,texture,texture},
|
||||||
@ -719,7 +716,7 @@ function register_falling_node(nodename, texture)
|
|||||||
self.object:setacceleration({x=0, y=-10, z=0})
|
self.object:setacceleration({x=0, y=-10, z=0})
|
||||||
-- Turn to actual sand when collides to ground or just move
|
-- Turn to actual sand when collides to ground or just move
|
||||||
pos = self.object:getpos()
|
pos = self.object:getpos()
|
||||||
bcp = {x=pos.x, y=pos.y-0.5, z=pos.z} -- Position of bottom center point
|
bcp = {x=pos.x, y=pos.y-0.6, z=pos.z} -- Position of bottom center point
|
||||||
bcn = minetest.env:get_node(bcp)
|
bcn = minetest.env:get_node(bcp)
|
||||||
if bcn.name ~= "air" then
|
if bcn.name ~= "air" then
|
||||||
-- Turn to a sand node
|
-- Turn to a sand node
|
||||||
|
@ -177,6 +177,7 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
|||||||
speed_f -= speed_f.dotProduct(dirs[i]) * dirs[i];
|
speed_f -= speed_f.dotProduct(dirs[i]) * dirs[i];
|
||||||
pos_f -= pos_f.dotProduct(dirs[i]) * dirs[i];
|
pos_f -= pos_f.dotProduct(dirs[i]) * dirs[i];
|
||||||
pos_f += oldpos_f.dotProduct(dirs[i]) * dirs[i];
|
pos_f += oldpos_f.dotProduct(dirs[i]) * dirs[i];
|
||||||
|
result.collides = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -232,6 +233,8 @@ collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
|
|||||||
|
|
||||||
if(result.touching_ground)
|
if(result.touching_ground)
|
||||||
final_result.touching_ground = true;
|
final_result.touching_ground = true;
|
||||||
|
if(result.collides)
|
||||||
|
final_result.collides = true;
|
||||||
}
|
}
|
||||||
while(dtime_downcount > 0.001);
|
while(dtime_downcount > 0.001);
|
||||||
|
|
||||||
|
@ -28,9 +28,11 @@ class IGameDef;
|
|||||||
struct collisionMoveResult
|
struct collisionMoveResult
|
||||||
{
|
{
|
||||||
bool touching_ground;
|
bool touching_ground;
|
||||||
|
bool collides;
|
||||||
|
|
||||||
collisionMoveResult():
|
collisionMoveResult():
|
||||||
touching_ground(false)
|
touching_ground(false),
|
||||||
|
collides(false)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1457,11 +1457,34 @@ void LuaEntityCAO::updateNodePos()
|
|||||||
|
|
||||||
void LuaEntityCAO::step(float dtime, ClientEnvironment *env)
|
void LuaEntityCAO::step(float dtime, ClientEnvironment *env)
|
||||||
{
|
{
|
||||||
|
if(m_prop->physical){
|
||||||
|
core::aabbox3d<f32> box = m_prop->collisionbox;
|
||||||
|
box.MinEdge *= BS;
|
||||||
|
box.MaxEdge *= BS;
|
||||||
|
collisionMoveResult moveresult;
|
||||||
|
f32 pos_max_d = BS*0.25; // Distance per iteration
|
||||||
|
v3f p_pos = m_position;
|
||||||
|
v3f p_velocity = m_velocity;
|
||||||
|
IGameDef *gamedef = env->getGameDef();
|
||||||
|
moveresult = collisionMovePrecise(&env->getMap(), gamedef,
|
||||||
|
pos_max_d, box, dtime, p_pos, p_velocity);
|
||||||
|
// Apply results
|
||||||
|
m_position = p_pos;
|
||||||
|
m_velocity = p_velocity;
|
||||||
|
|
||||||
|
bool is_end_position = moveresult.collides;
|
||||||
|
pos_translator.update(m_position, is_end_position, dtime);
|
||||||
|
pos_translator.translate(dtime);
|
||||||
|
updateNodePos();
|
||||||
|
|
||||||
|
m_velocity += dtime * m_acceleration;
|
||||||
|
} else {
|
||||||
m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
|
m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
|
||||||
m_velocity += dtime * m_acceleration;
|
m_velocity += dtime * m_acceleration;
|
||||||
pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
|
pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
|
||||||
pos_translator.translate(dtime);
|
pos_translator.translate(dtime);
|
||||||
updateNodePos();
|
updateNodePos();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LuaEntityCAO::processMessage(const std::string &data)
|
void LuaEntityCAO::processMessage(const std::string &data)
|
||||||
@ -1487,10 +1510,12 @@ void LuaEntityCAO::processMessage(const std::string &data)
|
|||||||
// update_interval
|
// update_interval
|
||||||
float update_interval = readF1000(is);
|
float update_interval = readF1000(is);
|
||||||
|
|
||||||
if(do_interpolate)
|
if(do_interpolate){
|
||||||
|
if(!m_prop->physical)
|
||||||
pos_translator.update(m_position, is_end_position, update_interval);
|
pos_translator.update(m_position, is_end_position, update_interval);
|
||||||
else
|
} else {
|
||||||
pos_translator.init(m_position);
|
pos_translator.init(m_position);
|
||||||
|
}
|
||||||
updateNodePos();
|
updateNodePos();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ struct SmoothTranslator
|
|||||||
if(anim_time > 0.001)
|
if(anim_time > 0.001)
|
||||||
moveratio = anim_time_counter / anim_time;
|
moveratio = anim_time_counter / anim_time;
|
||||||
// Move a bit less than should, to avoid oscillation
|
// Move a bit less than should, to avoid oscillation
|
||||||
moveratio = moveratio * 0.5;
|
moveratio = moveratio * 0.8;
|
||||||
float move_end = 1.5;
|
float move_end = 1.5;
|
||||||
if(aim_is_end)
|
if(aim_is_end)
|
||||||
move_end = 1.0;
|
move_end = 1.0;
|
||||||
|
@ -1555,6 +1555,7 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos,
|
|||||||
m_yaw(0),
|
m_yaw(0),
|
||||||
m_last_sent_yaw(0),
|
m_last_sent_yaw(0),
|
||||||
m_last_sent_position(0,0,0),
|
m_last_sent_position(0,0,0),
|
||||||
|
m_last_sent_velocity(0,0,0),
|
||||||
m_last_sent_position_timer(0),
|
m_last_sent_position_timer(0),
|
||||||
m_last_sent_move_precision(0)
|
m_last_sent_move_precision(0)
|
||||||
{
|
{
|
||||||
@ -1612,8 +1613,27 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
|
|||||||
{
|
{
|
||||||
m_last_sent_position_timer += dtime;
|
m_last_sent_position_timer += dtime;
|
||||||
|
|
||||||
m_base_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
|
if(m_prop->physical){
|
||||||
|
core::aabbox3d<f32> box = m_prop->collisionbox;
|
||||||
|
box.MinEdge *= BS;
|
||||||
|
box.MaxEdge *= BS;
|
||||||
|
collisionMoveResult moveresult;
|
||||||
|
f32 pos_max_d = BS*0.25; // Distance per iteration
|
||||||
|
v3f p_pos = getBasePosition();
|
||||||
|
v3f p_velocity = m_velocity;
|
||||||
|
IGameDef *gamedef = m_env->getGameDef();
|
||||||
|
moveresult = collisionMovePrecise(&m_env->getMap(), gamedef,
|
||||||
|
pos_max_d, box, dtime, p_pos, p_velocity);
|
||||||
|
// Apply results
|
||||||
|
setBasePosition(p_pos);
|
||||||
|
m_velocity = p_velocity;
|
||||||
|
|
||||||
m_velocity += dtime * m_acceleration;
|
m_velocity += dtime * m_acceleration;
|
||||||
|
} else {
|
||||||
|
m_base_position += dtime * m_velocity + 0.5 * dtime
|
||||||
|
* dtime * m_acceleration;
|
||||||
|
m_velocity += dtime * m_acceleration;
|
||||||
|
}
|
||||||
|
|
||||||
if(m_registered){
|
if(m_registered){
|
||||||
lua_State *L = m_env->getLua();
|
lua_State *L = m_env->getLua();
|
||||||
@ -1623,7 +1643,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
|
|||||||
if(send_recommended == false)
|
if(send_recommended == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: force send when velocity/acceleration changes enough
|
// TODO: force send when acceleration changes enough?
|
||||||
float minchange = 0.2*BS;
|
float minchange = 0.2*BS;
|
||||||
if(m_last_sent_position_timer > 1.0){
|
if(m_last_sent_position_timer > 1.0){
|
||||||
minchange = 0.01*BS;
|
minchange = 0.01*BS;
|
||||||
@ -1632,7 +1652,9 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
|
|||||||
}
|
}
|
||||||
float move_d = m_base_position.getDistanceFrom(m_last_sent_position);
|
float move_d = m_base_position.getDistanceFrom(m_last_sent_position);
|
||||||
move_d += m_last_sent_move_precision;
|
move_d += m_last_sent_move_precision;
|
||||||
if(move_d > minchange || fabs(m_yaw - m_last_sent_yaw) > 1.0){
|
float vel_d = m_velocity.getDistanceFrom(m_last_sent_velocity);
|
||||||
|
if(move_d > minchange || vel_d > minchange ||
|
||||||
|
fabs(m_yaw - m_last_sent_yaw) > 1.0){
|
||||||
sendPosition(true, false);
|
sendPosition(true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1675,6 +1697,7 @@ std::string LuaEntitySAO::getStaticData()
|
|||||||
|
|
||||||
InventoryItem* LuaEntitySAO::createPickedUpItem()
|
InventoryItem* LuaEntitySAO::createPickedUpItem()
|
||||||
{
|
{
|
||||||
|
// TODO: Ask item from scriptapi
|
||||||
std::istringstream is("CraftItem testobject1 1", std::ios_base::binary);
|
std::istringstream is("CraftItem testobject1 1", std::ios_base::binary);
|
||||||
IGameDef *gamedef = m_env->getGameDef();
|
IGameDef *gamedef = m_env->getGameDef();
|
||||||
InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
|
InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
|
||||||
@ -1732,7 +1755,7 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
|
|||||||
m_last_sent_position_timer = 0;
|
m_last_sent_position_timer = 0;
|
||||||
m_last_sent_yaw = m_yaw;
|
m_last_sent_yaw = m_yaw;
|
||||||
m_last_sent_position = m_base_position;
|
m_last_sent_position = m_base_position;
|
||||||
//m_last_sent_velocity = m_velocity;
|
m_last_sent_velocity = m_velocity;
|
||||||
//m_last_sent_acceleration = m_acceleration;
|
//m_last_sent_acceleration = m_acceleration;
|
||||||
|
|
||||||
float update_interval = m_env->getSendRecommendedInterval();
|
float update_interval = m_env->getSendRecommendedInterval();
|
||||||
|
@ -231,6 +231,7 @@ private:
|
|||||||
float m_yaw;
|
float m_yaw;
|
||||||
float m_last_sent_yaw;
|
float m_last_sent_yaw;
|
||||||
v3f m_last_sent_position;
|
v3f m_last_sent_position;
|
||||||
|
v3f m_last_sent_velocity;
|
||||||
float m_last_sent_position_timer;
|
float m_last_sent_position_timer;
|
||||||
float m_last_sent_move_precision;
|
float m_last_sent_move_precision;
|
||||||
};
|
};
|
||||||
|
@ -362,14 +362,13 @@ public:
|
|||||||
~ClientEnvironment();
|
~ClientEnvironment();
|
||||||
|
|
||||||
Map & getMap()
|
Map & getMap()
|
||||||
{
|
{ return *m_map; }
|
||||||
return *m_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientMap & getClientMap()
|
ClientMap & getClientMap()
|
||||||
{
|
{ return *m_map; }
|
||||||
return *m_map;
|
|
||||||
}
|
IGameDef *getGameDef()
|
||||||
|
{ return m_gamedef; }
|
||||||
|
|
||||||
void step(f32 dtime);
|
void step(f32 dtime);
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||||
|
|
||||||
LuaEntityProperties::LuaEntityProperties():
|
LuaEntityProperties::LuaEntityProperties():
|
||||||
physical(true),
|
physical(false),
|
||||||
weight(5),
|
weight(5),
|
||||||
collisionbox(-0.5,-0.5,-0.5, 0.5,0.5,0.5),
|
collisionbox(-0.5,-0.5,-0.5, 0.5,0.5,0.5),
|
||||||
visual("single_sprite")
|
visual("single_sprite")
|
||||||
|
Loading…
Reference in New Issue
Block a user