示例#1
0
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);
}
////////////////////////////////////////////////////////////////////////
///
/// @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;
}
示例#3
0
void processRemoval(b2Vec2 removalPosition, float removalRadius, b2World& world, bool simplifyGeometry)
{
	auto foundBodies = queryDestructibleBodies(removalPosition, removalRadius, world);
	auto batch = matchBodiesToRings(foundBodies.begin(), foundBodies.end());

	// Partition the shapes by area, so that elements to be processed are at the beginning
	auto borderIt = std::partition(batch.begin(), batch.end(), [](const match_t& m) {
		const double areaEpsilon = 0.02;
		return bg::area(m.second) > areaEpsilon;
	});

	// Remove small shapes
	std::for_each(borderIt, batch.end(), [&](const match_t& m) {
		world.DestroyBody(m.first);
	});

	// Subtract the input polygon from each shape returned from the query
	ring_t diff = makeConvexRing(removalPosition, removalRadius, 16);
	boost::geometry::correct(diff);

	typedef std::pair<std::unique_ptr<b2ChainShape>, b2Filter> shape_property_t;
	std::vector<shape_property_t> resultShapes;
	std::for_each(batch.begin(), borderIt, [&](const match_t& m) {
		auto subtractionResult = subtract(m.second, diff);
		// Simplify the results
		if (simplifyGeometry)
		{
			simplify(subtractionResult);
		}
		
		// Convert the rings to b2ChainShapes and add to result shapes
		auto converted = convertGeometry(subtractionResult);

		auto moveBegin = std::make_move_iterator(converted.begin());
		auto moveEnd = std::make_move_iterator(converted.end());
		std::transform(moveBegin, moveEnd, std::back_inserter(resultShapes),
			[&](std::unique_ptr<b2ChainShape> converted) {
			auto filter = m.first->GetFixtureList()->GetFilterData();
			return std::make_pair(std::move(converted), filter);
		});
		
		if (!subtractionResult.empty())
		{
			world.DestroyBody(m.first);
		}
	});

	for (auto&& s : resultShapes)
	{
		b2BodyDef bd;
		b2Body* body = world.CreateBody(&bd);
		auto fixture = body->CreateFixture(s.first.get(), 0.0f);
		fixture->SetFilterData(s.second);
	}
}
////////////////////////////////////////////////////////////////////////
///
/// @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;
}
示例#5
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;
}