转自:http://blog.csdn.net/weiqubo/article/details/7108363

Ogre采用树桩管理场景中的各种"元素"(摄像机、灯光、物体等),所有的东西都挂在"树"上,不在"树"上的东西不会被渲染。
Ogre::SceneManager就是"树"的管理者,Ogre::SceneNode是从SceneManager中创建的(当然BSP和8*树的管理也和这两个类有关,这暂时不讨论)。

AABB(轴对齐包围盒)

这个东西是碰撞检测的基础,和它类似的还有OBB(有向包围盒),由于OBB创建复杂,所以Ogre采用了AABB。

最简单的碰撞检测

通过Ogre::SceneNode::_getWorldAABB()可以取得这个叶子节点的AABB(Ogre::AxisAlignedBox),Ogre::AxisAlignedBox封装了对AABB的支持,该类的成员函数Ogre::AxisAlignedBox::intersects()可以判断一个AABB和"球体、点、面以及其他面"的相交情况(碰撞情况)。

m_SphereNode树的叶子,挂了一个"球"
m_CubeNode树的叶子,挂了一个"正方体"

  1. AxisAlignedBox spbox = m_SphereNode->_getWorldAABB();
  2. AxisAlignedBox cbbox = m_CubeNode->_getWorldAABB();
  3. if(spbox.intersects(cbbox))
  4. {
  5. //相交
  6. }
AxisAlignedBox spbox = m_SphereNode->_getWorldAABB();
AxisAlignedBox cbbox = m_CubeNode->_getWorldAABB();
if(spbox.intersects(cbbox))
{
//相交
}
 
附上简单的AABB测试程序,碰撞之后模型放大十倍,当然碰撞之后的事情你可以随意修改
  1. #include"ExampleApplication.h"
  2. #include <stdio.h>
  3. class CollionFrameListener:public ExampleFrameListener
  4. {
  5. private:
  6. SceneNode* m_node;
  7. SceneNode*m_node2;
  8. SceneManager* mSceneMgr;
  9. public:
  10. CollionFrameListener(RenderWindow* win, Camera* cam,SceneNode* node,SceneNode*node22,SceneManager* manager)
  11. :ExampleFrameListener(win,cam),m_node(node),m_node2(node22),mSceneMgr(manager)
  12. {
  13. }
  14. bool frameStarted(const FrameEvent& evt)
  15. {
  16. AxisAlignedBox spbox=m_node->_getWorldAABB();
  17. AxisAlignedBox cbbox=m_node2->_getWorldAABB();
  18. if(spbox.intersects(cbbox))
  19. {
  20. m_node2->setScale(10,10,10);
  21. }
  22. return ExampleFrameListener::frameStarted(evt);
  23. }
  24. };
  25. class CollionApplication:public ExampleApplication
  26. {
  27. protected:
  28. SceneNode*node1;
  29. SceneNode* node2;
  30. void createScene()
  31. {
  32. mSceneMgr->setAmbientLight(ColourValue(1,1,1));
  33. Entity* ent1=mSceneMgr->createEntity("robot","robot.mesh");
  34. node1=mSceneMgr->getRootSceneNode()->createChildSceneNode("robotnode");
  35. node1->attachObject(ent1);
  36. Entity *ent2=mSceneMgr->createEntity("ogrehead","ogreHead.mesh");
  37. node2=mSceneMgr->getRootSceneNode()->createChildSceneNode("ogreheadnode",Vector3(2,0,0));
  38. node2->attachObject(ent2);
  39. }
  40. void createFrameListener()
  41. {
  42. mFrameListener=new CollionFrameListener(mWindow,mCamera,node1,node2,mSceneMgr);
  43. mFrameListener->showDebugOverlay(true);
  44. mRoot->addFrameListener(mFrameListener);
  45. }
  46. };
  47. INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE,  LPSTR, int )
  48. {
  49. CollionApplication app;
  50. app.go();
  51. }
