1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-08-06 17:41:04 +00:00

Added object <-> object collision handling (player + luaentity support only)

This commit is contained in:
sapier 2012-02-05 17:23:08 +01:00
parent f34f75291b
commit ffe6025f61
12 changed files with 157 additions and 32 deletions

View file

@ -62,6 +62,7 @@ public:
virtual u8 getType() const = 0; virtual u8 getType() const = 0;
virtual aabb3f* getCollisionBox() = 0;
protected: protected:
u16 m_id; // 0 is invalid, "no id" u16 m_id; // 0 is invalid, "no id"
}; };

View file

@ -22,8 +22,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "map.h" #include "map.h"
#include "nodedef.h" #include "nodedef.h"
#include "gamedef.h" #include "gamedef.h"
#include "environment.h"
#include "log.h" #include "log.h"
#include <vector> #include <vector>
#include <list>
// Helper function: // Helper function:
// Checks for collision of a moving aabbox with a static aabbox // Checks for collision of a moving aabbox with a static aabbox
@ -183,11 +185,14 @@ bool wouldCollideWithCeiling(
} }
collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, collisionMoveResult collisionMoveSimple(Environment* env,
f32 pos_max_d, const aabb3f &box_0, f32 pos_max_d, const aabb3f &box_0,
f32 stepheight, f32 dtime, f32 stepheight, f32 dtime,
v3f &pos_f, v3f &speed_f, v3f &accel_f) v3f &pos_f, v3f &speed_f, v3f &accel_f)
{ {
Map * map = &env->getMap();
IGameDef * gamedef = env->getGameDef();
TimeTaker tt("collisionMoveSimple"); TimeTaker tt("collisionMoveSimple");
collisionMoveResult result; collisionMoveResult result;
@ -252,6 +257,27 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
assert(cboxes.size() == is_unloaded.size()); assert(cboxes.size() == is_unloaded.size());
assert(cboxes.size() == is_step_up.size()); assert(cboxes.size() == is_step_up.size());
{
TimeTaker tt3("collisionMoveSimple collect object boxes");
/* add object boxes to cboxes */
core::list<ActiveObject*> objects = env->getActiveObjects();
for (core::list<ActiveObject*>::Iterator iter = objects.begin();
iter != objects.end(); iter++)
{
aabb3f* object_collisionbox = (*iter)->getCollisionBox();
//TODO do we need to check if it's really near enough?
if (object_collisionbox != NULL)
{
cboxes.push_back(*object_collisionbox);
is_unloaded.push_back(false);
is_step_up.push_back(false);
}
}
} //tt3
/* /*
Collision detection Collision detection
*/ */
@ -277,7 +303,8 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
loopcount++; loopcount++;
if(loopcount >= 100) if(loopcount >= 100)
{ {
infostream<<"collisionMoveSimple: WARNING: Loop count exceeded, aborting to avoid infiniite loop"<<std::endl; infostream<<"collisionMoveSimple: WARNING: Loop count exceeded, "
"aborting to avoid infiniite loop"<<std::endl;
dtime = 0; dtime = 0;
break; break;
} }
@ -422,7 +449,7 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
return result; return result;
} }
collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef, collisionMoveResult collisionMovePrecise(Environment* env,
f32 pos_max_d, const aabb3f &box_0, f32 pos_max_d, const aabb3f &box_0,
f32 stepheight, f32 dtime, f32 stepheight, f32 dtime,
v3f &pos_f, v3f &speed_f, v3f &accel_f) v3f &pos_f, v3f &speed_f, v3f &accel_f)
@ -470,7 +497,7 @@ collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
dtime_downcount = 0; dtime_downcount = 0;
} }
collisionMoveResult result = collisionMoveSimple(map, gamedef, collisionMoveResult result = collisionMoveSimple(env,
pos_max_d, box_0, stepheight, dtime_part, pos_max_d, box_0, stepheight, dtime_part,
pos_f, speed_f, accel_f); pos_f, speed_f, accel_f);

View file

