void Collisionhandler::collisionBetweenEntitiesAndTerrains(Entities &entities, Terrains &terrains){ for (Entities::size_type i = 0; i < entities.size(); i++){ Entity *e0 = entities[i]; for (Terrains::size_type j = 0; j < terrains.size(); j++){ Terrain *e1 = terrains[j]; if (e0->isOnScreen() && e1->isOnScreen()) { if (hasCollided(e0, e1)) { checkCollisionDirection(e0, e1); } } } } }
void Collisionhandler::collisionBetweenEntities(Entities &entities){ for (Entities::size_type i = 0; i < entities.size(); i++){ Entity *e0 = entities[i]; for (Entities::size_type j = i + 1; j < entities.size(); j++){ Entity *e1 = entities[j]; if (e0->isOnScreen() && e1->isOnScreen()) { if (hasCollided(e0, e1)) { if (e0->getType() != e1->getType() && e0->getType() == Entity::PLAYER) { checkCollisionDirection(e0, e1); //checkCollisionDirection(e1, e0); } } } } } }
void Shot::draw(BITMAP *buffer, int offsetX, int offsetY, int layer){ int x = getDrawPositionX(); int y = getDrawPositionY(); int frame; if(! hasCollided()){ frame = mFrame/10; mShotAnimation[mShotType]->drawFrame(buffer, frame, offsetX + x - mShotAnimation[mShotType]->getFrameWidth()/2, offsetY + y+getHalfSize().y-mShotAnimation[mShotType]->getFrameHeight()); } else { cFrame++; frame = cFrame/10; mCollisionAnimation[mShotType]->drawFrame(buffer, frame, offsetX + x - mCollisionAnimation[mShotType]->getFrameWidth()/2, offsetY + y+getHalfSize().y-mCollisionAnimation[mShotType]->getFrameHeight()); } }
//Stroke vs rectangle bool hasCollided(sf::Vector2f c1, float r11, float r12, sf::Vector2f c2, sf::Vector2f s2, float dir2) { if (!hasCollided(c2, s2, dir2, c1, r12)) return false; if (r11 < 0) return false; //Transforming vectors float unitX2 = cos(dir2); float unitY2 = sin(dir2); sf::Vector2f rotWidth2(unitX2 * s2.x / 2.f, unitY2 * s2.x / 2.f); sf::Vector2f rotHeight2(-unitY2 * s2.y / 2.f, unitX2 * s2.y / 2.f); sf::Vector2f tr2[] = {c2 - rotWidth2 - rotHeight2, c2 + rotWidth2 - rotHeight2, c2 + rotWidth2 + rotHeight2, c2 - rotWidth2 + rotHeight2}; //Inside edge cross check if (getDist(c1, tr2[0]) > r11) return true; if (getDist(c1, tr2[1]) > r11) return true; if (getDist(c1, tr2[2]) > r11) return true; if (getDist(c1, tr2[3]) > r11) return true; return false; }
void Simulation::collisionResolution() { bool collisionDetected = false; auto first = planetList.begin(); while(first != planetList.end()) { for(auto second = planetList.begin(); second != planetList.end(); second++) { if( (*first) != (*second) && first->hasCollided(*second)) { planetList.push_back((*first) + (*second)); planetList.erase(second); first = planetList.erase(first); //erase the two collided planets. collisionDetected = true; break; } } if(collisionDetected) //If there is a collision, then "first" automatically points to the next value, so there is no need to increment it. collisionDetected = false; else first++; } }
bool hasCollided(sf::Vector2f c1, util::ShapeVector s1, float dir1, sf::Vector2f c2, util::ShapeVector s2, float dir2) { if (s1.s == Point && s2.s == Point) return hasCollided(c1, c2); if (s1.s == Point && s2.s == Circle) return hasCollided(c1, c2, s2.x); if (s1.s == Point && s2.s == Rectangle) return hasCollided(c1, c2, sf::Vector2f(s2.x, s2.y), dir2); if (s1.s == Point && s2.s == Stroke) return hasCollided(c1, c2, s2.x, s2.y); if (s1.s == Circle && s2.s == Point) return hasCollided(c2, c1, s1.x); if (s1.s == Circle && s2.s == Circle) return hasCollided(c1, s1.x, c2, s2.x); if (s1.s == Circle && s2.s == Rectangle) return hasCollided(c2, sf::Vector2f(s2.x, s2.y), dir2, c1, s1.x); if (s1.s == Circle && s2.s == Stroke) return hasCollided(c2, s2.x, s2.y, c1, s1.x); if (s1.s == Rectangle && s2.s == Point) return hasCollided(c2, c1, sf::Vector2f(s1.x, s1.y), dir1); if (s1.s == Rectangle && s2.s == Circle) return hasCollided(c1, sf::Vector2f(s1.x, s1.y), dir1, c2, s2.x); if (s1.s == Rectangle && s2.s == Rectangle) return hasCollided(c1, sf::Vector2f(s1.x, s1.y), dir1, c2, sf::Vector2f(s2.x, s2.y), dir2); if (s1.s == Rectangle && s2.s == Stroke) return hasCollided(c2, s2.x, s2.y, c1, sf::Vector2f(s1.x, s1.y), dir1); if (s1.s == Stroke && s2.s == Point) return hasCollided(c2, c1, s1.x, s1.y); if (s1.s == Stroke && s2.s == Circle) return hasCollided(c1, s1.x, s1.y, c2, s2.x); if (s1.s == Stroke && s2.s == Rectangle) return hasCollided(c1, s1.x, s1.y, c2, sf::Vector2f(s2.x, s2.y), dir2); return false; }
void Shot::update(){ if (++mLife > 180){ setCollided(true); } if (touchesDangerousTile()){ setCollided(true); } if(hasCollided()){ if (--mCollidedTimer < 0){ remove(); //remove } return; } // move int cur_x = getPosition().x; int cur_y = getPosition().y; int floor_y, edge_x; int bumps; /* floor_y= cur_y+getHalfSize().y+5; if (mFacingDirection == Direction_Left){ edge_x=cur_x-getHalfSize().x; } else { edge_x=cur_x+getHalfSize().x; } */ if(mGravity[mShotType] == ShotType_Bullet){ setVelocity(float2(mInitialVelocity[mShotType].x*getDirection(),mInitialVelocity[mShotType].y)); } else { setVelocity(float2(mInitialVelocity[mShotType].x*getDirection(),mInitialVelocity[mShotType].y+GRAVITY*mLife)); } //setVelocity(float2(12.0f,.0f)); bumps=moveWithCollision(); if((bumps & Direction_Left) != 0 || (bumps & Direction_Right) != 0 || (bumps & Direction_Up) != 0|| (bumps & Direction_Down) != 0 ){ setCollided(true); if (mShotType == ShotType_GravityGrenade || mShotType == ShotType_Fireball) { Sound::playSample("data/sounds/grenadeexplode.wav"); } } if(!mHurtPlayer){ std::vector<Entity*> collidedEntity = mRoom->checkEntitiesForCollision(this); if(collidedEntity.size() > 0){ setCollided(true); if (mShotType == ShotType_GravityGrenade || mShotType == ShotType_Fireball) { Sound::playSample("data/sounds/grenadeexplode.wav"); } for(int i=0;i<collidedEntity.size();i++){ attack(collidedEntity[i]); } } } else { Hero* h = mRoom->getHero(); Entity::CollisionRect cr= h->getCollisionRect(); if(Collides(getCollisionRect(),cr)){ setCollided(true); if (mShotType == ShotType_GravityGrenade || mShotType == ShotType_Fireball) { Sound::playSample("data/sounds/grenadeexplode.wav"); } if(mShotType == ShotType_Fireball || mShotType == ShotType_Bullet){ h->die(); return; } if(mShotType == ShotType_GravityGrenade){ attack(h); return; } } } mFrame++; }
/* Calculates the coordinates of the collision point */ void Convex::convexCollision(Convex* other, sf::RenderWindow* window) { sf::Vector2f collisionNormal; float collisionX, collisionY; float x1, x2, x3, x4, y1, y2, y3, y4; if (hasCollided(other)) { for (int i = 0; i < getPointCount(); i++) { //Retrieves the coordinates of the point i x1 = this->getPoint(i).x; y1 = this->getPoint(i).y; //If the index 'i' equals the amount of points //the other end of the line should be the starting point if (i == getPointCount() - 1) { x2 = this->getPoint(0).x; y2 = this->getPoint(0).y; } else { x2 = this->getPoint(i + 1).x; y2 = this->getPoint(i + 1).y; } for (int j = 0; j < other->getPointCount(); j++) { x3 = other->getPoint(j).x; y3 = other->getPoint(j).y; //If the index 'j' equals the amount of points //the other end of the line should be the starting point if (i == getPointCount() - 1) { x4 = other->getPoint(0).x; y4 = other->getPoint(0).y; } else { x4 = other->getPoint(i + 1).x; y4 = other->getPoint(i + 1).y; } collisionX = vectorProduct(vectorProduct(x1, y1, x2, y2), vectorProduct(x1, 1, x2, 1), vectorProduct(x3, y3, x4, y4), vectorProduct(x3, 1, x4, 1)) / vectorProduct(vectorProduct(x1, 1, x2, 1), vectorProduct(y1, 1, y2, 1), vectorProduct(x3, 1, x4, 1), vectorProduct(y3, 1, y4, 1)); collisionY = vectorProduct(vectorProduct(x1, y1, x2, y2), vectorProduct(y1, 1, y2, 1), vectorProduct(x3, y3, x4, y4), vectorProduct(y3, 1, y4, 1)) / vectorProduct(vectorProduct(x1, 1, x2, 1), vectorProduct(y1, 1, y2, 1), vectorProduct(x3, 1, x4, 1), vectorProduct(y3, 1, y4, 1)); //Checking that the collision point is actually between the corners //of the convexes if (isBetween(collisionX, x1, x2) && isBetween(collisionX, x3, x4) && isBetween(collisionY, y1, y2) && isBetween(collisionY, y3, y4)) { //If the collision point is between these points use them to calculate the //collisionNormal's components if (isBetween(collisionX, x1, x2) && isBetween(collisionY, y1, y2)) { float x = x2 - x1; float y = y2 - y1; float length = sqrt(pow(x, 2) + pow(y, 2)); float unitX = x / length; float unitY = y / length; collisionNormal.x = -unitY; collisionNormal.y = unitX; float impulse = getImpulse(&sf::Vector2f(collisionX, collisionY), &collisionNormal, other, this); applyChanges(&collisionNormal, impulse, &sf::Vector2f(collisionX, collisionY), other, this); } else { float x = x4 - x3; float y = y4 - y3; float length = sqrt(pow(x, 2) + pow(y, 2)); float unitX = x / length; float unitY = y / length; collisionNormal.x = -unitY; collisionNormal.y = unitX; float impulse = getImpulse(&sf::Vector2f(collisionX, collisionY), &collisionNormal, this, other); applyChanges(&collisionNormal, impulse, &sf::Vector2f(collisionX, collisionY), this, other); } sf::CircleShape circle(5); circle.setFillColor(sf::Color::Red); circle.setPosition(collisionX, collisionY); window->draw(circle); } } } } }
const int Ball::move(short scrWidth, short scrHeight, double deltaTime, const SDL_Rect bat, const double batSpeed, std::vector<Brick*>& bricks) { direction.normalize(); int score = 0; const int speedCollisionIncrease = 6; //===================== //MOVE THE BALL ACROSS //===================== const double xMove = direction.x * speed * deltaTime; position.x += xMove; //the only time it'll hit the player after moving across is when it hits the end of the bat //so reverse both velocities if( hasCollided(bat) ) { position.x -= xMove; direction.x *= -1; direction.y *= -1; speed += speedCollisionIncrease; } //left or right of the screen if(position.x - radius < 0) { position.x = radius; direction.x *= -1; } else if (position.x + radius > scrWidth) { position.x = scrWidth - radius; direction.x *= -1; } //if a brick is destructible, increment the score with the brick's score //destroy the brick, move the player back and reverse their direction for(auto& b : bricks) { if( hasCollided(b->box()) ) { if( b->isDestructible() ) { score += b->getScore(); delete b; b = nullptr; } position.x -= xMove; direction.x *= -1; speed += speedCollisionIncrease; } } bricks.erase(std::remove(bricks.begin(), bricks.end(), static_cast<Brick*>(nullptr)), bricks.end()); //==================== //MOVE THE BALL DOWN //==================== const double yMove = direction.y * speed * deltaTime; position.y += yMove; //put the ball on the top of the bat so it doesn't get caught "inside" it and reverse the direction //the last line adds some spin onto the ball if( hasCollided(bat)) { position.y = bat.y - radius; direction.y *= -1; speed += speedCollisionIncrease; direction.x += batSpeed * 0.05f; } //top of the screen if(position.y - radius < 0) { position.y = radius; direction.y *= -1; } //bottom of the screen //return -1 as a special case to say the ball is off screen if(position.y - radius > scrHeight) { return -1; } for(auto& b : bricks) { if( hasCollided(b->box()) ) { if( b->isDestructible() ) { score += b->getScore(); delete b; b = nullptr; } position.y -= yMove; direction.y *= -1; speed += speedCollisionIncrease; } } bricks.erase(std::remove(bricks.begin(), bricks.end(), static_cast<Brick*>(nullptr)), bricks.end()); return score; }