#include"ExampleApplication.h"
#include <stdio.h>
class CollionFrameListener:public ExampleFrameListener
{
private:
SceneNode* m_node;
SceneNode*m_node2;
SceneManager* mSceneMgr;
public:
CollionFrameListener(RenderWindow* win, Camera* cam,SceneNode* node,SceneNode*node22,SceneManager* manager)
:ExampleFrameListener(win,cam),m_node(node),m_node2(node22),mSceneMgr(manager)
{
}
bool frameStarted(const FrameEvent& evt)
{
AxisAlignedBox spbox=m_node->_getWorldAABB();
AxisAlignedBox cbbox=m_node2->_getWorldAABB();
if(spbox.intersects(cbbox))
{
m_node2->setScale(10,10,10);
}
return ExampleFrameListener::frameStarted(evt);
}
}; class CollionApplication:public ExampleApplication
{
protected:
SceneNode*node1;
SceneNode* node2;
void createScene()
{
mSceneMgr->setAmbientLight(ColourValue(1,1,1));
Entity* ent1=mSceneMgr->createEntity("robot","robot.mesh");
node1=mSceneMgr->getRootSceneNode()->createChildSceneNode("robotnode");
node1->attachObject(ent1);
Entity *ent2=mSceneMgr->createEntity("ogrehead","ogreHead.mesh");
node2=mSceneMgr->getRootSceneNode()->createChildSceneNode("ogreheadnode",Vector3(2,0,0));
node2->attachObject(ent2); }
void createFrameListener()
{
mFrameListener=new CollionFrameListener(mWindow,mCamera,node1,node2,mSceneMgr);
mFrameListener->showDebugOverlay(true);
mRoot->addFrameListener(mFrameListener);
}
};
INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int )
{
CollionApplication app;
app.go();
}
区域查询:

简单的讲就是,查询某一区域中有什么东西,分为AABB、球体、面查询。

  1. //创建一个球体查询,这里的100是m_SphereNode挂着的那个球体的半径
  2. SphereSceneQuery * pQuery=m_SceneMgr->createSphereQuery(Sphere(m_SphereNode->getPosition(),100));
  3. //执行这个查询
  4. SceneQueryResult QResult=pQuery->execute();
  5. //遍历查询列表找出范围内的物体
  6. for (SceneQueryResultMovableList::iterator iter = QResult.movables.begin(); iter != QResult.movables.end();++iter)
  7. {
  8. MovableObject* pObject=static_cast<MovableObject*>(*iter);
  9. if(pObject)
  10. {
  11. if(pObject->getMovableType()=="Entity")
  12. {
  13. Entity* ent = static_cast<Entity*>(pObject);
  14. //这里简化了操作,由于只有一个"球体"和一个"正方体",
  15. //所以只判断了球体和正方体的相交
  16. if(ent->getName()=="cube")
  17. {
  18. //改变位置防止物体重叠
  19. vtl=-vtl;
  20. m_SphereNode->translate(vtl);
  21. break;
  22. }
  23. }
  24. }
  25. }
    //创建一个球体查询,这里的100是m_SphereNode挂着的那个球体的半径
