bool Collider2D::checkOverlap(const Collider2D& other) const { if (this == &other) return false; struct Callback : b2QueryCallback { bool overlapping = false; const b2Body* bod = nullptr; bool ReportFixture(b2Fixture* fix) override { overlapping = bod == fix->GetBody(); return !overlapping; } } cb; cb.bod = other.m_body; // Visual studio 2013 doesn't compile without this-> ??? auto fixList = this->m_body->GetFixtureList(); b2AABB totalaabb(fixList->GetAABB(0)); while (fixList) { totalaabb.Combine(fixList->GetAABB(0)); fixList = fixList->GetNext(); } this->m_worldRef2D.m_worldData2D->QueryAABB(&cb, totalaabb); return cb.overlapping; }
bool Collision::PixelPerfectTest(const sf::Sprite& Object1, const sf::Sprite& Object2, sf::Uint8 AlphaLimit) { //Get AABBs of the two sprites sf::IntRect Object1AABB = GetAABB(Object1); sf::IntRect Object2AABB = GetAABB(Object2); sf::IntRect Intersection; if (Object1AABB.Intersects(Object2AABB, &Intersection)) { //We've got an intersection we need to process the pixels //In that Rect. //Bail out now if AlphaLimit = 0 if (AlphaLimit == 0) return true; //There are a few hacks here, sometimes the TransformToLocal returns negative points //Or Points outside the image. We need to check for these as they print to the error console //which is slow, and then return black which registers as a hit. sf::IntRect O1SubRect = Object1.GetSubRect(); sf::IntRect O2SubRect = Object2.GetSubRect(); sf::Vector2i O1SubRectSize(O1SubRect.GetWidth(), O1SubRect.GetHeight()); sf::Vector2i O2SubRectSize(O2SubRect.GetWidth(), O2SubRect.GetHeight()); sf::Vector2f o1v; sf::Vector2f o2v; //Loop through our pixels for (int i = Intersection.Left; i < Intersection.Right; i++) { for (int j = Intersection.Top; j < Intersection.Bottom; j++) { o1v = Object1.TransformToLocal(sf::Vector2f(i, j)); //Creating Objects each loop :( o2v = Object2.TransformToLocal(sf::Vector2f(i, j)); //Hack to make sure pixels fall withint the Sprite's Image if (o1v.x > 0 && o1v.y > 0 && o2v.x > 0 && o2v.y > 0 && o1v.x < O1SubRectSize.x && o1v.y < O1SubRectSize.y && o2v.x < O2SubRectSize.x && o2v.y < O2SubRectSize.y) { //If both sprites have opaque pixels at the same point we've got a hit if ((Object1.GetPixel(static_cast<int> (o1v.x), static_cast<int> (o1v.y)).a > AlphaLimit) && (Object2.GetPixel(static_cast<int> (o2v.x), static_cast<int> (o2v.y)).a > AlphaLimit)) { return true; } } } } return false; } return false; }
void Portal::Update() { Trigger::Update(); // Check for players no longer intersecting // NB erasing elements while iterating over container for (auto it = m_collidingPlayers.begin(); it != m_collidingPlayers.end(); ) { Player* p = *it; if (p->GetAABB().Intersects(GetAABB())) { ++it; } else { // No intersection - remove this player #if defined(WIN32) || defined(AMJU_IOS) it = m_collidingPlayers.erase(it); #else m_collidingPlayers.erase(it); ++it; #endif } } }
void Bomb::DoDraw() const { if (!IsAlive()) return; const double tile_width_in_px = 16.0; const double tile_height_in_px = 16.0; TexCoords tc((470.0+tile_width_in_px*m_anim_frame_num), 16.0, tile_width_in_px, tile_height_in_px); Engine::Get().Renderer()->DrawSprite(tc, GetPosition()); if (g_render_aabbs) Engine::Get().Renderer()->DrawAABB(GetAABB()); }
bool Civilian::CheckTractVictim(World & world){ if(!tractteamid){ return false; } std::vector<Uint8> types; types.push_back(ObjectTypes::PLAYER); int x1, y1, x2, y2; GetAABB(world.resources, &x1, &y1, &x2, &y2); std::vector<Object *> objects = world.TestAABB(x1, y1, x2, y2, types); for(std::vector<Object *>::iterator it = objects.begin(); it != objects.end(); it++){ Player * player = static_cast<Player *>(*it); if(player->teamid != tractteamid){ draw = false; for(int i = 0; i < 6; i++){ BodyPart * bodypart = (BodyPart *)world.CreateObject(ObjectTypes::BODYPART); if(bodypart){ bodypart->suitcolor = suitcolor; bodypart->x = x; bodypart->y = y - 50; bodypart->type = i; if(i == 0){ bodypart->xv = 0; bodypart->yv = -20; } } } state = DYINGEXPLODE; EmitSound(world, world.resources.soundbank["seekexp1.wav"], 128); Object tractprojectile(ObjectTypes::PLASMAPROJECTILE); tractprojectile.healthdamage = 80; tractprojectile.shielddamage = 80; tractprojectile.ownerid = id; player->HandleHit(world, 50, 50, tractprojectile); Sint8 xvs[] = {-14, 14, -10, 10, -10, 10}; Sint8 yvs[] = {-25, -25, -10, -10, -5, -5}; for(int i = 0; i < 6; i++){ PlasmaProjectile * plasmaprojectile = (PlasmaProjectile *)world.CreateObject(ObjectTypes::PLASMAPROJECTILE); if(plasmaprojectile){ plasmaprojectile->large = false; plasmaprojectile->x = x; plasmaprojectile->y = y - 40; plasmaprojectile->ownerid = id; plasmaprojectile->xv = xvs[i]; plasmaprojectile->yv = yvs[i]; } } return true; } } return false; }
dgCollisionBVH::dgCollisionBVH (dgWorld* const world, dgDeserialize deserialization, void* const userData) :dgCollisionMesh (world, deserialization, userData), dgAABBPolygonSoup() { m_rtti |= dgCollisionBVH_RTTI; m_builder = NULL;; m_userRayCastCallback = NULL; dgAABBPolygonSoup::Deserialize (deserialization, userData); dgVector p0; dgVector p1; GetAABB (p0, p1); SetCollisionBBox(p0, p1); }
void Player::Draw() { TexCoords tc = Engine::Get().Scripts()->GetPlayerSprite(GetType(), GetDirection(), IsDying(), SDL_GetTicks() - m_current_action_start_time); // std::cerr << "type = " << GetType() << ", direction = " << GetDirection().x() << ", " << GetDirection().y() // << ", is dying = " << IsDying() << "dt = " << SDL_GetTicks() - m_current_action_start_time << "\n"; // std::cerr << "tc = " << tc.left << ", " << tc.bottom << ", " << tc.width << ", " << tc.height << "\n"; Engine::Get().Renderer()->DrawSprite(tc, GetPosition()); if (g_render_aabbs) Engine::Get().Renderer()->DrawAABB(GetAABB()); }
void Ve1Object::Update() { m_oldPos = m_pos; if (!IsHidden()) { GameObject::Update(); } // To avoid being culled?! if (m_sceneNode) { m_sceneNode->SetAABB(GetAABB()); } }
void Baddie::Update() { Ve1Object::Update(); if (m_bb) { m_bb->Update(); } // Surely this is all done in base class ??? if (m_sceneNode) { Matrix m; m.Translate(m_pos); m_sceneNode->SetLocalTransform(m); } if (GetAABB()) { // Make bounding box smaller to give player the benefit of the doubt float x = m_size.x * 0.4f; float y = m_size.y * 0.4f; static const float YSIZE = 50.0f; GetAABB()->Set( m_pos.x - x, m_pos.x + x, m_pos.y, m_pos.y + YSIZE, m_pos.z - y, m_pos.z + y); //if (m_effect) //{ // *(m_effect->GetAABB()) = *(m_sceneNode->GetAABB()); //} } }
dgCollisionBVH::dgCollisionBVH (dgWorld* const world, dgDeserialize deserialization, void* const userData, dgInt32 revisionNumber) :dgCollisionMesh (world, deserialization, userData, revisionNumber) ,dgAABBPolygonSoup() { dgAssert (m_rtti | dgCollisionBVH_RTTI); m_builder = NULL;; m_userRayCastCallback = NULL; dgAABBPolygonSoup::Deserialize (deserialization, userData, revisionNumber); dgVector p0; dgVector p1; GetAABB (p0, p1); SetCollisionBBox(p0, p1); }
void dgCollisionBVH::EndBuild(dgInt32 optimize) { dgVector p0; dgVector p1; bool state = optimize ? true : false; m_builder->End(state); Create (*m_builder, state); GetAABB (p0, p1); SetCollisionBBox (p0, p1); delete m_builder; m_builder = NULL; }
void BombPowerup::DoDraw() const { if(!IsAlive()) { return; } const double tile_width_in_px = 16.0; const double tile_height_in_px = 16.0; const int m_anim_frame_num = 0; TexCoords tc((518.0+tile_width_in_px*m_anim_frame_num), 16.0, tile_width_in_px, tile_height_in_px); // these two are semanticaly equal // Engine::Get().Renderer()->DrawSprite(tc, GetPosition()); Engine::Get().Renderer()->DrawSpriteInCenter(tc, GetCenterPosition()); if (g_render_aabbs) Engine::Get().Renderer()->DrawAABB(GetAABB()); }
bool QuadNode::Subdivide() { if (_children[0]==NULL) { _children[TL]=QuadNode::CreatNode(this->_level+1,GetAABB().GetLeft(),GetAABB().GetTop(),GetAABB().w/2,GetAABB().h/2,this,_tree); _children[TR]=QuadNode::CreatNode(this->_level+1,GetAABB().GetCenter().x,GetAABB().GetTop(),GetAABB().w/2,GetAABB().h/2,this,_tree); _children[BR]=QuadNode::CreatNode(this->_level+1,GetAABB().GetCenter().x,GetAABB().GetCenter().y,GetAABB().w/2,GetAABB().h/2,this,_tree); _children[BL]=QuadNode::CreatNode(this->_level+1,GetAABB().GetLeft(),GetAABB().GetCenter().y,GetAABB().w/2,GetAABB().h/2,this,_tree); _isLeaf = false; } return true; }
void Mesh::Recenter() { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Mesh not created"); return; } if (m_impl->animationType != AnimationType_Static) { NazaraError("Mesh must be static"); return; } #endif // Le centre de notre mesh est le centre de l'AABB *globale* Vector3f center = GetAABB().GetCenter(); for (SubMesh* subMesh : m_impl->subMeshes) { StaticMesh* staticMesh = static_cast<StaticMesh*>(subMesh); BufferMapper<VertexBuffer> mapper(staticMesh->GetVertexBuffer(), BufferAccess_ReadWrite); MeshVertex* vertices = static_cast<MeshVertex*>(mapper.GetPointer()); unsigned int vertexCount = staticMesh->GetVertexCount(); for (unsigned int i = 0; i < vertexCount; ++i) { vertices->position -= center; vertices++; } // l'AABB ne change pas de dimensions mais seulement de position, appliquons-lui le même procédé Boxf aabb = staticMesh->GetAABB(); aabb.Translate(-center); staticMesh->SetAABB(aabb); } // Il ne faut pas oublier d'invalider notre AABB m_impl->aabbUpdated = false; }
void Treasure::Update() { // TODO Doesn't move, so no need to do this every frame, right? Ve1Object::Update(); if (m_sceneNode) { Matrix m; m.Translate(m_pos); m_sceneNode->SetLocalTransform(m); m_glow->SetLocalTransform(m); // ??? WHY ??? if (m_sceneNode->GetAABB()) { m_sceneNode->SetAABB(AABB( m_pos.x - XSIZE, m_pos.x + XSIZE, m_pos.y, m_pos.y + YSIZE, m_pos.z - XSIZE, m_pos.z + XSIZE)); } // Delete scene node if we have already been collected // (Extra check in case player not created yet when Load() called) std::string key = MakeTreasureKey(); Assert(GetLocalPlayer()); if (GetLocalPlayer()->Exists(key)) { // Or OnLocationExit ..? SetHidden(true); m_sceneNode = 0; } } GetAABB()->Set( m_pos.x - XSIZE, m_pos.x + XSIZE, m_pos.y, m_pos.y + YSIZE, m_pos.z - XSIZE, m_pos.z + XSIZE); }
void Player::Update() { if (m_isLoggedIn) { Ve1ObjectChar::Update(); } else if (m_sceneNode) { Matrix m; m.Translate(m_pos); m_sceneNode->SetLocalTransform(m); // Set shadow AABB to same as Scene Node so we don't cull it by mistake m_shadow->SetAABB(*(m_sceneNode->GetAABB())); static const float XSIZE = ROConfig()->GetFloat("player-aabb-x", 30.0f); static const float YSIZE = ROConfig()->GetFloat("player-aabb-y", 100.0f); GetAABB()->Set( m_pos.x - XSIZE, m_pos.x + XSIZE, m_pos.y, m_pos.y + YSIZE, m_pos.z - XSIZE, m_pos.z + XSIZE); /* DISABLED for 2D look and feel TurnToFaceDir(); */ } if (m_hidden) { return; } // Stop moving if we are close enough to the destination // TODO This ends up happening every frame, only do it if we are moving if (true) //m_isMoving) { Vec3f dir = GetPos() - m_newPos; dir.y = 0; // ignore y coord for now static const float STOP_DISTANCE = ROConfig()->GetFloat("stop-dist", 20.0f); if (dir.SqLen() < STOP_DISTANCE) { SetVel(Vec3f(0, 0, 0)); m_newPos = GetPos(); SetArrowVis(false); m_isMoving = false; } } else { //Assert(GetVel().SqLen() == 0); } if (m_sceneNode) { // Set shadow AABB to same as Scene Node so we don't cull it by mistake m_nameTag->SetAABB(*(m_sceneNode->GetAABB())); } if (m_ignorePortalId != -1) { GameObject* g = TheGame::Instance()->GetGameObject(m_ignorePortalId); if (g) { const AABB& aabb = g->GetAABB(); if (!GetAABB()->Intersects(aabb)) { // No longer intersecting portal m_ignorePortalId = -1; } } else { m_ignorePortalId = -1; // ? } } if (IsLocalPlayer()) { TheGSMain::Instance()->SetHeartNum(m_stamina); if (m_stamina <= 0) { // Player now has to go back to the spaceship to regenerate or something. if (!m_isDead) { LurkMsg lm("You need to return to your spaceship to recover from your injuries!", Colour(1, 1, 1, 1), Colour(1, 0, 0, 1), AMJU_CENTRE); TheLurker::Instance()->Queue(lm); } m_isDead = true; } } }
void Ve1ObjectChar::Update() { // Not safe to do anything if the Terrain has not been created yet if (!TerrainReady()) { return; } // TODO Not if underwater ? // TODO Put in base class, so we can drop things ? static const float GRAVITY = ROConfig()->GetFloat("gravity", -50.0f); m_acc.y = GRAVITY; Ve1Object::Update(); if (IsHidden()) { return; } // Handle wall collisions with terrain and any building if (HandleWalls(GetTerrain()->GetCollisionMesh(), m_oldPos, m_pos)) { m_recalcHeading = true; } HasCollisionMesh* h = dynamic_cast<HasCollisionMesh*>(m_collidingObject); if (h) { if (HandleWalls(h->GetCollisionMesh(), m_oldPos, m_pos)) { m_recalcHeading = true; } } HandleFloor(GetTerrain()->GetCollisionMesh()); if (h) { HandleFloor(h->GetCollisionMesh()); } // Recalc heading if we are not colliding if (m_collidingObject) { m_recalcHeading = true; } if (true) //m_recalcHeading) { m_recalcHeading = false; if (m_isMoving) { MoveTo(m_newPos); } } m_collidingObject = 0; /* // Stop moving if we are close enough to the destination // TODO This ends up happening every frame, only do it if we are moving if (m_isMoving) { Vec3f dir = GetPos() - m_newPos; dir.y = 0; // ignore y coord for now if (dir.SqLen() < 1.0f) // TODO CONFIG { SetVel(Vec3f(0, 0, 0)); m_newPos = GetPos(); SetArrowVis(false); m_isMoving = false; } } else { Assert(GetVel().SqLen() == 0); } */ if (m_sceneNode) { Matrix m; m.Translate(m_pos); m_sceneNode->SetLocalTransform(m); //m_sceneNode->Update(); // done for whole scene graph elsewhere if (m_shadow) { // Set shadow AABB to same as Scene Node so we don't cull it by mistake m_shadow->SetAABB(*m_sceneNode->GetAABB()); } if (m_effect) { m_effect->SetAABB(*m_sceneNode->GetAABB()); } static const float XSIZE = ROConfig()->GetFloat("player-aabb-x", 30.0f); static const float YSIZE = ROConfig()->GetFloat("player-aabb-y", 100.0f); GetAABB()->Set( m_pos.x - XSIZE, m_pos.x + XSIZE, m_pos.y, m_pos.y + YSIZE, m_pos.z - XSIZE, m_pos.z + XSIZE); /* NOT FOR 2D TurnToFaceDir(); */ Ve1Character* vc = dynamic_cast<Ve1Character*>(m_sceneNode.GetPtr()); if (vc) //// && vc->GetMd2()) { Vec3f v = m_vel; v.y = 0; float speed = v.SqLen(); // TODO Simplify -- either moving or idle. // NB Speeds should be an avatar variable and level up static const float MAX_SPEED = 100.0f; // TODO CONFIG static const float RUN_SPEED = MAX_SPEED * 0.5f; static const float WALK_SPEED = RUN_SPEED * 0.5f; if (speed > RUN_SPEED) { vc->SetAnim(Ve1Character::ANIM_RUN); } else if (speed > WALK_SPEED) { vc->SetAnim(Ve1Character::ANIM_WALK); } else { vc->SetAnim(Ve1Character::ANIM_IDLE); } } } }