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 aabb3f* getCollisionBox() = 0;
protected:
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 "nodedef.h"
#include "gamedef.h"
#include "environment.h"
#include "log.h"
#include <vector>
#include <list>
// Helper function:
// 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 stepheight, f32 dtime,
v3f &pos_f, v3f &speed_f, v3f &accel_f)
{
Map * map = &env->getMap();
IGameDef * gamedef = env->getGameDef();
TimeTaker tt("collisionMoveSimple");
collisionMoveResult result;
@ -252,6 +257,27 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
assert(cboxes.size() == is_unloaded.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
*/
@ -277,7 +303,8 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
loopcount++;
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;
break;
}
@ -422,7 +449,7 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
return result;
}
collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
collisionMoveResult collisionMovePrecise(Environment* env,
f32 pos_max_d, const aabb3f &box_0,
f32 stepheight, f32 dtime,
v3f &pos_f, v3f &speed_f, v3f &accel_f)
@ -470,7 +497,7 @@ collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
dtime_downcount = 0;
}
collisionMoveResult result = collisionMoveSimple(map, gamedef,
collisionMoveResult result = collisionMoveSimple(env,
pos_max_d, box_0, stepheight, dtime_part,
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 <vector>
class Map;
class IGameDef;
class Environment;
struct collisionMoveResult
{
@ -42,13 +41,13 @@ struct collisionMoveResult
};
// 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 stepheight, f32 dtime,
v3f &pos_f, v3f &speed_f, v3f &accel_f);
// 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 stepheight, f32 dtime,
v3f &pos_f, v3f &speed_f, v3f &accel_f);

View file