SphereSceneQuery * pQuery=m_SceneMgr->createSphereQuery(Sphere(m_SphereNode->getPosition(),100));
//执行这个查询
SceneQueryResult QResult=pQuery->execute();
//遍历查询列表找出范围内的物体
for (SceneQueryResultMovableList::iterator iter = QResult.movables.begin(); iter != QResult.movables.end();++iter)
{
MovableObject* pObject=static_cast<MovableObject*>(*iter);
if(pObject)
{
if(pObject->getMovableType()=="Entity")
{
Entity* ent = static_cast<Entity*>(pObject);
//这里简化了操作,由于只有一个"球体"和一个"正方体",
//所以只判断了球体和正方体的相交 if(ent->getName()=="cube")
{
//改变位置防止物体重叠
vtl=-vtl;
m_SphereNode->translate(vtl);
break;
}
}
}
}
新建一个空的ogre程序,将这个代码添加到你的cpp文件中就可以运行,这个例子是如果碰撞就将模型放大十倍,当然碰撞之后的代码你可以随便修改
  1. #include"ExampleApplication.h"
  2. #include <stdio.h>
  3. class CollionFrameListener:public ExampleFrameListener
  4. {
  5. private:
  6. SceneNode* m_node;
  7. SceneManager* mSceneMgr;
  8. public:
  9. CollionFrameListener(RenderWindow* win, Camera* cam,SceneNode* node,SceneManager* manager)
  10. :ExampleFrameListener(win,cam),m_node(node),mSceneMgr(manager)
  11. {
  12. }
  13. bool frameStarted(const FrameEvent& evt)
  14. {
  15. SphereSceneQuery * pQuery=mSceneMgr->createSphereQuery(Sphere(m_node->getPosition(),10));
  16. SceneQueryResult QResult=pQuery->execute();
  17. for (SceneQueryResultMovableList::iterator iter = QResult.movables.begin(); iter != QResult.movables.end();++iter)
  18. {
  19. MovableObject* pObject=static_cast<MovableObject*>(*iter);
  20. if(pObject)
  21. {
  22. if(pObject->getMovableType()=="Entity")
  23. {
  24. Entity* ent = static_cast<Entity*>(pObject);
  25. if(ent->getName()=="ogrehead")
  26. {
  27. m_node->setScale(10,10,10);
  28. break;
  29. }
  30. }
  31. }
  32. }
  33. return ExampleFrameListener::frameStarted(evt);
  34. }
  35. };
  36. class CollionApplication:public ExampleApplication
  37. {
  38. protected:
  39. SceneNode*node1;
  40. void createScene()
  41. {
  42. mSceneMgr->setAmbientLight(ColourValue(1,1,1));
  43. Entity* ent1=mSceneMgr->createEntity("robot","robot.mesh");
  44. node1=mSceneMgr->getRootSceneNode()->createChildSceneNode("robotnode");
  45. node1->attachObject(ent1);
  46. Entity *ent2=mSceneMgr->createEntity("ogrehead","ogreHead.mesh");
  47. SceneNode* node2=mSceneMgr->getRootSceneNode()->createChildSceneNode("ogreheadnode",Vector3(2,0,0));
  48. node2->attachObject(ent2);
  49. }
  50. void createFrameListener()
  51. {
  52. mFrameListener=new CollionFrameListener(mWindow,mCamera,node1,mSceneMgr);
  53. mFrameListener->showDebugOverlay(true);
  54. mRoot->addFrameListener(mFrameListener);
  55. }
  56. };
  57. INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE,  LPSTR, int )
  58. {
  59. CollionApplication app;
  60. app.go();
  61. }
#include"ExampleApplication.h"
#include <stdio.h>
class CollionFrameListener:public ExampleFrameListener
{
private:
SceneNode* m_node;
SceneManager* mSceneMgr;
public:
CollionFrameListener(RenderWindow* win, Camera* cam,SceneNode* node,SceneManager* manager)
:ExampleFrameListener(win,cam),m_node(node),mSceneMgr(manager)
{
}
bool frameStarted(const FrameEvent& evt)
{
SphereSceneQuery * pQuery=mSceneMgr->createSphereQuery(Sphere(m_node->getPosition(),10));
SceneQueryResult QResult=pQuery->execute();
for (SceneQueryResultMovableList::iterator iter = QResult.movables.begin(); iter != QResult.movables.end();++iter)
{
MovableObject* pObject=static_cast<MovableObject*>(*iter);
if(pObject)
{
if(pObject->getMovableType()=="Entity")
{
Entity* ent = static_cast<Entity*>(pObject);
if(ent->getName()=="ogrehead")
{
m_node->setScale(10,10,10);
break;
}
}
}
}
return ExampleFrameListener::frameStarted(evt);
}
}; class CollionApplication:public ExampleApplication
{
protected:
SceneNode*node1;
void createScene()
{
mSceneMgr->setAmbientLight(ColourValue(1,1,1));
Entity* ent1=mSceneMgr->createEntity("robot","robot.mesh");
node1=mSceneMgr->getRootSceneNode()->createChildSceneNode("robotnode");
node1->attachObject(ent1);
Entity *ent2=mSceneMgr->createEntity("ogrehead","ogreHead.mesh");
SceneNode* node2=mSceneMgr->getRootSceneNode()->createChildSceneNode("ogreheadnode",Vector3(2,0,0));
node2->attachObject(ent2);
}
void createFrameListener()
{
mFrameListener=new CollionFrameListener(mWindow,mCamera,node1,mSceneMgr);
mFrameListener->showDebugOverlay(true);
mRoot->addFrameListener(mFrameListener);
}
}; INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int )
{
CollionApplication app;
app.go();
}