@ -23,8 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common_irrlicht.h" #include "common_irrlicht.h"
#include <vector> #include <vector>
class Map; class Environment;
class IGameDef;
struct collisionMoveResult struct collisionMoveResult
{ {
@ -42,13 +41,13 @@ struct collisionMoveResult
}; };
// Moves using a single iteration; speed should not exceed pos_max_d/dtime // Moves using a single iteration; speed should not exceed pos_max_d/dtime
collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, collisionMoveResult collisionMoveSimple(Environment* env,
f32 pos_max_d, const aabb3f &box_0, f32 pos_max_d, const aabb3f &box_0,
f32 stepheight, f32 dtime, f32 stepheight, f32 dtime,
v3f &pos_f, v3f &speed_f, v3f &accel_f); v3f &pos_f, v3f &speed_f, v3f &accel_f);
// Moves using as many iterations as needed // Moves using as many iterations as needed
collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef, collisionMoveResult collisionMovePrecise(Environment* env,
f32 pos_max_d, const aabb3f &box_0, f32 pos_max_d, const aabb3f &box_0,
f32 stepheight, f32 dtime, f32 stepheight, f32 dtime,
v3f &pos_f, v3f &speed_f, v3f &accel_f); v3f &pos_f, v3f &speed_f, v3f &accel_f);

View file

@ -1701,6 +1701,7 @@ private:
int m_anim_num_frames; int m_anim_num_frames;
float m_anim_framelength; float m_anim_framelength;
float m_anim_timer; float m_anim_timer;
aabb3f m_collisionbox;
public: public:
LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env): LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env):
@ -1879,8 +1880,7 @@ public:
v3f p_pos = m_position; v3f p_pos = m_position;
v3f p_velocity = m_velocity; v3f p_velocity = m_velocity;
v3f p_acceleration = m_acceleration; v3f p_acceleration = m_acceleration;
IGameDef *gamedef = env->getGameDef(); moveresult = collisionMovePrecise(env,
moveresult = collisionMovePrecise(&env->getMap(), gamedef,
pos_max_d, box, stepheight, dtime, pos_max_d, box, stepheight, dtime,
p_pos, p_velocity, p_acceleration); p_pos, p_velocity, p_acceleration);
// Apply results // Apply results
@ -2047,6 +2047,21 @@ public:
updateTexturePos(); updateTexturePos();
} }
} }
aabb3f* getCollisionBox() {
if (m_prop->physical) {
//update collision box
m_collisionbox.MinEdge = m_prop->collisionbox.MinEdge * BS;
m_collisionbox.MaxEdge = m_prop->collisionbox.MaxEdge * BS;
m_collisionbox.MinEdge += m_position;
m_collisionbox.MaxEdge += m_position;
return &m_collisionbox;
}
return NULL;
}
}; };
// Prototype // Prototype
@ -2070,6 +2085,7 @@ private:
LocalPlayer *m_local_player; LocalPlayer *m_local_player;
float m_damage_visual_timer; float m_damage_visual_timer;
bool m_dead; bool m_dead;
aabb3f m_collisionbox;
public: public:
PlayerCAO(IGameDef *gamedef, ClientEnvironment *env): PlayerCAO(IGameDef *gamedef, ClientEnvironment *env):
@ -2116,6 +2132,17 @@ public:
} }
} }
aabb3f* getCollisionBox() {
//update collision box
m_collisionbox.MinEdge = m_selection_box.MinEdge;
m_collisionbox.MaxEdge = m_selection_box.MaxEdge;
m_collisionbox.MinEdge += m_position;
m_collisionbox.MaxEdge += m_position;
return &m_collisionbox;
}
~PlayerCAO() ~PlayerCAO()
{ {
if(m_node) if(m_node)

View file

@ -165,8 +165,7 @@ void ItemSAO::step(float dtime, bool send_recommended)
v3f pos_f_old = pos_f; v3f pos_f_old = pos_f;
v3f accel_f = v3f(0,0,0); v3f accel_f = v3f(0,0,0);
f32 stepheight = 0; f32 stepheight = 0;
IGameDef *gamedef = m_env->getGameDef(); moveresult = collisionMoveSimple(m_env,
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
pos_max_d, box, stepheight, dtime, pos_max_d, box, stepheight, dtime,
pos_f, m_speed_f, accel_f); pos_f, m_speed_f, accel_f);
@ -409,8 +408,7 @@ void RatSAO::step(float dtime, bool send_recommended)
v3f pos_f_old = pos_f; v3f pos_f_old = pos_f;
v3f accel_f = v3f(0,0,0); v3f accel_f = v3f(0,0,0);
f32 stepheight = 0; f32 stepheight = 0;
IGameDef *gamedef = m_env->getGameDef(); moveresult = collisionMoveSimple(m_env,
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
pos_max_d, box, stepheight, dtime, pos_max_d, box, stepheight, dtime,
pos_f, m_speed_f, accel_f); pos_f, m_speed_f, accel_f);
m_touching_ground = moveresult.touching_ground; m_touching_ground = moveresult.touching_ground;
@ -660,8 +658,7 @@ void Oerkki1SAO::step(float dtime, bool send_recommended)
v3f pos_f_old = pos_f; v3f pos_f_old = pos_f;
v3f accel_f = v3f(0,0,0); v3f accel_f = v3f(0,0,0);
f32 stepheight = 0; f32 stepheight = 0;
IGameDef *gamedef = m_env->getGameDef(); moveresult = collisionMovePrecise(m_env,
moveresult = collisionMovePrecise(&m_env->getMap(), gamedef,
pos_max_d, box, stepheight, dtime, pos_max_d, box, stepheight, dtime,
pos_f, m_speed_f, accel_f); pos_f, m_speed_f, accel_f);
m_touching_ground = moveresult.touching_ground; m_touching_ground = moveresult.touching_ground;
@ -910,8 +907,7 @@ void FireflySAO::step(float dtime, bool send_recommended)
v3f pos_f_old = pos_f; v3f pos_f_old = pos_f;
v3f accel_f = v3f(0,0,0); v3f accel_f = v3f(0,0,0);
f32 stepheight = 0; f32 stepheight = 0;
IGameDef *gamedef = m_env->getGameDef(); moveresult = collisionMoveSimple(m_env,
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
pos_max_d, box, stepheight, dtime, pos_max_d, box, stepheight, dtime,
pos_f, m_speed_f, accel_f); pos_f, m_speed_f, accel_f);
m_touching_ground = moveresult.touching_ground; m_touching_ground = moveresult.touching_ground;
@ -1634,8 +1630,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
v3f p_pos = m_base_position; v3f p_pos = m_base_position;
v3f p_velocity = m_velocity; v3f p_velocity = m_velocity;
v3f p_acceleration = m_acceleration; v3f p_acceleration = m_acceleration;
IGameDef *gamedef = m_env->getGameDef(); moveresult = collisionMovePrecise(m_env,
moveresult = collisionMovePrecise(&m_env->getMap(), gamedef,
pos_max_d, box, stepheight, dtime, pos_max_d, box, stepheight, dtime,
p_pos, p_velocity, p_acceleration); p_pos, p_velocity, p_acceleration);
// Apply results // Apply results
@ -1844,3 +1839,18 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
m_messages_out.push_back(aom); m_messages_out.push_back(aom);
} }
aabb3f* LuaEntitySAO::getCollisionBox() {
if (m_prop->physical) {
//update collision box
m_collisionbox.MinEdge = m_prop->collisionbox.MinEdge * BS;
m_collisionbox.MaxEdge = m_prop->collisionbox.MaxEdge * BS;
m_collisionbox.MinEdge += m_base_position;
m_collisionbox.MaxEdge += m_base_position;
return &m_collisionbox;
}
return NULL;
}

