RigidBody2D::RigidBody2D(const RigidBody2D& other, Object& newObj) : Collider2D(other, newObj) { b2BodyDef bd; b2FixtureDef fdf; auto& pos = getObject()->getGlobalPosition(); bd.angle = glm::eulerAngles(getObject()->getGlobalRotation()).z; bd.position = b2Vec2(pos.x, pos.y); bd.userData = this; auto om = other.m_body; bd.type = om->GetType(); newObj.setIgnoreParent(other.getObject()->ignoresParent()); fdf.isSensor = om->GetFixtureList()->IsSensor(); bd.allowSleep = om->IsSleepingAllowed(); m_body = other.m_worldRef2D.m_worldData2D->CreateBody(&bd); auto omf = om->GetFixtureList(); fdf.filter = omf->GetFilterData(); fdf.friction = omf->GetFriction(); fdf.restitution = omf->GetRestitution(); fdf.shape = omf->GetShape(); fdf.density = omf->GetDensity(); m_body->CreateFixture(&fdf); }
//////////////////////////////////////////////////////////////////////// /// /// @fn bool BonusModifierChangeZone::Revert() /// /// Reverts the effect on the node, /// return unsed for now /// /// /// @return bool /// //////////////////////////////////////////////////////////////////////// bool BonusModifierChangeZone::Revert() { #if WIN32 SoundFMOD::obtenirInstance()->playEffect(BONUS_CHANGE_SIDE_OUT_EFFECT); #endif #if BOX2D_PLAY for(int i=0; i<(int)mFixtures.size(); ++i) { auto fixture = mFixtures[i]; b2Filter filter = fixture->GetFilterData(); // adds the wall as categories that can block the node filter.maskBits |= CATEGORY_MIDLANE; fixture->SetFilterData(filter); } #endif NoeudMaillet* maillet = (NoeudMaillet*)mOwner; if(maillet) { auto pos = maillet->getPosition(); auto initialPos = maillet->getOriginalPosition(); // verification si le maillet n'est plus dans sa zone if(pos[VX]*initialPos[VX] <= 0) { maillet->setPosition(initialPos); } } return true; }
void addStaticShapes(b2World& world) { ShapeFactory factory { constants::RENDER_SCALE }; // Add the nondestructible screen edges std::vector<b2Vec2> boundaryPoints = { b2Vec2{ 0.0f, 0.0f }, b2Vec2{ 0.0f, screenHeight }, b2Vec2{ screenWidth, screenHeight }, b2Vec2{ screenWidth, 0.0f } }; auto boundaryShape = factory.chain(boundaryPoints.data(), boundaryPoints.size()); b2BodyDef boundaryDef; b2Body* boundaryBody = world.CreateBody(&boundaryDef); auto boundaryFixture = boundaryBody->CreateFixture(boundaryShape.get(), 0.0f); auto filter = boundaryFixture->GetFilterData(); filter.categoryBits = Shape::normal; boundaryFixture->SetFilterData(filter); // Add a destructible polygon std::vector<b2Vec2> polygonPoints = { b2Vec2{ screenWidth * 0.1f, screenHeight * 0.4f }, b2Vec2{ screenWidth * 0.1f, screenHeight * 0.95f }, b2Vec2{ screenWidth * 0.9f, screenHeight * 0.95f }, b2Vec2{ screenWidth * 0.9f, screenHeight * 0.7f }, b2Vec2{ screenWidth * 0.4f, screenHeight * 0.4f } }; auto polygonShape = factory.chain(polygonPoints.data(), polygonPoints.size()); b2BodyDef polygonDef; b2Body* polygonBody = world.CreateBody(&polygonDef); auto polygonFixture = polygonBody->CreateFixture(polygonShape.get(), 0.0f); filter.categoryBits = Shape::destructible; polygonFixture->SetFilterData(filter); }
void FilterCatalogParams::fillCatalog(FilterCatalog &catalog) { for (size_t i = 0; i < getCatalogs().size(); ++i) { const FilterCatalogs catalogToAdd = getCatalogs()[i]; const unsigned int entries = GetNumEntries(catalogToAdd); const unsigned int propEntries = GetNumPropertyEntries(catalogToAdd); // XXX Fix Me -> these should probably be shared to save memory const FilterProperty_t *props = GetFilterProperties(catalogToAdd); for (unsigned int i = 0; i < entries; ++i) { const FilterData_t &data = GetFilterData(catalogToAdd)[i]; FilterCatalogEntry *entry = MakeFilterCatalogEntry(data, propEntries, props); PRECONDITION(entry, "Bad Entry data"); if (entry) catalog.addEntry(entry); // catalog owns entry } } }
//////////////////////////////////////////////////////////////////////// /// /// @fn bool BonusModifierChangeZone::Apply() /// /// Applies the real effect on the node /// returns false if the bonus finished the execution (no time to live) /// in case it returns false, complete its execution /// /// /// @return bool /// //////////////////////////////////////////////////////////////////////// bool BonusModifierChangeZone::Apply() { if(mOwner) { auto existingModifiers = mOwner->GetModifiers(); // recherche pour un bonus déjà présent for(auto it = existingModifiers.begin(); it != existingModifiers.end(); ++it) { BonusModifierChangeZone* modifier = dynamic_cast<BonusModifierChangeZone*>(*it); if(modifier && modifier != this) { // resets time to live on the modifier modifier->mTimeToLive = mTimeToLive; /// return false to indicate that the bonus was not added to the node, even though the /// bonus itself was applied. return false; } } #if BOX2D_PLAY auto body = mOwner->getPhysicBody(); if(body) { for(auto fixture = body->GetFixtureList(); fixture; fixture = fixture->GetNext()) { b2Filter filter = fixture->GetFilterData(); if(filter.maskBits & CATEGORY_MIDLANE) { // removes the wall as categorie that can block the node filter.maskBits &= ~CATEGORY_MIDLANE; fixture->SetFilterData(filter); mFixtures.push_back(fixture); } } } #endif } // if any fixtures were found, it means that this node had a modifiation applied return mFixtures.size() != 0; }
int main() { sf::Font font; sf::Text overlayText; const std::string fontFile = "am.ttf"; if (font.loadFromFile(fontFile)) { overlayText.setFont(font); } else { std::cerr << "Could not find " << fontFile << "\n"; return 1; } overlayText.setCharacterSize(10); overlayText.setString("Hold left mouse button to modify\nRight mouse button to add objects"); sf::VideoMode videoMode{ static_cast<unsigned int>(screenWidth), static_cast<unsigned int>(screenHeight) }; sf::ContextSettings settings; settings.antialiasingLevel = 8; sf::RenderWindow window(videoMode, "Box2D modifiable geometry", sf::Style::Default, settings); std::unique_ptr<b2World> physicsWorld{ new b2World{ b2Vec2{ 0.0f, 18.0f } } }; physicsWorld->SetAutoClearForces(false); physicsWorld->SetContactListener(nullptr); DebugDraw debugDraw(&window, physicsWorld.get()); addStaticShapes(*physicsWorld); sf::Clock clock; bool simplifyGeometry = true; while (window.isOpen()) { float elapsed = clock.restart().asSeconds(); sf::Event event; auto mousePos = sf::Mouse::getPosition(window); auto worldPos = window.mapPixelToCoords(mousePos); const float removalRadius = 25.f; b2Vec2 position = { worldPos.x, worldPos.y }; while (window.pollEvent(event)) { if (event.type == sf::Event::Closed) { window.close(); } if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Button::Right) { ShapeFactory factory{ constants::RENDER_SCALE }; auto ballShape = factory.circle(position, removalRadius / 2.f); b2BodyDef ballDef; b2Body* ballBody = physicsWorld->CreateBody(&ballDef); auto ballFixture = ballBody->CreateFixture(ballShape.get(), 0.0f); ballBody->SetType(b2BodyType::b2_dynamicBody); auto filter = ballFixture->GetFilterData(); filter.categoryBits = Shape::normal; filter.maskBits = Shape::normal | Shape::destructible; ballFixture->SetFilterData(filter); } if (event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::S) { simplifyGeometry = !simplifyGeometry; } } window.clear(); step(*physicsWorld, elapsed); b2Vec2 scaledPos = position; scaledPos *= (1.f / constants::RENDER_SCALE); float scaledRadius = removalRadius / constants::RENDER_SCALE; if (sf::Mouse::isButtonPressed(sf::Mouse::Button::Left)) { processRemoval(scaledPos, scaledRadius, *physicsWorld, simplifyGeometry); drawMouseIndicator(worldPos, removalRadius, window); } physicsWorld->DrawDebugData(); window.draw(overlayText); window.display(); } return 0; }