相交查询:

遍历所有的对象,找到一对一对的相交物体(废话呀,相交当然至少两个物体)。

  1. //创建相交检测
  2. IntersectionSceneQuery* pISQuery=m_SceneMgr->createIntersectionQuery();
  3. //执行查询
  4. IntersectionSceneQueryResult QResult=pISQuery->execute();
  5. //遍历查询列表找出两个相交的物体
  6. for (SceneQueryMovableIntersectionList::iterator iter = QResult.movables2movables.begin();
  7. iter != QResult.movables2movables.end();++iter)
  8. {
  9. SceneQueryMovableObjectPair pObject=static_cast<SceneQueryMovableObjectPair>(*iter);
  10. //if(pObject)
  11. {
  12. String strFirst=pObject.first->getName();
  13. String strSecond=pObject.second->getName();
  14. //下面加入你自己的两个物体相交判断代码,或者简单的用AABB的判断方法,
  15. }
  16. }
//创建相交检测
IntersectionSceneQuery* pISQuery=m_SceneMgr->createIntersectionQuery();
//执行查询
IntersectionSceneQueryResult QResult=pISQuery->execute();
//遍历查询列表找出两个相交的物体
for (SceneQueryMovableIntersectionList::iterator iter = QResult.movables2movables.begin();
iter != QResult.movables2movables.end();++iter)
{ SceneQueryMovableObjectPair pObject=static_cast<SceneQueryMovableObjectPair>(*iter);
//if(pObject)
{
String strFirst=pObject.first->getName();
String strSecond=pObject.second->getName();
//下面加入你自己的两个物体相交判断代码,或者简单的用AABB的判断方法,
}
}

在Ogre中,可以创建一个查询器,比如球体查询器,AABB查询器,面查询器等。下面我们以最常用的球形查询器为例来说明:

如下面的代码,我们首先创建一个球形查询器,它需要定义一个球体,我们把它的位置,设置为摄像机的位置,半径为10,掩码为第二个参数,默认为-1,

通过掩码,可以把碰撞的物体分成不同的组,比如我们设置球形场景查询器的掩码为0x1,则它只检测和它掩码相同物体的碰撞。该摄像机检测到entity对象后,就把摄像机位置沿摄像机方向,向后移动一个单位,这样会实现碰撞检测,但是摄像机因为向后有个移动,所以会有抖动。

  1. //创建球形查询器,第二个参数表示掩码,默认情况下为-1
  2. SphereSceneQuery * pQuery=mSceneMgr->createSphereQuery(Sphere(mCamera->getPosition(),10));
  3. SceneQueryResult QResult=pQuery->execute();
  4. for (std::list<MovableObject*>::iterator iter = QResult.movables.begin(); iter != QResult.movables.end();++iter)
  5. {
  6. MovableObject* pObject=static_cast<MovableObject*>(*iter);
  7. if(pObject)
  8. {
  9. if(pObject->getMovableType()=="Entity")
  10. {
  11. Entity* ent = static_cast<Entity*>(pObject);
  12. //if(ent->getName()=="Head")
  13. //{
  14. //    //m_node->setScale(10,10,10);
  15. //    pObject->getParentNode()->scale(0.5,0.5,0.5);
  16. //    break;
  17. //}
  18. Ogre::Vector3 v = mCamera->getPosition();
  19. Ogre::Vector3 d = mCamera->getDirection();
  20. v = v + d*(-1);
  21. mCamera->setPosition(v);
  22. }
  23. }
  24. }全部的代码:
  //创建球形查询器,第二个参数表示掩码,默认情况下为-1
