예제 #1
0
TEST_F(LocalIds, using_entities)
{
    if (get_parallel_size() == 1)
    {
        setup_mesh("generated:2x2x2", stk::mesh::BulkData::AUTO_AURA);
        BulkDataHelper bulkDataHelper(get_bulk());

        typedef stk::mesh::Field<double, stk::mesh::Cartesian3d> CoordFieldType;
        CoordFieldType *coords = get_meta().get_field<CoordFieldType>(stk::topology::NODE_RANK, "coordinates");

        unsigned elemIndex = 0;
        const stk::mesh::BucketVector& elemBuckets = get_bulk().buckets(stk::topology::ELEM_RANK);
        for(size_t i=0;i<elemBuckets.size();++i)
        {
            const stk::mesh::Bucket& bucket = *elemBuckets[i];
            for(size_t j=0;j<bucket.size();++j)
            {
                Entities nodes = bulkDataHelper.get_nodes(bucket[j]);
                for(unsigned k=0;k<nodes.size();++k)
                {
                    double *node_data = stk::mesh::field_data(*coords, nodes[k]);
                    EXPECT_NEAR(gold_x_coordinates[elemIndex][k], node_data[0], 1.e-6);
                }
                ++elemIndex;
            }
        }
    }
}
예제 #2
0
//=======================================================================
// Display Function
//=======================================================================
void Display(void)
{
	current_time = glutGet(GLUT_ELAPSED_TIME);

	if(current_time - previous_time > 15)
	{
		previous_time = current_time;

		elapsedTimeLastFrame =  current_time - lastFrame;

		glClear(GL_COLOR_BUFFER_BIT); 

		switch(GameState)	
		{
		case GAMEOVER:

			glColor3f(1.0, 0.0, 0.0);
			
			glLineWidth(20);
			renderText("GAME OVER", WIDTH/5, HEIGHT/2, 10);
			
			glLineWidth(1);
			DisplayScore();

			break;

		case GAMEPLAY:
		
			glColor3f(1.0, 1.0, 1.0);

			Ship(WIDTH/2, HEIGHT/2, shipRotation);

			EnemyList.Render(elapsedTimeLastFrame);
		
			glColor3f(1,0,0);
			bulletsList.Render(elapsedTimeLastFrame);

			if(fireLaser)
			Laser();
		
			DisplayScore();
			DisplayHints();
		
			CalculateFPS();
			DisplayFPS();
		
			break;
		}

		/* update animation */
		bulletsList.CheckCollision(&EnemyList);
		
		lastFrame = current_time;

	    glutSwapBuffers();

	}

	glutPostRedisplay();
}
예제 #3
0
Entities Manager::getEntities(const std::string& componentType)
{
    Entities entityList;

    for (auto e : entities_) {
        if (e->hasComponent(componentType)) {
            entityList.push_back(e);
        }
    }

    return entityList;
}
예제 #4
0
//=======================================================================
// Mouse Function
//=======================================================================
void Mouse(int button, int state, int x, int y)
{
	y = glutGet(GLUT_WINDOW_HEIGHT) - y;

	if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
		Vector dirVector = Vector(x,y) - Vector(WIDTH/2, HEIGHT/2);

		float dirVectorMag = sqrtf((dirVector.x * dirVector.x) + (dirVector.y * dirVector.y));

		Vector normalizedDir = dirVector/dirVectorMag;

		Entity *bullet = new Entity(WIDTH/2, HEIGHT/2, normalizedDir, BULLET);

		bulletsList.AddEntity(bullet);

		Vector shipUp(0,1);

		float dotProduct = (dirVector.x * shipUp.x) + (dirVector.y * shipUp.y);

		float cosAngle = dotProduct / (shipUp.Magnitude() * dirVector.Magnitude()) ;

		float angle = acos(cosAngle) * 180.f / PI;

		x > WIDTH/2 ? shipRotation = -angle : shipRotation = angle;
	}
}
void Collisionhandler::collisionBetweenEntities(Entities &entities){
	for (Entities::size_type i = 0; i < entities.size(); i++){
		Entity *e0 = entities[i];
		for (Entities::size_type j = i + 1; j < entities.size(); j++){
			Entity *e1 = entities[j];
			if (e0->isOnScreen() && e1->isOnScreen()) {
				if (hasCollided(e0, e1)) {
					if (e0->getType() != e1->getType() && e0->getType() == Entity::PLAYER) {
						checkCollisionDirection(e0, e1);
						//checkCollisionDirection(e1, e0);
					}
				}
			}
		}
	}
}
예제 #6
0
bool	Colision::doHeroShot(Entities& arg, Entities& arg_cmp)
{
	if (arg.getType() != MAZZELTOF && arg.getType() != PEPELOUNI)
	{
		Serializer<IBLAST::PackCollHeroShot> ser;
		ser.GData()._type = IBLAST::_COLL_HERO_SHOT;
		ser.GData()._idMob = arg_cmp.getIdMob();
		ser.GData()._idShot = arg_cmp.getIdT();
		memset(ser.GData()._playerName, '/0', IBLAST::_MAX_NAME_LEN);
		memcpy(ser.GData()._playerName, arg.getName().c_str(), IBLAST::_MAX_NAME_LEN); 
		ser.Serialize();
		this->IBlast.gSocketNFO().SendTo(ser.GBinData());
		return (true);
	}
	return false;
}
예제 #7
0
//=======================================================================
// Timer Function
//=======================================================================
void timer(int)
{
    /* update animation */
	CalculateFPS();
	
	bulletsList.CheckCollision(&EnemyList);

    glutPostRedisplay();
    glutTimerFunc(1000.f/60.f, timer, 0);
}
/* ****************************************************************************
*
* postBatchQuery -
*
* POST /v2/op/query
*
* Payload In:  BatchQueryRequest
* Payload Out: Entities
*
* URI parameters:
*   - limit=NUMBER
*   - offset=NUMBER
*   - options=count,keyValues
*/
std::string postBatchQuery
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  BatchQuery*           bqP  = &parseDataP->bq.res;
  QueryContextRequest*  qcrP = &parseDataP->qcr.res;
  Entities              entities;
  std::string           answer;

  qcrP->fill(bqP);
  bqP->release();  // qcrP just 'took over' the data from bqP, bqP no longer needed

  answer = postQueryContext(ciP, components, compV, parseDataP);

  if (ciP->httpStatusCode != SccOk)
  {
    parseDataP->qcr.res.release();
    return answer;
  }

  // 03. Render Entities response
  if (parseDataP->qcrs.res.contextElementResponseVector.size() == 0)
  {
    ciP->httpStatusCode = SccOk;
    answer = "[]";
  }
  else
  {
    entities.fill(&parseDataP->qcrs.res);

    TIMED_RENDER(answer = entities.render(ciP, EntitiesResponse));
  }

  // 04. Cleanup and return result
  entities.release();
  parseDataP->qcr.res.release();

  return answer;
}
예제 #9
0
//=======================================================================
// Random Enemy Location Function
//=======================================================================
void SpawnEnemies(int)
{
	Vector startlocation = GetRandomPosOffScreen();
	int level;
	(((int)startlocation.x + (int)startlocation.y) % 2) == 0 ? level = 0 : level = 1;
	Enemy *enemy = new Enemy(startlocation.x, startlocation.y, Vector(), ENEMY, startlocation, level);
	EnemyList.AddEntity(enemy);

	glutTimerFunc(1000.0/Difficulty, SpawnEnemies, 0);
}
예제 #10
0
/* ****************************************************************************
*
* present - no output expected, just exercising the code
*/
TEST(Entities, present)
{
  utInit();

  Entity* enP    = new Entity();
  enP->id        = "E";
  enP->type      = "T";
  enP->isPattern = "false";

  ContextAttribute* caP = new ContextAttribute("A", "T", "val");
  enP->attributeVector.push_back(caP);

  Entities ens;
  ens.vec.push_back(enP);
  ens.oe.fill(SccNone, "Lorem ipsum", "FooError");

  ens.present("");

  utExit();
}
예제 #11
0
PyObject* Entities<T>::__py_pyGet(PyObject* self, PyObject * args, PyObject* kwds)
{
	Entities* lpEntities = static_cast<Entities*>(self);
	PyObject * pDefault = Py_None;
	int id = 0;
	if (!PyArg_ParseTuple( args, "i|O", &id, &pDefault))
	{
		return NULL;
	}

	PyObject* pEntity = lpEntities->find(id);

	if (!pEntity)
	{
		pEntity = pDefault;
	}

	Py_INCREF(pEntity);
	return pEntity;
}
예제 #12
0
void Display::updateDisplay(Entities &entities){
    al_clear_to_color(al_map_rgba(0, 0, 0, 255));

    std::list<Entity*> entitiesTemp = entities.getEntities();

    for (std::list<Entity*>::iterator it = entitiesTemp.begin(); it != entitiesTemp.end(); it++){
        (*it)->draw();
    }
    displayText(score, Coordinates(80, 10), font2);

    al_flip_display();
}
void Collisionhandler::collisionBetweenEntitiesAndTerrains(Entities &entities, Terrains &terrains){
	for (Entities::size_type i = 0; i < entities.size(); i++){
		Entity *e0 = entities[i];
		for (Terrains::size_type j = 0; j < terrains.size(); j++){
			Terrain *e1 = terrains[j];
			if (e0->isOnScreen() && e1->isOnScreen()) {
				if (hasCollided(e0, e1)) {
					checkCollisionDirection(e0, e1);
				}
			}
		}
	}
}
예제 #14
0
/* ****************************************************************************
*
* getEntities - 
*
* GET /v2/entities
*
* Payload In:  None
* Payload Out: Entities
*
* URI parameters:
*   - limit=NUMBER
*   - offset=NUMBER
*   - count=true/false
*
* 01. Fill in QueryContextRequest
* 02. Call standard op postQueryContext
* 03. Render Entities response
* 04. Cleanup and return result
*/
std::string getEntities
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  std::string  answer;
  Entities     entities;


  // 01. Fill in QueryContextRequest
  parseDataP->qcr.res.fill(".*", "", "true", EntityTypeEmptyOrNotEmpty, "");
  

  // 02. Call standard op postQueryContext
  answer = postQueryContext(ciP, components, compV, parseDataP);


  // 03. Render Entities response
  if (parseDataP->qcrs.res.contextElementResponseVector.size() == 0)
  {
    ciP->httpStatusCode = SccOk;
    answer = "[]";
  }
  else
  {
    entities.fill(&parseDataP->qcrs.res);
    answer = entities.render(ciP, EntitiesResponse);
  }

  // 04. Cleanup and return result
  entities.release();
  parseDataP->qcr.res.release();

  return answer;
}
예제 #15
0
PyObject * Entities<T>::mp_subscript(PyObject* self, PyObject* key /*entityID*/)
{
	Entities* lpEntities = static_cast<Entities*>(self);
	ENTITY_ID entityID = PyLong_AsLong(key);
	if (PyErr_Occurred())
		return NULL;

	PyObject * pyEntity = NULL;

	ENTITYS_MAP& entities = lpEntities->getEntities();
	ENTITYS_MAP::const_iterator iter = entities.find(entityID);
	if (iter != entities.end())
		pyEntity = iter->second.get();

	if(pyEntity == NULL)
	{
		PyErr_Format(PyExc_KeyError, "%d", entityID);
		PyErr_PrintEx(0);
		return NULL;
	}

	Py_INCREF(pyEntity);
	return pyEntity;
}
예제 #16
0
//-------------------------------------------------------------------------------------
void SpaceViewer::updateClient()
{
	if (spaceID_ == 0)
		return;

	Space* space = Spaces::findSpace(spaceID_);
	if (space == NULL || !space->isGood())
	{
		return;
	}

	// 最多每次更新500个实体
	const int MAX_UPDATE_COUNT = 100;
	int updateCount = 0;

	// 获取本次与上次结果的差值,将差值放入stream中更新到客户端
	// 差值包括新增的实体,以及已经有的实体的位置变化
	MemoryStream s;

	Entities<Entity>* pEntities = Cellapp::getSingleton().pEntities();
	Entities<Entity>::ENTITYS_MAP& entitiesMap = pEntities->getEntities();

	// 先检查已经监视的实体,对于版本号较低的优先更新
	if (updateCount < MAX_UPDATE_COUNT)
	{
		std::map< ENTITY_ID, ViewEntity >::iterator viewerIter = viewedEntities.begin();
		for (; viewerIter != viewedEntities.end(); )
		{
			if (updateCount >= MAX_UPDATE_COUNT)
				break;

			ViewEntity& viewEntity = viewerIter->second;
			if (viewEntity.updateVersion > lastUpdateVersion_)
				continue;

			Entities<Entity>::ENTITYS_MAP::iterator iter = entitiesMap.find(viewerIter->first);

			// 找不到实体, 说明已经销毁或者跑到其他进程了
			// 如果在其他进程, 其他进程会将其更新到客户端
			if (iter == entitiesMap.end())
			{
				s << viewerIter->first;
				s << false; // true为更新, false为销毁

				// 将其从viewedEntities删除
				viewedEntities.erase(viewerIter++);
			}
			else
			{
				Entity* pEntity = static_cast<Entity*>(iter->second.get());
				if (pEntity->spaceID() != spaceID_)
				{
					// 将其从viewedEntities删除
					viewedEntities.erase(viewerIter++);
					continue;
				}

				/*
				if (pEntity->cellID() != cellID_)
				{
					// 将其从viewedEntities删除
					viewedEntities.erase(viewerIter++);
					continue;
				}
				*/

				// 有新增的实体或者已经观察到的实体,检查位置变化
				// 如果没有变化则pass
				if ((viewEntity.position - pEntity->position()).length() <= 0.0004f &&
					(viewEntity.direction.dir - pEntity->direction().dir).length() <= 0.0004f)
				{
					++viewerIter;
					continue;
				}

				viewEntity.entityID = pEntity->id();
				viewEntity.position = pEntity->position();
				viewEntity.direction = pEntity->direction();
				++viewEntity.updateVersion;

				s << viewEntity.entityID;
				s << true; // true为更新, false为销毁
				s << pEntity->pScriptModule()->getUType();
				s << viewEntity.position.x << viewEntity.position.y << viewEntity.position.z;
				s << viewEntity.direction.roll() << viewEntity.direction.pitch() << viewEntity.direction.yaw();

				++updateCount;
				++viewerIter;
			}
		}
	}

	// 再检查是否有新增的实体
	if (updateCount < MAX_UPDATE_COUNT)
	{
		Entities<Entity>::ENTITYS_MAP::iterator iter = entitiesMap.begin();

		for (; iter != entitiesMap.end(); ++iter)
		{
			if (updateCount >= MAX_UPDATE_COUNT)
				break;

			Entity* pEntity = static_cast<Entity*>(iter->second.get());
			if (pEntity->spaceID() != spaceID_)
				continue;

			/*
			if (pEntity->cellID() != cellID_)
				continue;
			*/

			std::map< ENTITY_ID, ViewEntity >::iterator findIter = viewedEntities.find(pEntity->id());
			ViewEntity& viewEntity = viewedEntities[pEntity->id()];

			if (findIter != viewedEntities.end())
				continue;

			viewEntity.entityID = pEntity->id();
			viewEntity.position = pEntity->position();
			viewEntity.direction = pEntity->direction();
			viewEntity.updateVersion = lastUpdateVersion_ + 1;

			++updateCount;

			s << viewEntity.entityID;
			s << true; // true为更新, false为销毁
			s << pEntity->pScriptModule()->getUType();
			s << viewEntity.position.x << viewEntity.position.y << viewEntity.position.z;
			s << viewEntity.direction.roll() << viewEntity.direction.pitch() << viewEntity.direction.yaw();
		}
	}

	sendStream(&s, updateType_);

	// 如果全部更新完毕,更换版本号
	if (updateCount < MAX_UPDATE_COUNT)
		++lastUpdateVersion_;
}
예제 #17
0
boost::iterator_range<ElementIterator> make_range(Entities& entities)
{
  ElementIterator begin(entities);
  return boost::make_iterator_range(begin,begin+entities.size());
}
예제 #18
0
/* ****************************************************************************
*
* getEntities - 
*
* GET /v2/entities
*
* Payload In:  None
* Payload Out: Entities
*
* URI parameters:
*   - limit=NUMBER
*   - offset=NUMBER
*   - count=true/false
*   - id
*   - idPattern
*   - q
*   - geometry
*   - coords
*
* 01. Fill in QueryContextRequest
* 02. Call standard op postQueryContext
* 03. Render Entities response
* 04. Cleanup and return result
*/
std::string getEntities
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  Entities     entities;
  std::string  answer;
  std::string  pattern    = ".*"; // all entities, default value
  std::string  id         = ciP->uriParam["id"];
  std::string  idPattern  = ciP->uriParam["idPattern"];
  std::string  q          = ciP->uriParam["q"];
  std::string  geometry   = ciP->uriParam["geometry"];
  std::string  coords     = ciP->uriParam["coords"];
  std::string  out;

  if ((idPattern != "") && (id != ""))
  {
    OrionError oe(SccBadRequest, "Incompatible parameters: id, IdPattern");

    TIMED_RENDER(answer = oe.render(ciP, ""));
    return answer;
  }
  else if (id != "")
  {
    // FIXME: a more efficient query could be possible ...
    std::vector<std::string> idsV;

    stringSplit(id, ',', idsV);

    for (unsigned int ix = 0; ix != idsV.size(); ++ix)
    {
      if (ix != 0)
      {
        pattern += "|";
      }

      pattern += idsV[ix];
    }
  }
  else if (idPattern != "")
  {
    pattern = idPattern;
  }


  // Making sure geometry and coords are not used individually
  if ((coords != "") && (geometry == ""))
  {
    OrionError   oe(SccBadRequest, "URI param /coords/ used without /geometry/");

    TIMED_RENDER(out = oe.render(ciP, ""));
    return out;
  }
  else if ((geometry != "") && (coords == ""))
  {
    OrionError oe(SccBadRequest, "URI param /geometry/ used without /coords/");

    TIMED_RENDER(out = oe.render(ciP, ""));

    return out;
  }

  // Making sure geometry is valid (if present)
  orion::Geometry           geo;
  std::vector<std::string>  coordsV;

  if (geometry != "")
  {
    std::string  errorString;

    if (geo.parse(geometry.c_str(), &errorString) != 0)
    {
      OrionError oe(SccBadRequest, std::string("error parsing geometry: ") + errorString);

      TIMED_RENDER(out = oe.render(ciP, ""));

      return out;
    }

    if ((geo.areaType != "polygon") && (geo.areaType != "circle"))
    {
      OrionError oe(SccBadRequest, "URI param /geometry/ must be either /polygon/ or /circle/");

      TIMED_RENDER(out = oe.render(ciP, ""));

      return out;
    }

    //
    // As 'geometry' is present, so is 'coords' - checking coords
    //
    int noOfCoords = stringSplit(coords, ';', coordsV);

    if (noOfCoords == 0)
    {
      OrionError oe(SccBadRequest, "URI param /coords/ has no coordinates");

      TIMED_RENDER(out = oe.render(ciP, ""));

      return out;
    }

    if ((geo.areaType == "circle") && (noOfCoords != 1))
    {
      OrionError oe(SccBadRequest, "Too many coordinates for circle");

      TIMED_RENDER(out = oe.render(ciP, ""));

      return out;
    }

    if ((geo.areaType == "polygon") && (noOfCoords < 3))
    {
      OrionError oe(SccBadRequest, "Too few coordinates for polygon");

      TIMED_RENDER(out = oe.render(ciP, ""));

      return out;
    }
  }


  //
  // 01. Fill in QueryContextRequest - type "" is valid for all types
  //
  parseDataP->qcr.res.fill(pattern, ciP->uriParam["type"], "true", EntityTypeEmptyOrNotEmpty, "");

  // If URI param 'q' is given, its value must be put in a scope
  if (q != "")
  {
    Scope* scopeP = new Scope(SCOPE_TYPE_SIMPLE_QUERY, q);

    parseDataP->qcr.res.restriction.scopeVector.push_back(scopeP);
  }


  // If URI params 'geometry' and 'coords' are given, another scope is to be created for this
  if ((coords != "") && (geometry != ""))
  {
    Scope*       scopeP = new Scope(SCOPE_TYPE_LOCATION, "");
    std::string  errorString;

    if (scopeP->fill(&geo, coordsV, &errorString) != 0)
    {
      OrionError oe(SccBadRequest, errorString);

      TIMED_RENDER(out = oe.render(ciP, ""));

      return out;
    }

    parseDataP->qcr.res.restriction.scopeVector.push_back(scopeP);
  }


  // 02. Call standard op postQueryContext
  answer = postQueryContext(ciP, components, compV, parseDataP);

  if (ciP->httpStatusCode != SccOk)
  {
    // Something went wrong in the query, an invalid pattern for example

    parseDataP->qcr.res.release();

    return answer;
  }

  // 03. Render Entities response
  if (parseDataP->qcrs.res.contextElementResponseVector.size() == 0)
  {
    ciP->httpStatusCode = SccOk;
    answer = "[]";
  }
  else
  {
    entities.fill(&parseDataP->qcrs.res);

    TIMED_RENDER(answer = entities.render(ciP, EntitiesResponse));
  }

  // 04. Cleanup and return result
  entities.release();
  parseDataP->qcr.res.release();

  return answer;
}
예제 #19
0
/* ****************************************************************************
*
* postBatchUpdate -
*
* POST /v2/op/update
*
* Payload In:  BatchUpdateRequest
* Payload Out: 201 or error
*
* URI parameters:
*   - limit=NUMBER
*   - offset=NUMBER
*   - options=keyValues
*/
std::string postBatchUpdate
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  BatchUpdate*           buP    = &parseDataP->bu.res;
  UpdateContextRequest*  upcrP  = &parseDataP->upcr.res;
  Entities               entities;
  std::string            answer;

  upcrP->fill(&buP->entities, buP->updateActionType.get());
  buP->release();  // upcrP just 'took over' the data from buP, buP is no longer needed
  parseDataP->upcr.res.present("");
  answer = postUpdateContext(ciP, components, compV, parseDataP);

  for (unsigned int ix = 0; ix < parseDataP->upcrs.res.contextElementResponseVector.size(); ++ix)
  {
    ContextElementResponse* cerP = parseDataP->upcrs.res.contextElementResponseVector[ix];

    if (cerP->statusCode.code != SccOk)
    {
      parseDataP->upcrs.res.errorCode.fill(cerP->statusCode);
    }
  }


  //
  // If an error is flagged by ciP->httpStatusCode, store it in parseDataP->upcrs.res.errorCode
  // for later processing (not sure this ever happen ...)
  //
  if (ciP->httpStatusCode != SccOk)
  {
    parseDataP->upcrs.res.errorCode.code     = ciP->httpStatusCode;
    parseDataP->upcrs.res.errorCode.details  = answer;
  }

  // If postUpdateContext gives back a parseDataP->upcrs with !200 OK in 'errorCode', transform to HTTP Status error
  if (parseDataP->upcrs.res.errorCode.code != SccOk)
  {
    OrionError   oe(parseDataP->upcrs.res.errorCode);

    ciP->httpStatusCode = parseDataP->upcrs.res.errorCode.code;

    // If 404 and details empty, assuming 'Entity not found'
    if ((parseDataP->upcrs.res.errorCode.code == SccContextElementNotFound) && (oe.details == ""))
    {
      oe.details = "Entity not found";
    }

    answer = oe.render(ciP, "");
  }
  else
  {
    //
    // NOTE
    //   For simplicity, 204 is always returned, even if entities are created
    //
    ciP->httpStatusCode = SccNoContent;
    answer = "";
  }

  // 04. Cleanup and return result
  entities.release();
  parseDataP->upcr.res.release();

  return answer;
}
예제 #20
0
bool IsElementsSurface::operator()(const Entities& component)
{
  return component.element_type().dimension() == component.element_type().dimensionality() + 1;
}
예제 #21
0
void PhysicsSystem::update(GameComponents& components, Entities const& entities, float dt) {
    std::vector<Contact> contacts;
    std::vector<StaticContact> static_contacts;
    std::vector<Collider*> colliders(entities.size());
    int collider_index = 0;
    
    float top = 600.0f;
    float bottom = 40.0f;
    
    // find contacts
    for (Entities::const_iterator it0 = entities.begin(); it0 != entities.end(); ++it0) {
        Entity entity0 = *it0;
        Collider* collider0 = &components.get<ColliderComponent>(entity0);
        collider0->touching.clear();
        colliders[collider_index++] = collider0;
        
        static_contacts.push_back({
            top - collider0->position(1) - collider0->radius,
            Mth::make_cvector(0.0f, 1.0f),
            collider0,
            entity0,
            0.0f
        });
        static_contacts.push_back({
            collider0->position(1) - bottom - collider0->radius,
            Mth::make_cvector(0.0f, -1.0f),
            collider0,
            entity0,
            0.0f
        });
        
        Entities::const_iterator it1 = it0; ++it1;
        for (; it1 != entities.end(); ++it1) {
            Entity entity1 = *it1;
            Collider* collider1 = &components.get<ColliderComponent>(entity1);
            
            if ((collider0->group == CG_PB && collider1->group == CG_PB) ||
                (collider0->group == CG_EB && collider1->group == CG_EB) ||
                (collider0->group == CG_PB && collider1->group == CG_EB) ||
                (collider0->group == CG_EB && collider1->group == CG_PB) ||
                (collider0->group == CG_P && collider1->group == CG_PB) ||
                (collider0->group == CG_PB && collider1->group == CG_P) ||
                (collider0->group == CG_E && collider1->group == CG_EB) ||
                (collider0->group == CG_EB && collider1->group == CG_E)) {
                continue;
            }
            
            Mth::CVector<float, 2> d = collider1->position - collider0->position;
            
            Contact c {
                Mth::length(d) - collider0->radius - collider1->radius,
                Mth::normal(d),
                collider0,
                collider1,
                entity0,
                entity1,
                0.0f
            };
            
            contacts.push_back(c);
        }
    }
    
    // solve contacts
    int iterations = 4;
    for (int i = 0; i < iterations; ++i) {
        for (auto& contact : static_contacts) {
            float relative_velocity = Mth::dot(-contact.collider->velocity, contact.normal);
            float remove_impuls = contact.distance / dt + relative_velocity;
            float new_impuls = std::min(contact.impuls + remove_impuls, 0.0f);
            float impuls_change = new_impuls - contact.impuls;
            contact.impuls = new_impuls;
            contact.collider->velocity += contact.normal * impuls_change;
        }
        
        for (auto& contact : contacts) {
            float relative_velocity = Mth::dot(contact.collider1->velocity - contact.collider0->velocity, contact.normal);
            float remove = contact.distance / dt + relative_velocity;
            float remove_impuls = remove / 2.0f;
            float new_impuls = std::min(contact.impuls + remove_impuls, 0.0f);
            float impuls_change = new_impuls - contact.impuls;
            
            contact.impuls = new_impuls;
            contact.collider0->velocity += contact.normal * impuls_change;
            contact.collider1->velocity -= contact.normal * impuls_change;
            
            if (i == iterations-1) {
                if (new_impuls < 0.0f) {
                    contact.collider0->touching.push_back(contact.entity1);
                    contact.collider1->touching.push_back(contact.entity0);
                }
            }
        }
    }
    
    // evaluate simulation
    for (Collider* collider : colliders) {
        collider->position += collider->velocity * dt;
        collider->velocity = Mth::make_cvector(0.0f, 0.0f);
    }
}
예제 #22
0
파일: scene.cpp 프로젝트: Commnets/QGAMES
// ---
void QGAMES::Scene::drawOn (QGAMES::Screen* s, const QGAMES::Position& p)
{
	assert (_activeMap);

	if (!_entitiesPerLayer.empty ())
	{
		// This means, there are entities that has to be drawn in an specific layer.
		// So it starts to iterate over the layers, 
		// drawing them, and the entities (or characters) in each
		// and also keeping control which one are drawn in each layer
		// to avoid they to be drawing on top of all layers.
		// At this point on the code, we don't still know which entities are in each layer
		std::vector <int> ePainted; // The entities that are being painted in its specific layer...
		QGAMES::Layers l = _activeMap -> layers (); // Let's go to iterate per layer...
		for (QGAMES::Layers::const_iterator i = l.begin (); i != l.end (); i++)
		{
			(*i) -> drawOn (s, p); // First of all the layer is drawn..
			QGAMES::EntitiesPerLayer::const_iterator j;
			// Is there something in this specific layer to be drawn?.
			if ((j = _entitiesPerLayer.find ((*i) -> name ())) != _entitiesPerLayer.end ())
			{
				// The list of the entities and characteres to be drawn...
				std::vector <int> es = (*j).second;
				// ...then the entities are drawn (if they have been defined in the layer)
				for (Entities::const_iterator k1 = _entities.begin (); 
					k1 != _entities.end (); k1++)
				{
					bool eFound = false;
					for (std::vector <int>::const_iterator l = es.begin (); 
							l != es.end () && !eFound; l++)
					{
						if ((*k1).second ->id () == (*l))
						{
							eFound = true;
							ePainted.push_back ((*l));
						}
					}

					if (eFound)
						(*k1).second -> drawOn (s); // The entities are drawn where they are...
				}

				// ...and the characters too (if they have been defined in the layer as well)
				for (Entities::const_iterator k2 = _characteres.begin (); 
					k2 != _characteres.end (); k2++)
				{
					bool eFound = false;
					for (std::vector <int>::const_iterator l = es.begin (); 
							l != es.end () && !eFound; l++)
					{
						if ((*k2).second ->id () == (*l))
						{
							eFound = true;
							ePainted.push_back ((*l));
						}
					}

					if (eFound)
						(*k2).second -> drawOn (s); // The entities are drawn where they are...
				}
			}
		}

		// Entities and characteres are put into the same structure
		// ...and ordered to be painted...
		Entities eTP = _entities; 
		eTP.insert (_characteres.begin (), _characteres.end ()); // Add the characters...
		eTP = orderEntitiesToDraw (eTP); // Order the set...
		for (Entities::const_iterator k3 = eTP.begin (); 
			k3 != eTP.end (); k3++)
		{
			bool eFound = false;
			for (std::vector <int>::const_iterator l = ePainted.begin (); 
					l != ePainted.end () && !eFound; l++)
				if ((*k3).second ->id () == (*l))
					eFound = true;
			if (!eFound) // If the entity was not drawn before...
				(*k3).second -> drawOn (s); // Every entity is drawn where it is...
		}
	}
	else
	{
		// This means that there are no specific entities per layer...
		_activeMap -> drawOn (s, p); // It is possible to alter where the map is drawn...
		Entities eTP = _entities;
		eTP.insert (_characteres.begin (), _characteres.end ()); // Add the characters...
		eTP = orderEntitiesToDraw (eTP); // Order everything...
		for (Entities::const_iterator i = eTP.begin (); i != eTP.end (); i++)
			(*i).second -> drawOn (s); // ...but the entities are drawn where they are...
	}
}