View file

@ -32,6 +32,7 @@ public:
static ServerActiveObject* create(ServerEnvironment *env, v3f pos, static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
const std::string &data); const std::string &data);
void step(float dtime, bool send_recommended); void step(float dtime, bool send_recommended);
inline aabb3f* getCollisionBox() { return NULL; }
private: private:
float m_timer1; float m_timer1;
float m_age; float m_age;
@ -51,6 +52,7 @@ public:
ItemStack createItemStack(); ItemStack createItemStack();
void punch(ServerActiveObject *puncher, float time_from_last_punch); void punch(ServerActiveObject *puncher, float time_from_last_punch);
float getMinimumSavedMovement(){ return 0.1*BS; } float getMinimumSavedMovement(){ return 0.1*BS; }
inline aabb3f* getCollisionBox() { return NULL; }
private: private:
std::string m_itemstring; std::string m_itemstring;
bool m_itemstring_changed; bool m_itemstring_changed;
@ -71,6 +73,7 @@ public:
std::string getClientInitializationData(); std::string getClientInitializationData();
std::string getStaticData(); std::string getStaticData();
void punch(ServerActiveObject *puncher, float time_from_last_punch); void punch(ServerActiveObject *puncher, float time_from_last_punch);
inline aabb3f* getCollisionBox() { return NULL; }
private: private:
bool m_is_active; bool m_is_active;
IntervalLimiter m_inactive_interval; IntervalLimiter m_inactive_interval;
@ -97,6 +100,7 @@ public:
std::string getStaticData(); std::string getStaticData();
void punch(ServerActiveObject *puncher, float time_from_last_punch); void punch(ServerActiveObject *puncher, float time_from_last_punch);
bool isPeaceful(){return false;} bool isPeaceful(){return false;}
inline aabb3f* getCollisionBox() { return NULL; }
private: private:
void doDamage(u16 d); void doDamage(u16 d);
@ -125,6 +129,7 @@ public:
void step(float dtime, bool send_recommended); void step(float dtime, bool send_recommended);
std::string getClientInitializationData(); std::string getClientInitializationData();
std::string getStaticData(); std::string getStaticData();
inline aabb3f* getCollisionBox() { return NULL; }
private: private:
bool m_is_active; bool m_is_active;
IntervalLimiter m_inactive_interval; IntervalLimiter m_inactive_interval;
@ -155,6 +160,7 @@ public:
void step(float dtime, bool send_recommended); void step(float dtime, bool send_recommended);
void punch(ServerActiveObject *puncher, float time_from_last_punch); void punch(ServerActiveObject *puncher, float time_from_last_punch);
bool isPeaceful(); bool isPeaceful();
inline aabb3f* getCollisionBox() { return NULL; }
private: private:
void sendPosition(); void sendPosition();
void setPropertyDefaults(); void setPropertyDefaults();
@ -222,6 +228,7 @@ public:
void setSprite(v2s16 p, int num_frames, float framelength, void setSprite(v2s16 p, int num_frames, float framelength,
bool select_horiz_by_yawpitch); bool select_horiz_by_yawpitch);
std::string getName(); std::string getName();
aabb3f* getCollisionBox();
private: private:
void sendPosition(bool do_interpolate, bool is_movement_end); void sendPosition(bool do_interpolate, bool is_movement_end);
@ -238,6 +245,7 @@ private:
v3f m_last_sent_velocity; 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;
aabb3f m_collisionbox;
}; };
#endif #endif