SphereSceneQuery * pQuery=mSceneMgr->createSphereQuery(Sphere(mCamera->getPosition(),10));
SceneQueryResult QResult=pQuery->execute();
for (std::list<MovableObject*>::iterator iter = QResult.movables.begin(); iter != QResult.movables.end();++iter)
{
MovableObject* pObject=static_cast<MovableObject*>(*iter);
if(pObject)
{
if(pObject->getMovableType()=="Entity")
{
Entity* ent = static_cast<Entity*>(pObject);
//if(ent->getName()=="Head")
//{
// //m_node->setScale(10,10,10);
// pObject->getParentNode()->scale(0.5,0.5,0.5);
// break;
//}
Ogre::Vector3 v = mCamera->getPosition();
Ogre::Vector3 d = mCamera->getDirection();
v = v + d*(-1);
mCamera->setPosition(v); }
}
}全部的代码:
  1. #include "ExampleApplication.h"
  2. RaySceneQuery* raySceneQuery = 0;
  3. // Event handler to add ability to alter curvature
  4. class TerrainFrameListener : public ExampleFrameListener
  5. {
  6. public:
  7. SceneManager* mSceneMgr;
  8. TerrainFrameListener(SceneManager *sceneMgr,RenderWindow* win, Camera* cam)
  9. : ExampleFrameListener(win, cam)
  10. {
  11. // Reduce move speed
  12. mMoveSpeed = 50;
  13. mSceneMgr = sceneMgr;
  14. }
  15. bool frameRenderingQueued(const FrameEvent& evt)
  16. {
  17. if( ExampleFrameListener::frameRenderingQueued(evt) == false )
  18. return false;
  19. // clamp to terrain
  20. static Ray updateRay;
  21. updateRay.setOrigin(mCamera->getPosition());
  22. updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y);
  23. raySceneQuery->setRay(updateRay);
  24. RaySceneQueryResult& qryResult = raySceneQuery->execute();
  25. RaySceneQueryResult::iterator i = qryResult.begin();
  26. if (i != qryResult.end() && i->worldFragment)//把摄像机定在地形10个单位高的地方。
  27. {
  28. mCamera->setPosition(mCamera->getPosition().x,
  29. i->worldFragment->singleIntersection.y + 10,
  30. mCamera->getPosition().z);
  31. }
  32. //创建球形查询器,第二个参数表示掩码,默认情况下为-1
  33. SphereSceneQuery * pQuery=mSceneMgr->createSphereQuery(Sphere(mCamera->getPosition(),10));
  34. SceneQueryResult QResult=pQuery->execute();
  35. for (std::list<MovableObject*>::iterator iter = QResult.movables.begin(); iter != QResult.movables.end();++iter)
  36. {
  37. MovableObject* pObject=static_cast<MovableObject*>(*iter);
  38. if(pObject)
  39. {
  40. if(pObject->getMovableType()=="Entity")
  41. {
  42. Entity* ent = static_cast<Entity*>(pObject);
  43. //if(ent->getName()=="Head")
  44. //{
  45. //    //m_node->setScale(10,10,10);
  46. //    pObject->getParentNode()->scale(0.5,0.5,0.5);
  47. //    break;
  48. //}
  49. Ogre::Vector3 v = mCamera->getPosition();
  50. Ogre::Vector3 d = mCamera->getDirection();
  51. v = v + d*(-1);
  52. mCamera->setPosition(v);
  53. }
  54. }
  55. }
  56. return true;
  57. }
  58. };
  59. class TerrainApplication : public ExampleApplication
  60. {
  61. public:
  62. TerrainApplication() {}
  63. ~TerrainApplication()
  64. {
  65. delete raySceneQuery;
  66. }
  67. protected:
  68. virtual void chooseSceneManager(void)
  69. {
  70. // Get the SceneManager, in this case a generic one
  71. mSceneMgr = mRoot->createSceneManager("TerrainSceneManager");
  72. }
  73. virtual void createCamera(void)
  74. {
  75. // Create the camera
  76. mCamera = mSceneMgr->createCamera("PlayerCam");
  77. // Position it at 500 in Z direction
  78. mCamera->setPosition(Vector3(128,25,128));
  79. // Look back along -Z
  80. mCamera->lookAt(Vector3(0,0,-300));
  81. mCamera->setNearClipDistance( 1 );
  82. mCamera->setFarClipDistance( 1000 );
  83. }
  84. // Just override the mandatory create scene method
  85. void createScene(void)
  86. {
  87. // Set ambient light
  88. mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
  89. // Create a light
  90. Light* l = mSceneMgr->createLight("MainLight");
  91. // Accept default settings: point light, white diffuse, just set position
  92. // NB I could attach the light to a SceneNode if I wanted it to move automatically with
  93. //  other objects, but I don't
  94. l->setPosition(20,80,50);
  95. // Fog
  96. // NB it's VERY important to set this before calling setWorldGeometry
  97. // because the vertex program picked will be different
  98. ColourValue fadeColour(0.93, 0.86, 0.76);
  99. mSceneMgr->setFog( FOG_LINEAR, fadeColour, .001, 500, 1000);
  100. mWindow->getViewport(0)->setBackgroundColour(fadeColour);
  101. std::string terrain_cfg("terrain.cfg");
  102. mSceneMgr -> setWorldGeometry( terrain_cfg );
  103. // Infinite far plane?
  104. if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE))
  105. {
  106. mCamera->setFarClipDistance(0);
  107. }
  108. // Set a nice viewpoint
  109. mCamera->setPosition(707,2500,528);
  110. mCamera->setOrientation(Quaternion(-0.3486, 0.0122, 0.9365, 0.0329));
  111. //mRoot -> showDebugOverlay( true );
  112. raySceneQuery = mSceneMgr->createRayQuery(
  113. Ray(mCamera->getPosition(), Vector3::NEGATIVE_UNIT_Y));//光线的位置和方向,垂直向下
  114. Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");
  115. //创建ogre head实体,测试通过射线查询movable来实现摄像机碰撞检测
  116. SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("ogreHead");
  117. headNode->attachObject(ogreHead);
  118. headNode->setPosition(500.0, 100.0, 500.0);
  119. headNode->scale(Vector3(2,2,2));
  120. }
  121. // Create new frame listener
  122. void createFrameListener(void)
  123. {
  124. mFrameListener= new TerrainFrameListener(mSceneMgr,mWindow, mCamera);
  125. mRoot->addFrameListener(mFrameListener);
  126. }
  127. };

