void Physics::detectCollisions (const std::vector<PhysicsObject*>& objects) { // Lets go through each collidable object checking if they collide. for (auto i = 0U; i < objects.size(); ++i) { // Cache the values for the first object. auto first = objects[i]; const auto& check = first->getCollider(); const auto checkLayer = m_layers[check.getLayer()]; auto checkBox = check.getBox(); checkBox.translate (first->getPosition().x, first->getPosition().y); for (auto j = i + 1; j < objects.size(); ++j) { // Cache the values for the second object. auto second = objects[j]; const auto& against = second->getCollider(); // Check if their layers collide. if ((checkLayer | (1 << against.getLayer())) > 0) { // We must now check if the rectangles intersect. auto againstBox = against.getBox(); againstBox.translate (second->getPosition().x, second->getPosition().y); // Check if they intersect. if (checkBox.intersects (againstBox)) { // Determine the desired collision type. if (check.isTrigger()) { first->onTrigger (second); if (against.isTrigger()) { second->onTrigger (first); } } // Collider on trigger. else if (against.isTrigger()) { second->onTrigger (first); } // Collider on collider. else { first->onCollision (second); second->onCollision (first); } } } } } }
void Player::moveForward(const float speed) { //Vector3 pos = getPosition(); const float speed_multiplier = 40; float cosYaw = cosf(degreesToRadians(m_yaw)); float sinYaw = sinf(degreesToRadians(m_yaw)); //pos.x += float(cosYaw)*speed; //pos.z += float(sinYaw)*speed; btVector3 linearVelocity = getCollider()->getBody()->getLinearVelocity(); getCollider()->getBody()->setLinearVelocity(btVector3(btScalar(float(cosYaw)*speed*speed_multiplier), linearVelocity.getY(), btScalar(float(sinYaw)*speed*speed_multiplier))); //setPosition(pos); }
void Player::onCollision(GameObject* other) { sf::Vector2f off = { 0.f, 0.f }; PlatformObject* platform = dynamic_cast<PlatformObject*>(other); if (platform) { if (m_position.y + dynamic_cast<BoxCollider*>(getCollider())->GetExtention().y <= platform->getPosition().y) { onGround = true; } if (m_collMgr->getCount() > 0) { off = platform->getCollider()->getOffset(); off /= static_cast<float>(m_collMgr->getCount()); off.x = floorf(off.x); off.y = floorf(off.y); m_position += off; } else { m_position += dynamic_cast<PlatformObject*>(platform)->getCollider()->getOffset(); } } //m_velocity *= 0.9f; //printf("Player::onCollision()\n") }
bool GameObject::collides(GameObject * otherGameObject) { Collider* c = getCollider(); assert( otherGameObject != NULL); Collider* oc = otherGameObject->getCollider(); assert( c != NULL); assert( oc != NULL); return c->collides(oc); }
void Enemy::tick(float delta) { movement(delta); if(canFire()) fire(); if(getCollider()->collides(SphereCollider(Game::getGame().getPlayer().getPosition(), 1))) { // TODO: what side we were hit on Connection::getInstance().write("EVN#1;0;"); destroy(); } }
void PhysicsEntity::renderCollider(int x, int y) const { Colliders::RectangleCollider collider = getCollider(); SDL_Rect srcRect = { collider.x + x, collider.y + y, collider.width, collider.height }; SDL_RenderDrawRect(renderer(), &srcRect); }
void Flying::handleMovement(Vector2D velocity) { Vector2D newPos = m_position; newPos.y(newPos.y() + velocity.y()); // Check collisions in y axis if (newPos.y() + getCollider().y <= 0 || newPos.y() + getCollider().y + getCollider().h >= TheGame::Instance().getMapHeight() || checkCollideTile(newPos) || checkCollideObject(newPos)) { m_bYCollision = !m_bYCollision; } else { m_position.y(newPos.y()); } // Update new position newPos = m_position; newPos.x(m_position.x() + velocity.x()); // Check collisions in x axis if (newPos.x() + getCollider().x <= 0 || newPos.x() + getCollider().x + getCollider().w >= TheGame::Instance().getMapWidth() || checkCollideTile(newPos) || checkCollideObject(newPos)) { // There have been a collision, so change direction m_bXCollision = !m_bXCollision; } else { // Move to new x position m_position.x(newPos.x()); } }
const SUCCESS StaticObject::checkCollision(PhysicalObject &object) { if(getCollider() == NULL || object.getCollider() == NULL) { return SUCCEEDED; } else { Radians angle; if(getCollider()->canCollide(object.getCollider()->getType())) if(getCollider()->collides(*object.getCollider(), &angle)) return collided(object, angle); // this ensures that object collider is called by this collided function, likewise a derived class needs to make sure its own derived collided function is called else return SUCCEEDED; else if(object.getCollider()->canCollide(getCollider()->getType())) if(object.getCollider()->collides(*getCollider(), &angle)) return collided(object, angle); else return SUCCEEDED; else return FAILED; } }
void Projectile::loadProjectile() { if(projectileAnimation == NULL) { for(int i = 0; i < PROJECTILE_FRAMES; i++) { char pathToFrame[256]; sprintf_s(pathToFrame, 256, PROJECTILE_FRAMES_PATH, i); if((projectileFrames[i] = ImageManager::createImage(pathToFrame)) == NULL) return; } projectileAnimation = AnimationManager::createAnimation(projectileFrames, PROJECTILE_FRAMES, DELAY_BETWEEM_FRAMES); projectileAnimation->startPlaying(); projectileCollideSurface = getCollider(projectileFrames[0]); } }
const SUCCESS PhysicalObject::collided(PhysicalObject &object, const Radians angle) { Vector initVec(getVelocity()-object.getVelocity()); Mag_t<double> initVel(initVec.mag()); Radians initTheta(initVec.theta()); if(fabs(getX(initVel, initTheta-angle)) < REST_THRESHOLD) { setVelocity(getVelocity()+initVec/2.0); object.setVelocity(object.getVelocity()-initVec/2.0); antigravitate(object); object.antigravitate(*this); return SUCCEEDED; } // Frame of reference with the object at rest with this approaching it with an angle of 0 Point<double> p2(Vector(Mag_t<double>(2.0*getMass()*getX(initVel, initTheta-angle)/(getMass()+object.getMass())), initTheta-angle)); // Gets the velocity of 2 based on elastic collision equation Point<double> p1((initVel*getMass()-p2.x()*object.getMass())/getMass(), -p2.y()*object.getMass()/getMass()); // Gets the velocity of 1 based off of elastic collision rulez if(fabs(p1.x()) < REST_THRESHOLD && fabs(p2.x()) < REST_THRESHOLD) { p1.x(0.0); p2.x(0.0); } Vector v1(p1); Vector v2(p2); v1.theta(-v1.theta()+initTheta); v2.theta(angle); v1 += object.getVelocity(); v2 += object.getVelocity(); Point<double> dif(object.getPosition()-*position); while(getCollider()->collides(*object.getCollider())) acceleration.set(*position-dif/pythagoras<double>(dif)); setVelocity(v1); object.setVelocity(v2); return SUCCEEDED; }
const SUCCESS StaticObject::collided(PhysicalObject &object, const Radians angle) { Vector v(object.getVelocity()); v.theta() -= angle; Point<double> appliedMomentum(v); if(fabs(appliedMomentum.x()) < REST_THRESHOLD) { appliedMomentum.x(0); } appliedMomentum.x() *= -1; v = appliedMomentum; v.theta() += angle; object.setVelocity(v); Point<double> dif(getPosition()-object.getPosition()); while(getCollider()->collides(*object.getCollider())) object.setPosition(object.getPosition()-dif/pythagoras<double>(dif)); return SUCCEEDED; }
void WorkerBee::onState(State state, sf::Time dt) { Vec2d empty(-1.0, -1.0); // first state if (state == IN_HIVE) { // if bee has pollen transfer it to hive if (getPollen() > 0) { transferPollen(dt); flower_location_ = empty; setDebugStatus("in_hive_leaving_pollen"); } else { // if bee has not enough energy to leave hive, eat its nectar if (getEnergy() < energy_leave_hive_ && getHive().getNectar() > 0) { setDebugStatus("in_hive_eating"); eatFromHive(dt); } // if there is a flower in memory and enough energy, target move // to this flower else if (flower_location_ != empty && getEnergy() > energy_collect_pollen_) { setDebugStatus("in_hive_leaving"); setMoveTarget(flower_location_); // change state to to flower nextState(); } else { setDebugStatus("in_hive_no_flower"); } } } // second state else if (state == TO_FLOWER) { setDebugStatus("to_flower"); if (getEnergy() < energy_collect_pollen_) { nextState(); nextState(); } Flower* flower = getAppEnv().getCollidingFlower(getVisionRange()); if (flower) { setMoveTarget(flower->getPosition()); setMoveState(MoveState::TARGET); if (isPointInside(flower->getPosition())) { nextState(); } } else if (isPointInside(flower_location_)) { // go back to hive and clear location nextState(); nextState(); setFlowerLocation(Vec2d(-1,-1)); } } // third state else if (state == COLLECT_POLLEN) { // if there is a flower at flower location and it has pollen and // bee has not enough pollen, eat pollen from flower Flower* flower(getAppEnv().getCollidingFlower(getCollider())); if ((getPollen() < max_pollen_) && (flower != nullptr) && (flower->getPollen() > 0)) { eatPollen(flower, dt); } else { // else skip collection nextState(); } } else if (state == RETURN_HIVE) { // if bee is in hive change state to in hive if (getHive().isColliderInside(getCollider())) { nextState(); } } }
/** *<summary> * Check separation Axis test between passed GameObject(A) and calling GameObject(B) * You may need to call it twice - for checking collision of B in A's coordinate system *</Summary> */ bool GameObject::separationAxisTest(SharedPointer<GameObject> i_other, float& o_collisionTime, float & o_separationTime, myEngine::typedefs::Axis &o_collisionAxis) //Move to Collsion System to make it better - To-Do { bool isColliding = false; float tCollisionInX = 0.0f; float tSeparationInX = 0.0f; float tCollisionInY = 0.0f; float tSeparationInY = 0.0f; float tCollisionInZ = 0.0f; float tSeparationInZ = 0.0f; //Position of other GameObject in this Vector3D i_otherCenterPositionInThis = getTranslatedPosition(i_other->getPosition()); //Extent of other gameObject in this Vector3D i_otherExtentInThis = getTransformedExtents(i_other); //Transformed velocity of calling gamobject in its own coordiante system Vector3D thisVelocityInThis = getTranslationMatrix() *physicsComponent->getCurrentVelocity(); //Velocity of other GameObject in calling gameObject coordinate system Vector3D i_otherVelocityInThis = getTranslationMatrix() * i_other->physicsComponent->getCurrentVelocity(); //Relative velocity of other gamObject in freezed gameObject coordinate system i.e. in calling gameObject coordiante system Vector3D i_otherChangedVelocityInThis = i_otherVelocityInThis - thisVelocityInThis; //Expanding the extents of calling gameObject float thisChangedXExtent = getCollider()->getExtendX() + i_otherExtentInThis.getX(); float thisChangedYExtent = getCollider()->getExtendY() + i_otherExtentInThis.getY(); float thisChangedZExtent = getCollider()->getExtendZ() + i_otherExtentInThis.getZ(); bool finalCollisionTimeInitialized = false; //Swept collision for each axes //Checking in X-Axis switch (i_otherCenterPositionInThis.getX() >= 0 ) { case true: if (i_otherCenterPositionInThis.getX() <= thisChangedXExtent) { //To-Do - time of collision - Done but need testing if (i_otherChangedVelocityInThis.getX() != 0) { tCollisionInX = abs(((0 + thisChangedXExtent) - i_otherCenterPositionInThis.getX()) / i_otherChangedVelocityInThis.getX()); tSeparationInX = abs((i_otherCenterPositionInThis.getX() - (0 - thisChangedXExtent)) / i_otherChangedVelocityInThis.getX()); o_collisionTime = tCollisionInX; o_separationTime = tSeparationInX; o_collisionAxis = myEngine::typedefs::XAxis; finalCollisionTimeInitialized = true; } } else return false; break; case false: if (abs(i_otherCenterPositionInThis.getX()) <= thisChangedXExtent) { //To-Do - time of collision - Done but need testing if (i_otherChangedVelocityInThis.getX() != 0) { tCollisionInX = abs((i_otherCenterPositionInThis.getX() - (0 - thisChangedXExtent)) / i_otherChangedVelocityInThis.getX()); tSeparationInX = abs(((0 + thisChangedXExtent) - i_otherCenterPositionInThis.getX()) / i_otherChangedVelocityInThis.getX()); o_collisionTime = tCollisionInX; o_separationTime = tSeparationInX; o_collisionAxis = myEngine::typedefs::XAxis; finalCollisionTimeInitialized = true; } } else return false; break; } //Check in Y-axis in case X-Axis collision is true switch (i_otherCenterPositionInThis.getY() >= 0) { case true: if (i_otherCenterPositionInThis.getY() <= thisChangedYExtent) { //To-Do - time of collision -Done but need testing if (i_otherChangedVelocityInThis.getY() != 0) { tCollisionInY = abs(((0 + thisChangedYExtent) - i_otherCenterPositionInThis.getY()) / i_otherChangedVelocityInThis.getY()); tSeparationInY = abs((i_otherCenterPositionInThis.getY() - (0 - thisChangedYExtent)) / i_otherChangedVelocityInThis.getY()); if (!finalCollisionTimeInitialized) { o_collisionTime = tCollisionInY; o_separationTime = tSeparationInY; o_collisionAxis = myEngine::typedefs::YAxis; } else { if (tCollisionInY < o_collisionTime) { o_collisionTime = tCollisionInY; o_collisionAxis = myEngine::typedefs::YAxis; } if (tSeparationInY < o_separationTime) o_separationTime = tSeparationInY; } } } else return false; break; case false: if (abs(i_otherCenterPositionInThis.getY()) <= thisChangedYExtent) { //To-Do - time of collision - Done but need testing if (i_otherChangedVelocityInThis.getY() != 0) { tCollisionInY = abs((i_otherCenterPositionInThis.getY() - (0 - thisChangedYExtent)) / i_otherChangedVelocityInThis.getY()); tSeparationInY = abs(((0 + thisChangedYExtent) - i_otherCenterPositionInThis.getY()) / i_otherChangedVelocityInThis.getY()); if (!finalCollisionTimeInitialized) { o_collisionTime = tCollisionInY; o_separationTime = tSeparationInY; o_collisionAxis = myEngine::typedefs::YAxis; } else { if (tCollisionInY < o_collisionTime) { o_collisionTime = tCollisionInY; o_collisionAxis = myEngine::typedefs::YAxis; } if (tSeparationInY < o_separationTime) o_separationTime = tSeparationInY; } } } else return false; break; } //Check in Z-axis in case X-Axis and Y-Axis collision is true switch (i_otherCenterPositionInThis.getZ() >= 0) { case true: if (i_otherCenterPositionInThis.getZ() <= thisChangedZExtent) { //To-Do - time of collision - Done but need testing if (i_otherChangedVelocityInThis.getZ() != 0) { tCollisionInZ = abs(((0 + thisChangedZExtent) - i_otherCenterPositionInThis.getZ()) / i_otherChangedVelocityInThis.getZ()); tSeparationInZ = abs((i_otherCenterPositionInThis.getZ() - (0 - thisChangedZExtent)) / i_otherChangedVelocityInThis.getZ()); if (!finalCollisionTimeInitialized) { o_collisionTime = tCollisionInZ; o_separationTime = tSeparationInZ; o_collisionAxis = myEngine::typedefs::ZAxis; } else { if (tCollisionInY < o_collisionTime) { o_collisionTime = tCollisionInZ; o_collisionAxis = myEngine::typedefs::ZAxis; } if (tSeparationInY < o_separationTime) o_separationTime = tSeparationInZ; } } } else return false; break; case false: if (abs(i_otherCenterPositionInThis.getZ()) <= thisChangedZExtent) { //To-Do - time of collision - Done but need testing if (i_otherChangedVelocityInThis.getZ() != 0) { tCollisionInZ = abs((i_otherCenterPositionInThis.getZ() - (0 - thisChangedZExtent)) / i_otherChangedVelocityInThis.getZ()); tSeparationInZ = abs(((0 + thisChangedZExtent) - i_otherCenterPositionInThis.getZ()) / i_otherChangedVelocityInThis.getZ()); if (!finalCollisionTimeInitialized) { o_collisionTime = tCollisionInZ; o_separationTime = tSeparationInZ; o_collisionAxis = myEngine::typedefs::ZAxis; } else { if (tCollisionInY < o_collisionTime) { o_collisionTime = tCollisionInZ; o_collisionAxis = myEngine::typedefs::ZAxis; } if (tSeparationInY < o_separationTime) o_separationTime = tSeparationInZ; } } } else return false; break; } //returning if all if's are false i.e. collsion occured in this coordinate system return true; }
void Chaser::handleMovement(Vector2D velocity) { Vector2D newPos = m_position; newPos.x(m_position.x() + velocity.x()); if (newPos.x() == m_playerPos->x()) { m_velocity.x(0); } else { // check if the chaser is trying to go off the map if (newPos.x() + getCollider().x < 0) { m_position.x(-getCollider().x); } else if (newPos.x() + getCollider().x + getCollider().w > TheGame::Instance().getMapWidth()) { m_position.x(TheGame::Instance().getMapWidth() - getCollider().w - getCollider().x); } else { if (checkCollideTile(newPos) || checkCollideObject(newPos)) { // collision, stop x movement m_velocity.x(0); if (checkCollideTile(newPos)) { // Collision with the map, move to contact if (m_position.x() < newPos.x()) // Collision with tile to the right { m_position.x(m_position.x() + ( abs(m_xSpeed) - (int(newPos.x() + getCollider().x + getCollider().w) % (*m_pCollisionLayers->begin())->getTileSize()))); } else // Collision with tile to the left { m_position.x(m_position.x() - (int(m_position.x() + getCollider().x) % (*m_pCollisionLayers->begin())->getTileSize())); } } } else { // no collision, add to the actual x position m_position.x(newPos.x()); } } } newPos.x(m_position.x()); newPos.y(m_position.y() + velocity.y()); // check if the chaser is going below map limits if (newPos.y() + getCollider().y + getCollider().h > TheGame::Instance().getMapHeight()) { m_position.y(TheGame::Instance().getMapHeight() - getCollider().h - getCollider().y); m_velocity.y(0); } else { if (checkCollideTile(newPos) || checkCollideObject(newPos)) { // Collision, stop y movement m_velocity.y(0); if (checkCollideTile(newPos)) { // Collision with map, move to contact. Chaser doesn't jump so it's a lower tile m_position.y(m_position.y() + (m_ySpeed - (int(newPos.y() + getCollider().y + getCollider().h) % (*m_pCollisionLayers->begin())->getTileSize()))); } } else { // no collision, add to the actual y position m_position.y(newPos.y()); } } }
void PhysicsEntity::move(PhysicsEntity::Direction dir) { Colliders::RectangleCollider collider = getCollider(); switch (dir) { case Direction_Top: if (_collisionSubscriber->value()->isColliding(collider.margin((int) speed(), Colliders::Direction_Top))) { for (int allowedMargin = (int) speed(); allowedMargin >= 0; allowedMargin--) { if (!_collisionSubscriber->value()->isColliding( collider.margin(allowedMargin, Colliders::Direction_Top))) { setPosition(position() + Vector2(0, -allowedMargin)); break; } } } else setPosition(position() + Vector2(0, -speed())); break; case Direction_Right: if (_collisionSubscriber->value()->isColliding(collider.margin((int) speed(), Colliders::Direction_Right))) { for (int allowedMargin = (int) speed(); allowedMargin >= 0; allowedMargin--) { if (!_collisionSubscriber->value()->isColliding( collider.margin(allowedMargin, Colliders::Direction_Right))) { setPosition(position() + Vector2(allowedMargin, 0)); break; } } } else setPosition(position() + Vector2(speed(), 0)); break; case Direction_Left: if (_collisionSubscriber->value()->isColliding(collider.margin((int) speed(), Colliders::Direction_Left))) { for (int allowedMargin = (int) speed(); allowedMargin >= 0; allowedMargin--) { if (!_collisionSubscriber->value()->isColliding( collider.margin(allowedMargin, Colliders::Direction_Left))) { setPosition(position() + Vector2(-allowedMargin, 0)); break; } } } else setPosition(position() + Vector2(-speed(), 0)); break; case Direction_Bottom: if (_collisionSubscriber->value()->isColliding(collider.margin((int) speed(), Colliders::Direction_Bottom))) { for (int allowedMargin = (int) speed(); allowedMargin >= 0; allowedMargin--) { if (!_collisionSubscriber->value()->isColliding( collider.margin(allowedMargin, Colliders::Direction_Bottom))) { setPosition(position() + Vector2(0, allowedMargin)); break; } } } else setPosition(position() + Vector2(0, speed())); break; } }