예제 #1
0
        void CollisionDestroyPositioner::affect(float ms)
        {
            Entity *entity = getEntity();
            CollisionDetector *collisionDetector =
                    entity->getLevel()->getCollisionDetector();

            /* Convert vectors to ellipse space. */
            Vector2D position = entity->getPosition();
            Vector2D velocity = entity->getVelocity() * ms;

            /* Used later. */
            float time;
            Vector2D collision;

            if(collisionDetector->getClosestCollision(
                    entity->getRadius(), position, velocity,
                    &time, &collision)) {
                entity->setGarbage();
                entity->setPosition(collision);
            } else {
                entity->setPosition(position + velocity);
            }

            velocity = entity->getVelocity() + getGravity() * ms;
            entity->setVelocity(velocity);
        }
예제 #2
0
/*
Method is responsible for runtime checks:
	- Collision detection
	- Food eaten
	- Drawing
	Return(true) -> GameOver
	Return(false)-> Keep running
*/
bool GameController::performGameRuntimeChecks(CInputManager &inputManager,
											  unsigned long &score, CollisionDetector &collisionDetector,
											  DrawEngine drawEngine, int key, Snake &snake, vector<Cell> &foodList,
											  FoodProvider &foodProvider, Cell lastCell)
{
	//If collision detected
	if(collisionDetector.collisionDetected(snake))
	{
		char message[] = "GAME OVER! <Press any key>";
		drawEngine.showMessage(message);
		inputManager.GetNextKeyWait(&key);
		return true;
	}
	//Food eaten
	else if(collisionDetector.foodEaten(snake, foodList))
	{
		//Setting new score
		score += snake.getCells().size()*2;
		//Draw score
		drawEngine.updateScore(score);
		//Add cell
		snake.addCell();
		//Recieving new foodList
		vector<Cell> &list = foodProvider.provideFood(snake, drawEngine.getWindownWidth(), 
			drawEngine.getMenuBorderHeight());
		foodList = list;
	}
	//Draw snake
	drawEngine.drawSnake(snake, lastCell);
	//Draw food
	drawEngine.drawFood(foodList);
	return false;
}
예제 #3
0
void GameController::initGame()
{
	//Initializing variables
	DrawEngine drawEngine;
	CInputManager inputManager;
	CLoopTimer loopTimer;
	CollisionDetector collisionDetector;
	FoodProvider foodProvider;
	GameStatus gameStatus;
	
	//Initializing console
	drawEngine.initialize();
	collisionDetector.initialize(drawEngine.getWindownWidth(), drawEngine.getMenuBorderHeight());
	//Set start values
	gameStatus.setGameStatus(gameStatus.MAIN_MENU);
	unsigned long score = 0;
	
	while(gameStatus.getGameStatus() != gameStatus.QUIT)
	{
		//Runs main menu
		if(gameStatus.getGameStatus() == gameStatus.MAIN_MENU)
		{
			drawEngine.showMenu(inputManager, gameStatus);
		}
		//Run game
		else
		{
			score = 0;
			runGame(inputManager, loopTimer, score, collisionDetector, foodProvider, drawEngine);
			gameStatus.setGameStatus(gameStatus.MAIN_MENU);
		}
	}
}
예제 #4
0
파일: Player.cpp 프로젝트: Clever-Boy/mario
void Player::handleDestructableCollisions(std::vector<Destructable*> destructables, Camera* camera)
{
	CollisionDetector detector;
	for(int i = 0; i < destructables.size(); ++i)
	{
		for(int j = 0; j < collisionPoints.size(); ++j)
		{
			CollisionPoint before = collisionPoints.at(j);
			CollisionPoint translatedPoint(before.x + movementVector.x, before.y + movementVector.y, before.type);
			if (detector.checkCollision(translatedPoint, destructables.at(i), camera))
			{
				switch (collisionPoints.at(j).type)
				{
					case HEAD: 
						movementVector.y = destructables.at(i)->getBoundingBox().y + destructables.at(i)->getBoundingBox().h + 1;
						break;
					case FEET:
						movementVector.y = destructables.at(i)->getBoundingBox().y - m_h;
						m_airbourne = false;
						break;
					case LEFT:
						movementVector.x = destructables.at(i)->getBoundingBox().x + destructables.at(i)->getBoundingBox().w + 1; // + camera->getOffsetX();
						break;
					case RIGHT:
						movementVector.x = destructables.at(i)->getBoundingBox().x - m_w - 1; // + camera->getOffsetX();
						break;
				}
			}
		}
	}
}
예제 #5
0
void cppCollisionDetection(double delta)  
{
	s0 = new Surface();
	s1 = new Surface();
	h0 = new Hierarchy();
	h1 = new Hierarchy();

	s0->Add(0,0,0,1,0);
	s0->CreateSurface();
	s1->Add(0,0,0,1,0);
	s1->CreateSurface();

	Triple t0(-delta,0,0);
	Triple t1(delta,0,0);
	RotationMatrix m0,m1;
	h0->Initialize(s0);
	h0->Behavior(&m0,&t0);
	h1->Initialize(s1);
	h1->Behavior(&m1,&t1);

	CollisionDetector cd;
	cd.CheckCollision(h0,h1);
	cd.Select(1);

	s->CreateSurface(s0,s1,delta); 

	delete h0;
	delete h1;

	delete s0;
	delete s1;
}
TEST_F(CollisionDetectorTest, projectile_projectile) {
    CollisionDetector detector;
    NiceMock<MockGameObject> proj_1;
    NiceMock<MockHitbox> proj_1_hitbox;
    NiceMock<MockGameObject> proj_2;
    NiceMock<MockHitbox> proj_2_hitbox;
    ON_CALL(proj_1, hitbox()).WillByDefault(ReturnRef(proj_1_hitbox));
    ON_CALL(proj_1_hitbox, is_overlapping(Ref(proj_2_hitbox))).WillByDefault(Return(true));
    ON_CALL(proj_2, hitbox()).WillByDefault(ReturnRef(proj_2_hitbox));
    ON_CALL(proj_2_hitbox, is_overlapping(Ref(proj_1_hitbox))).WillByDefault(Return(true));
    EXPECT_CALL(proj_1, notify_collision(Ref(proj_2))).Times(0);
    EXPECT_CALL(proj_2, notify_collision(Ref(proj_1))).Times(0);
    detector.add_projectile(Team::FRIENDLY, proj_1);
    detector.add_projectile(Team::ENEMY, proj_2);
    detector.check_collisions();
}
TEST_F(CollisionDetectorTest, projectile_gameobject_no_collision) {
    CollisionDetector detector;
    NiceMock<MockGameObject> projectile;
    NiceMock<MockHitbox> proj_hitbox;
    NiceMock<MockGameObject> gameobj;
    NiceMock<MockHitbox> gameobj_hitbox;
    ON_CALL(projectile, hitbox()).WillByDefault(ReturnRef(proj_hitbox));
    ON_CALL(proj_hitbox, is_overlapping(Ref(gameobj_hitbox))).WillByDefault(Return(false));
    ON_CALL(gameobj, hitbox()).WillByDefault(ReturnRef(gameobj_hitbox));
    ON_CALL(gameobj_hitbox, is_overlapping(Ref(proj_hitbox))).WillByDefault(Return(false));
    EXPECT_CALL(projectile, notify_collision(Ref(gameobj))).Times(0);
    EXPECT_CALL(gameobj, notify_collision(Ref(projectile))).Times(0);
    detector.add_projectile(Team::FRIENDLY, projectile);
    detector.add_game_object(Team::ENEMY, gameobj);
    detector.check_collisions();
}
TEST_F(CollisionDetectorTest, gameobject_gameobject_no_collision) {
    CollisionDetector detector;
    NiceMock<MockGameObject> gameobj_1;
    NiceMock<MockHitbox> hitbox_1;
    NiceMock<MockGameObject> gameobj_2;
    NiceMock<MockHitbox> hitbox_2;
    ON_CALL(gameobj_1, hitbox()).WillByDefault(ReturnRef(hitbox_1));
    ON_CALL(hitbox_1, is_overlapping(Ref(hitbox_2))).WillByDefault(Return(false));
    ON_CALL(gameobj_2, hitbox()).WillByDefault(ReturnRef(hitbox_2));
    ON_CALL(hitbox_2, is_overlapping(Ref(hitbox_1))).WillByDefault(Return(false));
    EXPECT_CALL(gameobj_1, notify_collision(Ref(gameobj_2))).Times(0);
    EXPECT_CALL(gameobj_2, notify_collision(Ref(gameobj_1))).Times(0);
    detector.add_game_object(Team::FRIENDLY, gameobj_1);
    detector.add_game_object(Team::ENEMY, gameobj_2);
    detector.check_collisions();
}
예제 #9
0
void SimpleCollisionHandler::handleCollisions(TwoDScene &scene, CollisionDetector &detector, const VectorXs &oldpos, VectorXs &oldvel, scalar dt)
{
  class SimpleCollisionCallback : public DetectionCallback
  {
  public:
    SimpleCollisionCallback(TwoDScene &scene, SimpleCollisionHandler &handler) : scene(scene), handler(handler) {}

    virtual void ParticleParticleCallback(int idx1, int idx2)
    {
      VectorXs n(2);
      if(handler.detectParticleParticle(scene, idx1, idx2, n))
	{
	  handler.addParticleParticleImpulse(idx1, idx2, n, 0);
	  handler.respondParticleParticle(scene, idx1, idx2, n);
	}
    }
    
    virtual void ParticleEdgeCallback(int vidx, int eidx)
    {
      VectorXs n(2);
      if(handler.detectParticleEdge(scene, vidx, eidx, n))
	{
	  handler.addParticleEdgeImpulse(vidx, eidx, n, 0);
	  handler.respondParticleEdge(scene, vidx, eidx, n);
	}
    }
    
    virtual void ParticleHalfplaneCallback(int vidx, int hidx)
    {
      VectorXs n(2);
      if(handler.detectParticleHalfplane(scene, vidx, hidx, n))
	{
	  handler.addParticleHalfplaneImpulse(vidx, hidx, n, 0);
	  handler.respondParticleHalfplane(scene, vidx, hidx, n);
	}
    }

    TwoDScene &scene;
    SimpleCollisionHandler &handler;
  };

  SimpleCollisionCallback callback(scene, *this);
  detector.performCollisionDetection(scene, scene.getX(), scene.getX(), callback);
}
예제 #10
0
bool checkCollisions(Device::Ptr device, const State &state, const CollisionDetector &detector, const Q &q) {
	State testState;
	CollisionDetector::QueryResult data;
	bool colFrom;

	testState = state;
	device->setQ(q,testState);
	colFrom = detector.inCollision(testState,&data);
	if (colFrom) {
		cerr << "Configuration in collision: " << q << endl;
		cerr << "Colliding frames: " << endl;
		FramePairSet fps = data.collidingFrames;
		for (FramePairSet::iterator it = fps.begin(); it != fps.end(); it++) {
			cerr << (*it).first->getName() << " " << (*it).second->getName() << endl;
		}
		return false;
	}
	return true;
}
예제 #11
0
int main(int argc, char** argv) {
  // Check arguments
  if (argc < 5) {
    std::cerr << "Usage: " << argv[0] << " NODES_FILE TETS_FILE\n";
    exit(1);
  }

  // Construct the first mesh
  MeshType mesh;
  //construct the second mesh
  MeshType mesh2;

  std::vector<typename MeshType::node_type> mesh_node;
  // Read all Points and add them to the Mesh
  std::ifstream nodes_file(argv[1]);
  Point p;
  while (CS207::getline_parsed(nodes_file, p)) {
    mesh_node.push_back(mesh.add_node(p));
  }

  // Read all mesh triangles and add them to the Mesh
  std::ifstream tris_file(argv[2]);
  std::array<int,3> t;
  while (CS207::getline_parsed(tris_file, t)) {
    mesh.add_triangle(mesh_node[t[0]], mesh_node[t[1]], mesh_node[t[2]]);
  }

  std::vector<typename MeshType::node_type> mesh_node2;
  // Read all Points and add them to the Mesh
  std::ifstream nodes_file2(argv[3]);
  while (CS207::getline_parsed(nodes_file2, p)) {
    mesh_node2.push_back(mesh2.add_node(p));
  }

  // Read all mesh triangles and add them to the Mesh
  std::ifstream tris_file2(argv[4]);
  while (CS207::getline_parsed(tris_file2, t)) {
    mesh2.add_triangle(mesh_node2[t[0]], mesh_node2[t[1]], mesh_node2[t[2]]);
  }
  
  //move the second mesh to the specified position
  for(auto it = mesh2.node_begin();it!=mesh2.node_end();++it){
    (*it).position().elem[1] +=4 ;
    (*it).position().elem[2] +=4 ;
  }

  // Print out the stats
  std::cout << mesh.num_nodes() << " "
            << mesh.num_edges() << " "
            << mesh.num_triangles() << std::endl;
  std::cout << mesh2.num_nodes() << " "
            << mesh2.num_edges() << " "
            << mesh2.num_triangles() << std::endl;



  //set the mass and velocity of each Node for the first mesh
  for (auto it = mesh.node_begin(); it != mesh.node_end(); ++it){
    (*it).value().mass = float(1)/mesh.num_nodes();
    (*it).value().velocity = Point(0, 10, 10);
  }
  //set the mass and velocity of each Node for the second mesh
  for (auto it = mesh2.node_begin(); it != mesh2.node_end(); ++it){
    (*it).value().mass = float(1)/mesh.num_nodes();
    (*it).value().velocity = Point(0, -10, -10);
  }

  //set K and L for each edge
  for (auto it = mesh.node_begin(); it != mesh.node_end(); ++it)
  {
    for (auto j = (*it).edge_begin(); j != (*it).edge_end(); ++j){
       (*j).value().L = (*j).length();
       (*j).value().K = 16000;
    }
  }

  for (auto it = mesh2.node_begin(); it != mesh2.node_end(); ++it)
  {
    for (auto j = (*it).edge_begin(); j != (*it).edge_end(); ++j){
       (*j).value().L = (*j).length();
       (*j).value().K = 16000;
    }
  }


  // Launch the SDLViewer
  CS207::SDLViewer viewer;
  auto node_map = viewer.empty_node_map(mesh);
  viewer.launch();

  viewer.add_nodes(mesh.node_begin(), mesh.node_end(), node_map);
  viewer.add_edges(mesh.edge_begin(), mesh.edge_end(), node_map);
  viewer.add_nodes(mesh2.node_begin(), mesh2.node_end(), node_map);
  viewer.add_edges(mesh2.edge_begin(), mesh2.edge_end(), node_map);

  viewer.center_view();
  
  //Begin the mass-spring simulation
  double dt = 0.0002;
  double t_start = 0.0;
  double t_end   = 10.0;
   
  //three color parameter
  int color1 = 1; 
  int color2 = 1; 
  int color3 = 1; 
  
  //Create listener
  Pause_listener* pause = new Pause_listener(dt); 
  Speed_listener* speed = new Speed_listener(dt, dt); 
  XYZ_listener<MeshType>* xyz = new XYZ_listener<MeshType>(&mesh);
  Color_listener* col = new Color_listener(&color1, &color2, &color3);
  
  //add listener
  viewer.add_listener(pause);
  viewer.add_listener(speed);
  viewer.add_listener(xyz);
  viewer.add_listener(col);

  //Initialize forces
  WindForce wind_force(Point(0,100,200));
  PressureForce<typename MeshType::node_type, MeshType> pressure_force(1, 2500, &mesh);
  DampingForce damp_force(float(1)/mesh.num_nodes());
  //auto force = make_combined_force(MassSpringForce(), GravityForce(), make_combined_force(pressure_force, damp_force, wind_force));
  auto force = make_combined_force(MassSpringForce(), make_combined_force(pressure_force, damp_force, wind_force));
  
  //Initialize constriants
  auto constraint = PlaneConstraint<MeshType>(-4);

  //simulation processing   
  for (double t = t_start; t < t_end; t += dt) {
    constraint(mesh, 0);
    constraint(mesh2, 0);
    //define a collision constrain
    auto collision_constrain = CollisionConstraint<MeshType>();
    //add the forces to the meshs at each dt
    symp_euler_step(mesh, t, dt, force);
    symp_euler_step(mesh2, t, dt, force);
    
    //detec the collision betweent the two meshes
    CollisionDetector<MeshType> c;
    c.add_object(mesh);
    c.add_object(mesh2);
    c.check_collisions();
    std::vector<unsigned> collision;
    std::vector<unsigned> collision2;

    //find the corresponding mesh for each node
    for (auto it=c.begin(); it!= c.end(); ++it){
      auto boom = *it;
      Node n = boom.n1;
      if (boom.mesh1 == &mesh)
        collision.push_back(n.index());
      if (boom.mesh1 == &mesh2)
        collision2.push_back(n.index());
    }

    //add the collision constrain to the meshes
    collision_constrain(mesh,mesh2,collision,collision2);
    viewer.set_label(t);
    
    //update with removed nodes
    //clear teh viewer's node
    viewer.clear();
    node_map.clear();
    //update viewer with new positions and new edges
    viewer.add_nodes(mesh.node_begin(), mesh.node_end(), color(color1, color2, color3), node_map);
    viewer.add_edges(mesh.edge_begin(), mesh.edge_end(), node_map);
    viewer.add_nodes(mesh2.node_begin(), mesh2.node_end(), color(color1, color2, color3), node_map);
    viewer.add_edges(mesh2.edge_begin(), mesh2.edge_end(), node_map);

    // These lines slow down the animation for small graphs
    if (mesh.num_nodes() < 100)
      CS207::sleep(0.001);
  }

  return 0;
}
예제 #12
0
int main(int argc, char* args[]) {
	Renderer* renderer = new Renderer();

	if(!renderer->init()) {
		printf( "Failed to initialize!\n" );
	} else {
		Character* c = new Character(new Texture("res/img/dot.bmp", 200, 200));
		renderer->addTexture(new Texture("res/img/waterlevel2.png", 0, 0));

		renderer->render();

		renderer->addTexture(c->getTexture());

		bool quit = false;

		SDL_Event e;

		LoadCollisionMap lcm;
		list<Circle> circlesList;
		circlesList = lcm.load();

		list<Circle> l;
		Circle c1(200,0,10);
		l.push_back(c1);

		CollisionDetector cd;
		int y = 0;

		while(!cd.hasCollision(circlesList, l)) {
			l.pop_back();
			y += 1;
			Circle c1(200,y,10);
			l.push_back(c1);
		}
		y -= 1;
		c->setPosX(200);
		c->setPosY(y);

		renderer->render();

		int mVelX = 0;
		int DOT_VEL = 1;

		while(!quit) {
			while(SDL_PollEvent(&e) != 0) {
				if(e.type == SDL_QUIT) {
					quit = true;
				}
				if(e.type == SDL_KEYDOWN && e.key.repeat == 0) {
					switch(e.key.keysym.sym) {
						case SDLK_LEFT: mVelX -= DOT_VEL; break;
						case SDLK_RIGHT: mVelX += DOT_VEL; break;
					}
				} else if(e.type == SDL_KEYUP && e.key.repeat == 0) {
					switch(e.key.keysym.sym) {
						case SDLK_LEFT: mVelX += DOT_VEL; break;
						case SDLK_RIGHT: mVelX -= DOT_VEL; break;
					}
				}
			}
			c->setPosX(c->getPosX() + mVelX);


			LoadCollisionMap lcm;
			list<Circle> circlesList;
			circlesList = lcm.load();

			int mPosX = c->getPosX();
			int mPosY = c->getPosY();

			list<Circle> l;
			Circle c1(mPosX,mPosY,10);
			l.push_back(c1);

			CollisionDetector cd;
			int y = mPosY;
			while(cd.hasCollision(circlesList, l)) {
				l.pop_back();
				y -= 1;
				Circle c1(mPosX,y,10);
				l.push_back(c1);
			};
			while(!cd.hasCollision(circlesList, l)) {
				l.pop_back();
				y += 1;
				Circle c1(mPosX,y,10);
				l.push_back(c1);
			};

			c->setPosY(y);

			renderer->render();
		}
	}
	return 0;
}
void GameEngine::run()
{
	spriteVec.push_back(levelVec.at(currentLevel)->getBackground());
	spriteVec.push_back(player);
	bool goOn = true;
	long laps = 0;
	while (goOn) {
		Uint32 nextTick = SDL_GetTicks() + ticks;
		SDL_RenderClear(win->getRen());
		if (initialLoop) {
			textInput();
			initialLoop = false;
		}
		SDL_Event eve2;
		for (size_t i = 0; i < spriteVec.size(); i++) {
			spriteVec.at(i)->draw();
			cd.checkCollisions(spriteVec.at(i));
		}
		removeSprites();
		cd.clearVector();
		for (size_t i = 0; i < textBoxVec.size(); i++) {
			textBoxVec.at(i)->draw();
		}
		if (pointCounter != nullptr) {
			pointCounter->draw();
		}
		SDL_RenderPresent(win->getRen());
		
		if (player == nullptr) {
			playerDied();
		}
		while (SDL_PollEvent(&eve2)) {
			switch (eve2.type) {
			case SDL_QUIT: goOn = false;
				break;
			case SDL_KEYDOWN:
				if (functionMap.count(eve2.key.keysym.sym) != 0) {
					functionMap[eve2.key.keysym.sym]();
				}
				for (size_t i = 0; i < memberFuncVec.size(); i++) {
					memberFuncVec.at(i)->perform(eve2.key.keysym.sym);
				}
				for (size_t i = 0; i < spriteVec.size(); i++) {
					spriteVec.at(i)->draw(eve2);
				}
				break;
			case SDL_KEYUP:
				for (size_t i = 0; i < spriteVec.size(); i++) {
					spriteVec.at(i)->draw(eve2);
				}
				break;
			}
		}
		laps++;
		
		levelVec.at(currentLevel)->spawnWave(this, laps);
		
		deleteSpawns(laps);

		//This is triggered when the level is over:
		if (laps > levelVec.at(currentLevel)->getEndFrame()) {
			SDL_RenderClear(win->getRen());
			for (size_t i = 0; i < spriteVec.size(); i++) {
				if (spriteVec.at(i)->getIsPlayer() == false) {
					spriteVec.at(i)->destroy(); //Prepare every sprite for removal except the player
				}
			}
			removeSprites();
			spriteVec.clear();
			deleteAllSpawns();
			SDL_RenderClear(win->getRen());
			levelSwap(); //Needs to be set by the game programmer
			currentLevel++;
			return this->run();
		}
		if (SDL_GetTicks() < nextTick) {
			SDL_Delay(nextTick - SDL_GetTicks());
		}
	}
}
예제 #14
0
//==============================================================================
void ConstraintTest::SingleContactTest(const std::string& _fileName)
{
  using namespace std;
  using namespace Eigen;
  using namespace dart::math;
  using namespace dart::collision;
  using namespace dart::constraint;
  using namespace dart::dynamics;
  using namespace dart::simulation;
  using namespace dart::utils;

  //----------------------------------------------------------------------------
  // Settings
  //----------------------------------------------------------------------------
  // Number of random state tests for each skeletons
#ifndef NDEBUG  // Debug mode
  // size_t testCount = 1;
#else
  // size_t testCount = 1;
#endif

  World* world = new World;
  EXPECT_TRUE(world != NULL);
  world->setGravity(Vector3d(0.0, -10.00, 0.0));
  world->setTimeStep(0.001);
  world->getConstraintSolver()->setCollisionDetector(
        new DARTCollisionDetector());

  Skeleton* sphereSkel = createSphere(0.05, Vector3d(0.0, 1.0, 0.0));
  BodyNode* sphere = sphereSkel->getBodyNode(0);
  Joint* sphereJoint = sphere->getParentJoint();
  sphereJoint->setVelocity(3, random(-2.0, 2.0));  // x-axis
  sphereJoint->setVelocity(5, random(-2.0, 2.0));  // z-axis
  world->addSkeleton(sphereSkel);
  EXPECT_EQ(sphereSkel->getGravity(), world->getGravity());
  assert(sphere);

  Skeleton* boxSkel = createBox(Vector3d(1.0, 1.0, 1.0),
                                Vector3d(0.0, 1.0, 0.0));
  BodyNode* box = boxSkel->getBodyNode(0);
  Joint* boxJoint = box->getParentJoint();
  boxJoint->setVelocity(3, random(-2.0, 2.0));  // x-axis
  boxJoint->setVelocity(5, random(-2.0, 2.0));  // z-axis
//  world->addSkeleton(boxSkel);
//  EXPECT_EQ(boxSkel->getGravity(), world->getGravity());
//  assert(box);

  Skeleton* groundSkel = createGround(Vector3d(10000.0, 0.1, 10000.0),
                                      Vector3d(0.0, -0.05, 0.0));
  groundSkel->setMobile(false);
  // BodyNode* ground = groundSkel->getBodyNode(0);
  world->addSkeleton(groundSkel);
  EXPECT_EQ(groundSkel->getGravity(), world->getGravity());
  // assert(ground);

  EXPECT_EQ(world->getNumSkeletons(), 2);

  ConstraintSolver* cs = world->getConstraintSolver();
  CollisionDetector* cd = cs->getCollisionDetector();

  // Lower and upper bound of configuration for system
  // double lb = -1.5 * DART_PI;
  // double ub =  1.5 * DART_PI;

  int maxSteps = 500;
  for (int i = 0; i < maxSteps; ++i)
  {
//    Vector3d pos1 = sphere->getWorldTransform().translation();
//    Vector3d vel1 = sphere->getWorldLinearVelocity(pos1);

//    std::cout << "pos1:" << pos1.transpose() << std::endl;
//    std::cout << "vel1:" << vel1.transpose() << std::endl;

    cd->detectCollision(true, true);
    if (cd->getNumContacts() == 0)
    {
      world->step();
      continue;
    }

    // for (size_t j = 0; j < cd->getNumContacts(); ++j)
    // {
      // Contact contact = cd->getContact(j);
      // Vector3d pos1 = sphere->getTransform().inverse() * contact.point;
      // Vector3d vel1 = sphere->getWorldLinearVelocity(pos1);

      // std::cout << "pos1:" << pos1.transpose() << std::endl;
      // std::cout << "vel1:" << vel1.transpose() << std::endl;
    // }

    world->step();

    for (size_t j = 0; j < cd->getNumContacts(); ++j)
    {
      Contact contact = cd->getContact(j);
      Vector3d pos1 = sphere->getTransform().inverse() * contact.point;
      Vector3d vel1 = sphere->getWorldLinearVelocity(pos1);

//      std::cout << "pos1:" << pos1.transpose() << std::endl;

//      std::cout << "pos1[1]: " << pos1[1] << std::endl;

//      std::cout << "pos1:" << pos1.transpose() << std::endl;
      std::cout << "vel1:" << vel1.transpose() << ", pos1[1]: " << pos1[1] << std::endl;

//      EXPECT_NEAR(pos1[0], 0.0, 1e-9);
//      EXPECT_NEAR(pos1[1], -0.05, 1e-2);
//      EXPECT_NEAR(pos1[2], 0.0, 1e-9);

//      EXPECT_NEAR(vel1[0], 0.0, 1e-9);
//      EXPECT_NEAR(vel1[1], 0.0, 1e-9);
//      EXPECT_NEAR(vel1[2], 0.0, 1e-9);

//      if (!equals(vel1, Vector3d(0.0, 0.0, 0.0)))
//        std::cout << "vel1:" << vel1.transpose() << std::endl;

//      EXPECT_EQ(vel1, Vector3d::Zero());
    }

//    std::cout << std::endl;

    break;
  }

  delete world;
}
/**
   @return top of the geometry indices assigned to the body.
   The geometry id corresponding to a link is <the top index> + <link->index()>.
*/
int cnoid::addBodyToCollisionDetector(Body& body, CollisionDetector& detector, bool enableSelfCollisions)
{
    const int idTop = detector.numGeometries();
    const int numLinks = body.numLinks();
    int excludeTreeDepth = 3;
    boost::dynamic_bitset<> exclusions(numLinks);
    boost::dynamic_bitset<> staticFlags(numLinks);
    
    const Mapping& cdInfo = *body.info()->findMapping("collisionDetection");
    if(cdInfo.isValid()){
        excludeTreeDepth = cdInfo.get("excludeTreeDepth", excludeTreeDepth);
        const Listing& excludeLinks = *cdInfo.findListing("excludeLinks");
        for(int i=0; i < excludeLinks.size(); ++i){
            Link* link = body.link(excludeLinks[i].toString());
            if(link){
                exclusions[link->index()] = true;
            }
        }
    }

    if(body.isStaticModel() || body.rootLink()->isFixedJoint()){
        setStaticFlags(body.rootLink(), staticFlags);
    }
    for(int i=0; i < numLinks; ++i){
        if(exclusions[i]){
            detector.addGeometry(0);
        } else {
            int id = detector.addGeometry(body.link(i)->collisionShape());
            if(staticFlags[i]){
                detector.setGeometryStatic(id);
            }
        }
    }

    if(!enableSelfCollisions){
        // exclude all the self link pairs
        for(int i=0; i < numLinks; ++i){
            if(!exclusions[i]){
                for(int j=i+1; j < numLinks; ++j){
                    if(!exclusions[j]){
                        detector.setNonInterfarenceGeometyrPair(i + idTop, j + idTop);
                    }
                }
            }
        }
    } else {
        // exclude the link pairs whose distance in the tree is less than excludeTreeDepth
        for(int i=0; i < numLinks; ++i){
            if(!exclusions[i]){
                Link* link1 = body.link(i);
                for(int j=i+1; j < numLinks; ++j){
                    if(!exclusions[j]){
                        Link* link2 = body.link(j);
                        Link* parent1 = link1;
                        Link* parent2 = link2;
                        for(int k=0; k < excludeTreeDepth; ++k){
                            if(parent1){
                                parent1 = parent1->parent();
                            }
                            if(parent2){
                                parent2 = parent2->parent();
                            }
                            if(!parent1 && !parent2){
                                break;
                            }
                            if(parent1 == link2 || parent2 == link1){
                                detector.setNonInterfarenceGeometyrPair(i + idTop, j + idTop);
                            }
                        }
                    }
                }
            }
        }
    }

    return idTop;
}