View file

@ -920,7 +920,7 @@ void ServerEnvironment::step(float dtime)
v3f playerpos = player->getPosition(); v3f playerpos = player->getPosition();
// Move // Move
player->move(dtime, *m_map, 100*BS); player->move(dtime, this, 100*BS);
/* /*
Add footsteps to grass Add footsteps to grass
@ -1803,6 +1803,22 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
} }
} }
//get a list of all active objects
core::list<ActiveObject*> ServerEnvironment::getActiveObjects() {
core::list<ActiveObject*> retval;
if (m_active_objects.size() > 0 )
{
for (core::map<u16, ServerActiveObject*>::Iterator iter=m_active_objects.getIterator();
iter.atEnd()==false; iter++) {
retval.push_back(iter.getNode()->getValue());
}
}
return retval;
}
#ifndef SERVER #ifndef SERVER
@ -1963,7 +1979,7 @@ void ClientEnvironment::step(float dtime)
Move the lplayer. Move the lplayer.
This also does collision detection. This also does collision detection.
*/ */
lplayer->move(dtime_part, *m_map, position_max_increment, lplayer->move(dtime_part, this, position_max_increment,
&player_collisions); &player_collisions);
} }
} }
@ -2034,7 +2050,7 @@ void ClientEnvironment::step(float dtime)
if(player->isLocal() == false) if(player->isLocal() == false)
{ {
// Move // Move
player->move(dtime, *m_map, 100*BS); player->move(dtime, this, 100*BS);
} }
@ -2311,6 +2327,21 @@ ClientEnvEvent ClientEnvironment::getClientEvent()
return m_client_event_queue.pop_front(); return m_client_event_queue.pop_front();
} }
//get a list of all active objects
core::list<ActiveObject*> ClientEnvironment::getActiveObjects() {
core::list<ActiveObject*> retval;
if (m_active_objects.size() > 0 )
{
for (core::map<u16, ClientActiveObject*>::Iterator iter=m_active_objects.getIterator();
iter.atEnd()==false; iter++)
{
retval.push_back(iter.getNode()->getValue());
}
}
return retval;
}
#endif // #ifndef SERVER #endif // #ifndef SERVER

View file

