void VerletPhysicsSystem::update( EntityManager &entities, EventManager &events, TimeDelta dt ) { ComponentHandle<VerletBody> body; for( auto __unused e : entities.entities_with_components( body ) ) { auto &b = *body.get(); auto current = b.position; auto velocity = (b.position - b.previous_position) * static_cast<float>((dt / previous_dt)) + b.acceleration * static_cast<float>(dt * dt); // Friction as viscous drag. velocity *= (1.0 - b.drag); /* // Friction as a fixed-ish force. // Perhaps do some kind of ground test and apply when things are on ground. auto l2 = glm::length2(velocity); if (l2 > 0.0f) { auto len = std::sqrt(l2); auto friction = (velocity / len) * std::min(b.friction, len); velocity -= friction; } */ b.position += velocity; b.previous_position = current; // We reset the acceleration so other systems/effects can simply add forces each frame. // TODO: consider alternative approaches to this. b.acceleration = vec3(0); previous_dt = dt; } // solve constraints ComponentHandle<VerletDistanceConstraint> constraint; const auto constraint_iterations = 2; for( auto __unused e : entities.entities_with_components( constraint ) ) { if( (! constraint->a.valid()) || (! constraint->b.valid()) ) { // would be cooler if the bodies knew about all constraints on them so this couldn't happen. constraint.remove(); continue; } for( int i = 0; i < constraint_iterations; i += 1 ) { auto &a = *constraint->a.get(); auto &b = *constraint->b.get(); auto center = (a.position + b.position) / 2.0f; auto delta = a.position - b.position; auto len = glm::length( delta ); if( len < std::numeric_limits<float>::epsilon() ) { delta = randVec3(); len = 1.0f; } delta *= constraint->distance / (len * 2.0f); // get half delta a.position = center + delta; b.position = center - delta; } } }
void soso::applyPhysicsAttraction(EntityManager &entities) { ComponentHandle<VerletBody> body; ComponentHandle<PhysicsAttraction> attraction; for (auto __unused e : entities.entities_with_components(body, attraction)) { ComponentHandle<PhysicsAttractor> attractor; ComponentHandle<VerletBody> attractor_body; for (auto __unused e : entities.entities_with_components(attractor, attractor_body)) { auto delta = attractor_body->position - body->position; auto len = glm::length( delta ); auto t = glm::clamp( len / attractor->distance_falloff, 0.0f, 1.0f ); t = 1.0f - (t * t); auto force = delta * attractor->strength * attraction->strength * t; body->nudge( force ); } } }
void HudSystem::update(EntityManager& entities, EventManager& events, double dt) { SpaceShip::Handle spaceShip; Health::Handle health; Gun::Handle gun; for (Entity entity : entities.entities_with_components(spaceShip, health, gun)) { m_heatBorderSprite.setPosition(50.0f, 485.0f); m_window.draw(m_heatBorderSprite); m_heatBarSprite.setPosition(50.0f, 485.0f); m_heatBarRect.width = static_cast<int>(gun->heat+0.5); m_heatBarSprite.setTextureRect(m_heatBarRect); m_window.draw(m_heatBarSprite); m_healthText.setPosition(50.0f, 500.0f); m_window.draw(m_healthText); if (!entity.has_component<DeathSentence>()) { float startX = 50.0f; for (int i = 0; i < health->health+1; ++i) { m_healthSprite.setPosition(startX, 540.0f); m_window.draw(m_healthSprite); startX += 25.0f; } } m_scoreText.setPosition(750.0f, 500.0f); m_window.draw(m_scoreText); m_scoreView.setPosition(750.0f, 533.0f); m_scoreView.draw(spaceShip->score, m_window); // Only support one space ship atm return; } }
void TransformSystem::update(EntityManager &entities, EventManager &events, TimeDelta dt) { ComponentHandle<Transform> transform; /// If/when entityx allows us to order our components in memory based on their hierarchy, /// we will be able to walk through and simply update in linear order. /// We could also do that if we wrote our own memory allocator for transforms (which we are unlikely to pursue). for (Entity __unused e : entities.entities_with_components(transform)) { if (transform->isRoot()) { transform->composeTransform(mat4(1)); transform->descend([] (const Transform &parent, Transform &child) { child.composeTransform(parent.worldTransform()); }); } } }