@ -1701,6 +1701,7 @@ private:
int m_anim_num_frames;
float m_anim_framelength;
float m_anim_timer;
aabb3f m_collisionbox;
public:
LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env):
@ -1879,8 +1880,7 @@ public:
v3f p_pos = m_position;
v3f p_velocity = m_velocity;
v3f p_acceleration = m_acceleration;
IGameDef *gamedef = env->getGameDef();
moveresult = collisionMovePrecise(&env->getMap(), gamedef,
moveresult = collisionMovePrecise(env,
pos_max_d, box, stepheight, dtime,
p_pos, p_velocity, p_acceleration);
// Apply results
@ -2047,6 +2047,21 @@ public:
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
@ -2070,6 +2085,7 @@ private:
LocalPlayer *m_local_player;
float m_damage_visual_timer;
bool m_dead;
aabb3f m_collisionbox;
public:
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()
{
if(m_node)

View file

@ -165,8 +165,7 @@ void ItemSAO::step(float dtime, bool send_recommended)
v3f pos_f_old = pos_f;
v3f accel_f = v3f(0,0,0);
f32 stepheight = 0;
IGameDef *gamedef = m_env->getGameDef();
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
moveresult = collisionMoveSimple(m_env,
pos_max_d, box, stepheight, dtime,
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 accel_f = v3f(0,0,0);
f32 stepheight = 0;
IGameDef *gamedef = m_env->getGameDef();
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
moveresult = collisionMoveSimple(m_env,
pos_max_d, box, stepheight, dtime,
pos_f, m_speed_f, accel_f);
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 accel_f = v3f(0,0,0);
f32 stepheight = 0;
IGameDef *gamedef = m_env->getGameDef();
moveresult = collisionMovePrecise(&m_env->getMap(), gamedef,
moveresult = collisionMovePrecise(m_env,
pos_max_d, box, stepheight, dtime,
pos_f, m_speed_f, accel_f);
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 accel_f = v3f(0,0,0);
f32 stepheight = 0;
IGameDef *gamedef = m_env->getGameDef();
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
moveresult = collisionMoveSimple(m_env,
pos_max_d, box, stepheight, dtime,
pos_f, m_speed_f, accel_f);
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_velocity = m_velocity;
v3f p_acceleration = m_acceleration;
IGameDef *gamedef = m_env->getGameDef();
moveresult = collisionMovePrecise(&m_env->getMap(), gamedef,
moveresult = collisionMovePrecise(m_env,
pos_max_d, box, stepheight, dtime,
p_pos, p_velocity, p_acceleration);
// Apply results
@ -1844,3 +1839,18 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
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,
const std::string &data);
void step(float dtime, bool send_recommended);
inline aabb3f* getCollisionBox() { return NULL; }
private:
float m_timer1;
float m_age;
@ -51,6 +52,7 @@ public:
ItemStack createItemStack();
void punch(ServerActiveObject *puncher, float time_from_last_punch);
float getMinimumSavedMovement(){ return 0.1*BS; }
inline aabb3f* getCollisionBox() { return NULL; }
private:
std::string m_itemstring;
bool m_itemstring_changed;
@ -71,6 +73,7 @@ public:
std::string getClientInitializationData();
std::string getStaticData();
void punch(ServerActiveObject *puncher, float time_from_last_punch);
inline aabb3f* getCollisionBox() { return NULL; }
private:
bool m_is_active;
IntervalLimiter m_inactive_interval;
@ -97,6 +100,7 @@ public:
std::string getStaticData();
void punch(ServerActiveObject *puncher, float time_from_last_punch);
bool isPeaceful(){return false;}
inline aabb3f* getCollisionBox() { return NULL; }
private:
void doDamage(u16 d);
@ -125,6 +129,7 @@ public:
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
inline aabb3f* getCollisionBox() { return NULL; }
private:
bool m_is_active;
IntervalLimiter m_inactive_interval;
@ -155,6 +160,7 @@ public:
void step(float dtime, bool send_recommended);
void punch(ServerActiveObject *puncher, float time_from_last_punch);
bool isPeaceful();
inline aabb3f* getCollisionBox() { return NULL; }
private:
void sendPosition();
void setPropertyDefaults();
@ -222,6 +228,7 @@ public:
void setSprite(v2s16 p, int num_frames, float framelength,
bool select_horiz_by_yawpitch);
std::string getName();
aabb3f* getCollisionBox();
private:
void sendPosition(bool do_interpolate, bool is_movement_end);
@ -238,6 +245,7 @@ private:
v3f m_last_sent_velocity;
float m_last_sent_position_timer;
float m_last_sent_move_precision;
aabb3f m_collisionbox;
};
#endif

View file

@ -920,7 +920,7 @@ void ServerEnvironment::step(float dtime)
v3f playerpos = player->getPosition();
// Move
player->move(dtime, *m_map, 100*BS);
player->move(dtime, this, 100*BS);
/*
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
@ -1963,7 +1979,7 @@ void ClientEnvironment::step(float dtime)
Move the lplayer.
This also does collision detection.
*/
lplayer->move(dtime_part, *m_map, position_max_increment,
lplayer->move(dtime_part, this, position_max_increment,
&player_collisions);
}
}
@ -2034,7 +2050,7 @@ void ClientEnvironment::step(float dtime)
if(player->isLocal() == false)
{
// 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();
}
//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

View file

@ -87,6 +87,9 @@ public:
return m_time_of_day;
}
virtual IGameDef *getGameDef() = 0;
virtual core::list<ActiveObject*> getActiveObjects() = 0;
protected:
// peer_ids in here should be unique, except that there may be many 0s
core::list<Player*> m_players;
@ -280,6 +283,8 @@ public:
// This makes stuff happen
void step(f32 dtime);
//get a list of all active objects
core::list<ActiveObject*> getActiveObjects();
private:
/*
@ -462,6 +467,9 @@ public:
// Get event from queue. CEE_NONE is returned if queue is empty.
ClientEnvEvent getClientEvent();
//get a list of all active objects
core::list<ActiveObject*> getActiveObjects();
private:
ClientMap *m_map;
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)
{
Map& map = env->getMap();
INodeDefManager *nodemgr = m_gamedef->ndef();
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);
collisionMoveResult result = collisionMoveSimple(&map, m_gamedef,
collisionMoveResult result = collisionMoveSimple(env,
pos_max_d, playerbox, player_stepheight, dtime,
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)

View file

@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class Map;
class IGameDef;
struct CollisionInfo;
class Environment;
class Player
{
@ -42,7 +43,7 @@ public:
void resetInventory();
//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()
{
@ -231,9 +232,9 @@ public:
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);
void move(f32 dtime, Map &map, f32 pos_max_d);
void move(f32 dtime, Environment* env, f32 pos_max_d);
void applyControl(float dtime);

View file

@ -262,9 +262,20 @@ void ServerRemotePlayer::setHP(s16 hp_)
m_messages_out.push_back(aom);
}
}
s16 ServerRemotePlayer::getHP()
{
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
{ 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;
// Incremented by step(), read and reset by Server
float m_time_from_last_punch;
aabb3f* getCollisionBox();
private:
bool m_position_not_sent;
aabb3f m_collisionbox;
};
#endif