// // Created by jovian on 18/07/17. // #include #include "Soldier.h" #include "b2Angle.h" Soldier::Soldier(Faction faction, Controller *ctrl, TinyWorld *tinyWorld, unsigned int imgId, unsigned int camp, unsigned int life) : Entity(faction, imgId, tinyWorld), m_ctrl(ctrl), m_camp(camp), m_life(life), m_tinyWorld(tinyWorld), m_homeFixture(nullptr), m_forceScale(50.0f), m_jumpVec(0.0f, -500.0f), m_jumpVelocityLimit(-0.5f), m_cool(0), m_coolCeil(10) { // Set the correct image if (imgId == 0) { if (m_camp == 0) m_imgId = 1; else if (m_camp == 1) m_imgId = 13; } } void Soldier::shoot(const b2Vec2 &dir) { m_cool = 0; m_tinyWorld->addEntity(new Bullet(m_body->GetPosition(), m_tinyWorld, dir, m_body->GetLinearVelocity(), m_camp)); } void Soldier::update() { // Life exist if (m_life == 0) m_exist = false; // todo A soldier fell out the world if (m_body->GetPosition().y > 100.0f) m_exist = false; // Firing m_cool++; if (m_ctrl->isFiring() && m_cool > m_coolCeil) shoot(m_ctrl->getVisor()); // todo Ship alignement // todo Shield activation // Movement b2Vec2 move(b2Dir(m_body->GetAngle() - b2_pi * 0.5f)); move.x *= m_forceScale * m_ctrl->getAcceleration(); move.y *= m_forceScale * m_ctrl->getAcceleration(); m_body->ApplyForceToCenter(move, true); // Torque with buttons #define TORQUE_MULTI_BUT 0.005f m_body->ApplyAngularImpulse(m_ctrl->getTorque() * TORQUE_MULTI_BUT, true); // Torque with visor #define TORQUE_MULTI_STICK 0.022f float deltaAngle = m_body->GetAngle() - b2Angle(m_ctrl->getVisor()) - b2_pi * 0.5f; while (deltaAngle > b2_pi) deltaAngle -= b2_pi * 2.0f; while (deltaAngle < -b2_pi) deltaAngle += b2_pi * 2.0f; m_body->ApplyAngularImpulse(-deltaAngle * TORQUE_MULTI_STICK, true); // todo Boosting if (isTouching() && m_ctrl->isBoosting() && m_body->GetLinearVelocity().y > m_jumpVelocityLimit) { m_body->ApplyForceToCenter(m_jumpVec, true); } // Damage taken by bullet for (b2ContactEdge *ce = m_body->GetContactList(); ce; ce = ce->next) { b2Contact *c = ce->contact; // Get incoming fixture b2Fixture *incomingFixture(c->GetFixtureA()); if (incomingFixture == m_homeFixture) incomingFixture = c->GetFixtureB(); // Detect bullet presence Entity *incomingEntity((Entity *) incomingFixture->GetBody()->GetUserData().pointer); if (incomingEntity->getFaction() == BULLET) { // Damage Bullet *incomingBullet((Bullet*)incomingEntity); int damage(incomingBullet->getDamage()); if (m_life < damage) m_life = 0; else m_life -= damage; // Bullet destroyed incomingEntity->setExistence(false); } } } void Soldier::createPhysicalShape(b2Vec2 spawn) { // Already exists ? if (m_body != nullptr) { std::cout << "Soldier::createPhysicalShape() > Body non null pointer. Creation aborted." << std::endl; return; } // Creation of physical body b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; bodyDef.position = spawn; bodyDef.fixedRotation = false; bodyDef.linearDamping = 1.0f; bodyDef.angularDamping = 10.0f; m_body = m_tinyWorld->CreateBody(&bodyDef); // Creation of super shape b2Vec2 vertices[5]; vertices[0].Set(0.0f, -28.0f / DEFAULT_ZOOM); vertices[1].Set(-26.0f / DEFAULT_ZOOM, 14.0f / DEFAULT_ZOOM); vertices[2].Set(-25.0f / DEFAULT_ZOOM, 28.0f / DEFAULT_ZOOM); vertices[3].Set(25.0f / DEFAULT_ZOOM, 28.0f / DEFAULT_ZOOM); vertices[4].Set(26.0f / DEFAULT_ZOOM, 14.0f / DEFAULT_ZOOM); b2PolygonShape allyShape; allyShape.Set(vertices, 5); // Definition of fixture b2FixtureDef fixtureDef; fixtureDef.shape = &allyShape; fixtureDef.density = 6.0f; fixtureDef.friction = 0.3f; // Fixture filtering if (m_camp == 0) { fixtureDef.filter.categoryBits = 0b0001; fixtureDef.filter.maskBits = 0b1101; } else if (m_camp == 1) { fixtureDef.filter.categoryBits = 0b0100; fixtureDef.filter.maskBits = 0b0111; } // Creation of fixture m_homeFixture = m_body->CreateFixture(&fixtureDef); // Link this soldier establishPhysicalLink(); }