Ogre碰撞检测的更多相关文章

  1. [比较老的文章]三维渲染引擎 OGRE 与 OSG 的比较综述

    1 .引言随着计算机可视化.虚拟现实技术的飞速发展,人们对实时真实感渲染以及场景复杂度提出了更高的要求.传统的直接使用底层图形接口如OpenGL.DirectX开发图形应用的模式越来越暴露出开发复杂性 ...

  2. MOGRE学习笔记(1) - OGRE简介及在vs2010下配置

    由于工作需要,花费了一段时间研究OGRE,但是研究的目的是要在vs2010平台下用c#进行MOGRE的开发,不得已才转到MGRE,步骤是首选熟悉MOGRE的一些基础知识,做到在winform下能用MO ...

  3. 转:关于 OGRE 与 OSG 的简单比较

    1   前言 我曾经细致阅读过 OGRE 和 OSG 官方提供的文档,有<Pro OGRE 3D Programming>.OGRE自带手册(manual).王锐老师等翻译的<Ope ...

  4. 转:高层游戏引擎——基于OGRE所实现的高层游戏引擎框架

    高层游戏引擎——基于OGRE所实现的高层游戏引擎框架 这是意念自己的毕业论文,在一个具体的实践之中,意念主要负责的是物件和GUI之外的其他游戏系统.意念才学疏陋,望众位前辈不吝赐教.由于代码质量不高. ...

  5. 关于OGRE与OSG的简单比较【转】

    关于OGRE与OSG的简单比较 林乃养 lnychina{at}gmail.com 浙江大学CAD&CG实验室 2010年3月27日 1 前言 我曾经细致阅读过OGRE和OSG官方提供的文档, ...

  6. 关于 OGRE 与 OSG 的简单比较 (转)

    关于 OGRE 与 OSG 的简单比较 1   前言 我曾经细致阅读过 OGRE 和 OSG 官方提供的文档,有<Pro OGRE 3D Programming>.OGRE自带手册(man ...

  7. javascript动画系列第三篇——碰撞检测

    前面的话 前面分别介绍了拖拽模拟和磁性吸附,当可视区域内存在多个可拖拽元素,就出现碰撞检测的问题,这也是javascript动画的一个经典问题.本篇将详细介绍碰撞检测 原理介绍 碰撞检测的方法有很多, ...

  8. 使用 JavaScript 和 canvas 做精确的像素碰撞检测

    原文地址:Pixel accurate collision detection with Javascript and Canvas 译者:nzbin 我正在开发一个需要再次使用碰撞检测的游戏.我通常 ...

  9. JavaScript动画-碰撞检测

    ▓▓▓▓▓▓ 大致介绍 碰撞检测是指在页面中有多个元素时,拖拽一个元素会出现碰撞问题,碰撞检测是以模拟拖拽和磁性吸附中的范围限定为基础的 效果:碰撞检测 ▓▓▓▓▓▓ 碰撞检测 先来看看碰撞检测的原理 ...

随机推荐

  1. 不能使用tpcc-mysql测试OneProxy

    因为Proxy类的中间件不适合实现prepared statement,所以无法测试,导致我们无法使用标准的测试工具去发布OneProxy的测试结果

  2. linux笔记:RPM软件包管理-rpm命令管理

    rpm包命名原则: rpm包的依赖性: 包名和包全名: rpm软件包安装.升级和卸载: rpm软件包查询: 从rpm包中提取指定文件:

  3. 百度地图API首页 -- 鼠标经过:类似翻页效果和 类似锚点链接效果

    var timer; $("li").on("mouseover",function(){ clearTimeout(timer); timer=null; $ ...

  4. Datatable的Select()方法简介

    DataTable是我们在进行开发时经常用到的一个类,并且经常需要对DataTable中的数据进行筛选等操作,下面就介绍一下Datatable中经常用到的一个方法——Select,微软提供了四个函数的 ...

  5. DSP基础学习-ADC同步采样

    DSP基础学习-ADC同步采样 彭会锋 2015-04-28 20:31:06 在DSP28027 LauchPad学习过程中,关于ADC同步采样和顺序采样的区别稍加研究了一下,发现里面还真有些门道, ...

  6. ubuntu环境变量添加变量

    1.sudo gedit /etc/profile打开环境变量文件夹 2.在文件末尾另起一行输入要加入的环境变量 格式: export XXXXXX=XXXXXX 3.重启 OK

  7. phantomjs 乱码解决

    system = require('system') //传递一些需要的参数给js文件 address = system.args[1];//获得命令行第二个参数 ,也就是指定要加载的页面地址,接下来 ...

  8. url重写后发布出错问题

    iis7 配置urlrewriter重写失效的问题 在IIS7下,如果使用微软的 URLRewriter 重写控件则需要在WEB.CONFIG中配置以下信息 第一个配置: <configSect ...

  9. python中字符串与列表的相互转换

    列表转字符串 list1 = ['abc' , 'def' , 'ghi'] str1 = ','.join(list1) str1 = '##'.join(list1) 字符串转列表 str1 = ...

  10. 198. 213. 337. House Robber -- 不取相邻值的最大值

    198. House Robber You are a professional robber planning to rob houses along a street. Each house ha ...