void Physics::addDynamicRectangle(CollidableObject* co, float centerX, float centerY, int width, int height, float angle, float density, float friction, float gravityScale) { b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; bodyDef.position.Set(pixelsToMeters(centerX),-pixelsToMeters(centerY)); bodyDef.gravityScale = gravityScale; bodyDef.angle = angle; co->getPhysicalProperties()->rigidBody = box2DWorld->CreateBody(&bodyDef); b2Body *rigidBody = co->getPhysicalProperties()->rigidBody; rigidBody->SetUserData(co); b2FixtureDef fixtureDef; setCollisionFilters(co, &fixtureDef); b2PolygonShape box; box.SetAsBox(pixelsToMeters(width/2), pixelsToMeters(height/2)); fixtureDef.shape = &box; fixtureDef.density = density; fixtureDef.friction = friction; fixtureDef.restitution = .03f; co->getPhysicalProperties()->rigidBody->CreateFixture(&fixtureDef); co->getPhysicalProperties()->setWidth(width); co->getPhysicalProperties()->setHeight(height); }
//////////////////////////KEEP///////////////////////////////////////////// void Physics::addCollidableObject(CollidableObject *collidableObjectToAdd) { PhysicalProperties *pp = collidableObjectToAdd->getPhysicalProperties(); float height = pixelsToMeters(collidableObjectToAdd->getBoundingVolume()->getHeight()) / 2; float width = pixelsToMeters(collidableObjectToAdd->getBoundingVolume()->getWidth()) / 2; float x = pixelsToMeters(pp->getX()); float y = pixelsToMeters(-pp->getY()); // Define the dynamic body. We set its position and call the body factory. b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; bodyDef.position.Set(x, y); b2Body* body = box2DWorld->CreateBody(&bodyDef); testSubjectBody = body; // Define another box shape for our dynamic body. b2PolygonShape dynamicBox; dynamicBox.SetAsBox(width, height); // Define the dynamic body fixture. b2FixtureDef fixtureDef; fixtureDef.shape = &dynamicBox; // Set the box density to be non-zero, so it will be dynamic. fixtureDef.density = 1.0f; // Override the default friction. fixtureDef.friction = 0.3f; // Add the shape to the body. body->CreateFixture(&fixtureDef); }
Shuriken::Shuriken(const sf::Vector2f& position, const sf::Vector2f& velocity, Game* game) : Entity(position, game, "shuriken " + std::to_string(Id)) { ++Id; sprite_.setTexture(game->getTextureManager().getTexture("spriteSheet")); sprite_.setTextureRect(sf::IntRect(0, 310, 20, 20)); sprite_.setOrigin(sprite_.getLocalBounds().left + sprite_.getLocalBounds().width / 2.f, sprite_.getLocalBounds().top + sprite_.getLocalBounds().height / 2.f); b2BodyDef bodyDef; bodyDef.position.Set(pixelsToMeters(position.x), pixelsToMeters(position.y)); bodyDef.type = b2_dynamicBody; b2PolygonShape shape; shape.SetAsBox(pixelsToMeters(static_cast<float>(20)) / 2.f, pixelsToMeters(static_cast<float>(20)) / 2.f); body_ = game->getWorld()->CreateBody(&bodyDef); b2FixtureDef fixtureDef; fixtureDef.shape = &shape; fixtureDef.density = 1.f; fixtureDef.restitution = 0.f; fixtureDef.isSensor = true; body_->CreateFixture(&fixtureDef); body_->SetFixedRotation(false); body_->SetUserData(this); body_->SetGravityScale(0.f); body_->ApplyLinearImpulse(b2Vec2(velocity.x, velocity.y), body_->GetWorldCenter(), true); body_->SetAngularVelocity(10.f); sprite_.setPosition(metersToPixels(body_->GetPosition().x), metersToPixels(body_->GetPosition().y)); }
Finish::Finish(const sf::Vector2f& position, Game* game) : Entity(position, game, "finish") { sprite_.setTexture(game->getTextureManager().getTexture("spriteSheet")); sprite_.setTextureRect(sf::IntRect(0, 335, 32, 32)); sprite_.setOrigin(sprite_.getLocalBounds().left + sprite_.getLocalBounds().width / 2.f, sprite_.getLocalBounds().top + sprite_.getLocalBounds().height / 2.f); b2BodyDef bodyDef; bodyDef.position.Set(pixelsToMeters(position.x), pixelsToMeters(position.y)); b2PolygonShape shape; shape.SetAsBox(pixelsToMeters(static_cast<float>(sprite_.getTexture()->getSize().x)) / 2.f, pixelsToMeters(static_cast<float>(sprite_.getTexture()->getSize().y)) / 2.f); body_ = game->getWorld()->CreateBody(&bodyDef); b2FixtureDef fixtureDef; fixtureDef.shape = &shape; fixtureDef.density = 1.f; fixtureDef.isSensor = true; body_->CreateFixture(&fixtureDef); body_->SetGravityScale(0.f); body_->SetFixedRotation(true); body_->SetUserData(this); sprite_.setPosition(metersToPixels(body_->GetPosition().x), metersToPixels(body_->GetPosition().y)); }
Ball::Ball() { ballImage = new Bitmap("magic_ball.bmp", true); isUnderPhysicsControl = false; ballRadius = pixelsToMeters((ballImage->getHeight()) / 2); Xpos = pixelsToMeters(725); Ypos = pixelsToMeters(100) + ballRadius; }
void Physics::addCollidableTiles(TiledLayer *collidableTiles) { if(!collidableTiles->hasCollidableTiles()) { //Why are you wasting time calling this method on a layer that doesn't even have collidable tiles? //I'd throw an exception, but that's too much work. return; } int rows = collidableTiles->getRows(); int columns = collidableTiles->getColumns(); int tileWidth = collidableTiles->getTileWidth(); int tileHeight = collidableTiles->getTileHeight(); for(int i = 0; i < rows; i++) { for(int k = 0; k < columns; k++) { Tile *tile = collidableTiles->getTile(i,k); if(tile->collidable) { //The bodyDef position is actually the position of the center of mass, so we add half the height and width to the original x coordinate b2BodyDef tileBodyDef; float tileXScaled = pixelsToMeters(tileWidth * k + tileWidth/2); float tileYScaled = -pixelsToMeters(tileHeight * i + tileHeight/2); float tileWidthScaled = pixelsToMeters(tileWidth)/2.0; float tileHeightScaled = pixelsToMeters(tileHeight)/2.0; tileBodyDef.position.Set(tileXScaled, tileYScaled); // Call the body factory which allocates memory for the ground body // from a pool and creates the ground box shape (also from a pool). // The body is also added to the world. b2Body* tileBody = box2DWorld->CreateBody(&tileBodyDef); //!!! THIS MAY CAUSE A MEMORY LEAK IF WE DESTORY THE TILE BODY WITHOUT ALSO DESTROYING THE USER DATA tileBody->SetUserData(new CollidableObject(CollisionType::TILE)); //We need to keep a reference to the body so that we can destroy it //later when we no longer need it //--------WE NEED TO STORE THE TILE BODIES IN A DATA STRUCTURE HERE----// // Define the ground box shape. b2PolygonShape groundBox; // The extents are the half-widths of the box. groundBox.SetAsBox(tileWidthScaled, tileHeightScaled); // Add the ground fixture to the ground body. tileBody->CreateFixture(&groundBox, 0.0f); } } } }
void Physics::addStaticRectangle(int x, int y, float width, float height) { b2BodyDef bodyDef; //The bodyDef position is actually the position of the center of mass bodyDef.position.Set(pixelsToMeters(x + width/2),-pixelsToMeters(y + height/2)); b2Body* body = box2DWorld->CreateBody(&bodyDef); b2FixtureDef fixtureDef; b2PolygonShape box; box.SetAsBox(pixelsToMeters(width/2), pixelsToMeters(height/2)); fixtureDef.shape = &box; fixtureDef.friction = 0.3f; body->CreateFixture(&fixtureDef); }
void Physics::update(Game *game) { // Prepare for simulation. Typically we use a time step of 1/60 of a // second (60Hz) and 10 iterations. This provides a high quality simulation // in most game scenarios. float32 timeStep = 1.0f / 60.0f; int32 velocityIterations = 6; int32 positionIterations = 2; // This is our little game loop. for (int32 i = 0; i < 60; ++i) { // Instruct the world to perform a single step of simulation. // It is generally best to keep the time step and iterations fixed. box2DWorld->Step(timeStep, velocityIterations, positionIterations); } list<b2Body*>::iterator bodiesIterator; bodiesIterator = bodiesToDestroy.begin(); while (bodiesIterator != bodiesToDestroy.end()) { b2Body* body = *bodiesIterator; bodiesIterator++; box2DWorld->DestroyBody(body); } bodiesToDestroy.clear(); if(explosionThisFrame) { list<Explosion*>::iterator explosionsIterator; explosionsIterator = explosions.begin(); while (explosionsIterator != explosions.end()) { Explosion* explosion = *explosionsIterator; explosionsIterator++; int numRays = explosion->numOfRays; b2Vec2 center = explosion->explosionEpicenter; float blastRadius = explosion->blastRadius; for (int i = 0; i < numRays; i++) { float angle = (i / (float)numRays) * 360 * DEGTORAD; b2Vec2 rayDir( sinf(angle), cosf(angle) ); b2Vec2 rayEnd = center + pixelsToMeters(blastRadius) * rayDir; //check what this ray hits ExplosionCallback callback;//basic callback to record body and hit point box2DWorld->RayCast(&callback, center, rayEnd); if ( callback.getClosestFixture() ) applyBlastImpulse(callback.getClosestFixture()->GetBody(), center, callback.getImplusePoint(), (explosion->blastPower / (float)numRays)); } } explosions.clear(); explosionThisFrame = false; } }
Bullet::Bullet(const sf::Vector2f& position, int direction, Game* game) : Entity(position, game, "bullet " + std::to_string(Id)) , Speed(0.5f) , TextureWidth(16) , TextureHeight(16) { ++Id; sprite_.setTexture(game->getTextureManager().getTexture("spriteSheet")); sprite_.setTextureRect(sf::IntRect(0, 0, TextureWidth, TextureHeight)); sprite_.setOrigin(sprite_.getLocalBounds().left + sprite_.getLocalBounds().width / 2.f, sprite_.getLocalBounds().top + sprite_.getLocalBounds().height / 2.f); b2BodyDef bodyDef; bodyDef.position.Set(pixelsToMeters(position.x), pixelsToMeters(position.y)); bodyDef.type = b2_dynamicBody; b2PolygonShape shape; shape.SetAsBox(pixelsToMeters(static_cast<float>(TextureWidth)) / 2.f, pixelsToMeters(static_cast<float>(TextureHeight)) / 2.f); body_ = game->getWorld()->CreateBody(&bodyDef); b2FixtureDef fixtureDef; fixtureDef.shape = &shape; fixtureDef.density = 1.f; fixtureDef.restitution = 0.f; fixtureDef.isSensor = true; body_->CreateFixture(&fixtureDef); body_->SetFixedRotation(true); body_->SetUserData(this); body_->SetGravityScale(0.f); body_->ApplyLinearImpulse(b2Vec2(Speed * direction, 0.f), body_->GetWorldCenter(), true); sprite_.setPosition(metersToPixels(body_->GetPosition().x), metersToPixels(body_->GetPosition().y)); }
void Physics::addCollidableObject(CollidableObject* co, float x, float y, int width, int height, float angle, float density, float friction, bool fixedRotation, float gravityScale, bool isCircular) { b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; //The bodyDef position is actually the position of the center of mass bodyDef.position.Set(pixelsToMeters(x + width/2),-pixelsToMeters(y + height/2)); bodyDef.gravityScale = gravityScale; bodyDef.angle = angle; co->getPhysicalProperties()->rigidBody = box2DWorld->CreateBody(&bodyDef); b2Body *rigidBody = co->getPhysicalProperties()->rigidBody; rigidBody->SetUserData(co); b2FixtureDef fixtureDef; setCollisionFilters(co, &fixtureDef); b2PolygonShape box; b2CircleShape circle; if(!isCircular) { box.SetAsBox(pixelsToMeters(width/2), pixelsToMeters(height/2)); fixtureDef.shape = &box; } else { //The circle shape should be centered over the body circle.m_p.Set(-pixelsToMeters(width/2),-pixelsToMeters(height/2)); //Width and height should be equal, so it doesn't matter which we use here for the radius circle.m_radius = pixelsToMeters(width/2); fixtureDef.shape = &circle; } fixtureDef.density = density; fixtureDef.friction = friction; fixtureDef.restitution = .03f; co->getPhysicalProperties()->rigidBody->CreateFixture(&fixtureDef); co->getPhysicalProperties()->rigidBody->SetFixedRotation(fixedRotation); co->getPhysicalProperties()->setWidth(width); co->getPhysicalProperties()->setHeight(height); }
void Ball::update(Uint32 deltaTime, AngularWall * wallAngle) { BasePhysics::update(deltaTime); updateLabels(deltaTime); //Detect the collision with the ground if ((Ypos - ballRadius) < pixelsToMeters(10)) { Ypos = pixelsToMeters(10.01) + ballRadius; Yvel = R *- Yvel; Xvel *= R; } //Collision detection with the right wall if ((Xpos + ballRadius) > pixelsToMeters(1490)) { Xpos = pixelsToMeters(1489.99) - ballRadius; Yvel *= R; Xvel = R *- Xvel; } //Collision detection with the left wall if ((Xpos - ballRadius) < pixelsToMeters(10)) { Xpos = pixelsToMeters(10.01) + ballRadius; Yvel *= R; Xvel = R *-Xvel; } //Collision detection against angular wall Vector2D pos(Xpos, Ypos); //For each side of the wall for (int i = 0; i < 4; i++) { //Get the start and end points of the line that represents this edge Vector2D start, end; wallAngle->getWallPoints(i, start, end); //Project the ball onto this line Vector2D point = GetClosestPointOnLineSegment(start, end, pos); float dist = (point - pos).length(); // If the closest point on the line segment is within the bounds of our radius, then we have collided with it if (dist <= ballRadius) { Vector2D surfaceNormal = wallAngle->getSurfaceNormal(i); //Push the ball out so it isn't colliding anymore Vector2D newpos = point + (surfaceNormal * (ballRadius + pixelsToMeters(0.01))); Xpos = newpos.x; Ypos = newpos.y; //Since we have collided wih the wall, we need to bounce off it //To do so, we reflect the ball's velocity, around the wall's edge's surfacenormal //This code was adapted from: http://www.3dkingdoms.com/weekly/weekly.php?a=2 Vector2D incoming(Xvel, Yvel); Vector2D result = surfaceNormal * incoming.dot(surfaceNormal); result *= -2.f; result += incoming; result *= R; Xvel = result.x; Yvel = result.y; } } }