Ogre的场景查询器具有强大的功能,而合理地利用掩码QueryMask,能够完成在游戏中对诸如“道具”,“墙壁”,“敌人”的分类处理。
场景查询器分为:光线查询(Ray Queries)、球体查询(Sphere Queries)、边界盒查询(Bounding-Box Queries)、边界平面查询(Bounding-Plane Queries)以及相交查询(Intersection Queries)。
我利用主角的位置mBodyNode->getPosition(),以半径1.5建立一个球体,通过该球体的场景查询,来实现主角物理检测的效果。
(按理说,边界盒查询要比球体查询达到的效果更好,但是考虑到边界盒的各个顶点离中心的距离并不相等,如果主角转身造成边界盒的旋转,主角在并未移动的情况下被场景查询器判断为发生了位移,很可能出现主角卡死的现象。虽然更精细的代码可以预防这种情况的出现并使游戏效果更好,但是我现在做的这个小游戏并不需要如此精巧,我以简单为主)
首先,我在GameState的初始化中建立一个Sphere Query:
p_sphere_scene_query_=p_scene_manager_->createSphereQuery(Sphere() );
p_sphere_scene_query_->setQueryTypeMask(Ogre::SceneManager::ENTITY_TYPE_MASK);
然后是场景中物体的初始化:
/****************code(Initailized Object)******************/
p_wall_entity_->setQueryFlags(1);//墙壁类物体的掩码为0001
p_prop_entity_->setQueryFlags(2);//道具类物体的掩码为0010
p_enemy_entity_->setQueryFlags(4);//敌人or陷阱类物体的掩码为0100
/*********code(初始化主角,主角的掩码为0,不需要检测)*************/
之后,主角的update(Ogre::Real timeSinceLastFrame)函数中,添加物理检测的代码:
p_sphere_scene_query_->setQueryMask(1);//检测墙壁
p_sphere_scene_query_->setSphere(Ogre::Sphere(p_player_node_->getPosition()+goal_direction_,1.5) );//圆心不是player的中心,而是中心靠前方向,实现碰撞的提前预测
SceneQueryResult result=p_sphere_scene_query_->execute();//计算
if(result.movables.begin() == result.movables.end())//如果result没有结果,说明碰撞不会发生
{
p_player_node_->translate(0, 0, timeSinceLastFrame* RUN_SPEED,Node::TS_LOCAL);//移动主角
}