@ -87,6 +87,9 @@ public:
return m_time_of_day; return m_time_of_day;
} }
virtual IGameDef *getGameDef() = 0;
virtual core::list<ActiveObject*> getActiveObjects() = 0;
protected: protected:
// peer_ids in here should be unique, except that there may be many 0s // peer_ids in here should be unique, except that there may be many 0s
core::list<Player*> m_players; core::list<Player*> m_players;
@ -280,6 +283,8 @@ public:
// This makes stuff happen // This makes stuff happen
void step(f32 dtime); void step(f32 dtime);
//get a list of all active objects
core::list<ActiveObject*> getActiveObjects();
private: private:
/* /*
@ -462,6 +467,9 @@ public:
// Get event from queue. CEE_NONE is returned if queue is empty. // Get event from queue. CEE_NONE is returned if queue is empty.
ClientEnvEvent getClientEvent(); ClientEnvEvent getClientEvent();
//get a list of all active objects
core::list<ActiveObject*> getActiveObjects();
private: private:
ClientMap *m_map; ClientMap *m_map;
scene::ISceneManager *m_smgr; scene::ISceneManager *m_smgr;

View file

@ -199,9 +199,10 @@ LocalPlayer::~LocalPlayer()
{ {
} }
void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, void LocalPlayer::move(f32 dtime, Environment* env, f32 pos_max_d,
core::list<CollisionInfo> *collision_info) core::list<CollisionInfo> *collision_info)
{ {
Map& map = env->getMap();
INodeDefManager *nodemgr = m_gamedef->ndef(); INodeDefManager *nodemgr = m_gamedef->ndef();
v3f position = getPosition(); v3f position = getPosition();
@ -312,7 +313,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
v3f accel_f = v3f(0,0,0); v3f accel_f = v3f(0,0,0);
collisionMoveResult result = collisionMoveSimple(&map, m_gamedef, collisionMoveResult result = collisionMoveSimple(env,
pos_max_d, playerbox, player_stepheight, dtime, pos_max_d, playerbox, player_stepheight, dtime,
position, m_speed, accel_f); position, m_speed, accel_f);
@ -420,9 +421,9 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
} }
} }
void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d) void LocalPlayer::move(f32 dtime,Environment* env, f32 pos_max_d)
{ {
move(dtime, map, pos_max_d, NULL); move(dtime, env, pos_max_d, NULL);
} }
void LocalPlayer::applyControl(float dtime) void LocalPlayer::applyControl(float dtime)

View file

@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class Map; class Map;
class IGameDef; class IGameDef;
struct CollisionInfo; struct CollisionInfo;
class Environment;
class Player class Player
{ {
@ -42,7 +43,7 @@ public:
void resetInventory(); void resetInventory();
//void move(f32 dtime, Map &map); //void move(f32 dtime, Map &map);
virtual void move(f32 dtime, Map &map, f32 pos_max_d) = 0; virtual void move(f32 dtime, Environment* env, f32 pos_max_d) = 0;
v3f getSpeed() v3f getSpeed()
{ {
@ -231,9 +232,9 @@ public:
return true; return true;
} }
void move(f32 dtime, Map &map, f32 pos_max_d, void move(f32 dtime, Environment* env, f32 pos_max_d,
core::list<CollisionInfo> *collision_info); core::list<CollisionInfo> *collision_info);
void move(f32 dtime, Map &map, f32 pos_max_d); void move(f32 dtime, Environment* env, f32 pos_max_d);
void applyControl(float dtime); void applyControl(float dtime);

View file

@ -262,9 +262,20 @@ void ServerRemotePlayer::setHP(s16 hp_)
m_messages_out.push_back(aom); m_messages_out.push_back(aom);
} }
} }
s16 ServerRemotePlayer::getHP() s16 ServerRemotePlayer::getHP()
{ {
return hp; return hp;
} }
aabb3f* ServerRemotePlayer::getCollisionBox() {
m_collisionbox.MinEdge = aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS*2.0,BS/3.).MinEdge;
m_collisionbox.MaxEdge = aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS*2.0,BS/3.).MaxEdge;
m_collisionbox.MinEdge += m_position;
m_collisionbox.MaxEdge += m_position;
return &m_collisionbox;
}

View file

@ -40,7 +40,7 @@ public:
virtual bool isLocal() const virtual bool isLocal() const
{ return false; } { return false; }
virtual void move(f32 dtime, Map &map, f32 pos_max_d) virtual void move(f32 dtime, Environment* env, f32 pos_max_d)
{ {
} }
@ -93,9 +93,10 @@ public:
bool m_is_in_environment; bool m_is_in_environment;
// Incremented by step(), read and reset by Server // Incremented by step(), read and reset by Server
float m_time_from_last_punch; float m_time_from_last_punch;
aabb3f* getCollisionBox();
private: private:
bool m_position_not_sent; bool m_position_not_sent;
aabb3f m_collisionbox;
}; };
#endif #endif