diff --git a/seminar13_polymorphism/arkanoid/arkanoid.cpp b/seminar13_polymorphism/arkanoid/arkanoid.cpp index 55e8b73..8256e4c 100644 --- a/seminar13_polymorphism/arkanoid/arkanoid.cpp +++ b/seminar13_polymorphism/arkanoid/arkanoid.cpp @@ -16,19 +16,23 @@ void Arkanoid::addRandomBonus(sf::Vector2f position) int max_rand = 10000; if ((rand() % max_rand) * 1.0f / max_rand < m_bonusProbability) { - m_bonuses.push_back(new TripleBallBonus(position)); - } - if ((rand() % max_rand) * 1.0f / max_rand < m_bonusProbability) - { - m_bonuses.push_back(new EnlargePaddleBonus(position)); - } - if ((rand() % max_rand) * 1.0f / max_rand < m_bonusProbability) - { - m_bonuses.push_back(new ShrinkPaddleBonus(position)); - } - if ((rand() % max_rand) * 1.0f / max_rand < m_bonusProbability) - { - m_bonuses.push_back(new SlowingBonus(position)); + int max = 4; int min = 1; + int range = max - min + 1; + int num = rand() % range + min; + switch (num) { + case 1: + m_bonuses.push_back(new TripleBallBonus(position)); + break; + case 2: + m_bonuses.push_back(new EnlargePaddleBonus(position)); + break; + case 3: + m_bonuses.push_back(new ShrinkPaddleBonus(position)); + break; + case 4: + m_bonuses.push_back(new SlowingBonus(position)); + break; + } } } @@ -87,6 +91,11 @@ void Arkanoid::addBall(const Ball& ball) m_balls.push_back(ball); } +bool Arkanoid::isMaxBalls() +{ + return m_balls.size() == kMaxNumBalls - 1; +} + // Эта функция вызывается каждый кадр void Arkanoid::update(const sf::RenderWindow& window, float dt) { @@ -114,6 +123,7 @@ void Arkanoid::update(const sf::RenderWindow& window, float dt) // Если шариков нет, то переходи в режим начала игры и уменьшаем кол-во жизней if (m_gameState == GameState::running && m_balls.size() == 0) { + m_effects.clear(); m_gameState = GameState::stuck; m_numLives--; } @@ -154,7 +164,6 @@ void Arkanoid::update(const sf::RenderWindow& window, float dt) /* Обработка эффектов */ for (auto it = m_effects.begin(); it != m_effects.end();) { - std::cout << "meow1" << std::endl; if ((*it)->isExpired(m_time)) { (*it)->deactivate(*this); diff --git a/seminar13_polymorphism/arkanoid/arkanoid.hpp b/seminar13_polymorphism/arkanoid/arkanoid.hpp index 5a1e68f..46b2523 100644 --- a/seminar13_polymorphism/arkanoid/arkanoid.hpp +++ b/seminar13_polymorphism/arkanoid/arkanoid.hpp @@ -74,6 +74,7 @@ public: void draw(sf::RenderWindow& window); void onMousePressed(sf::Event& event); + bool isMaxBalls(); // Класс бонус должен быть дружественным, так как он может менять внутреннее состояние игры friend class Bonus; diff --git a/seminar13_polymorphism/arkanoid/ball.hpp b/seminar13_polymorphism/arkanoid/ball.hpp index 115313e..2bca550 100644 --- a/seminar13_polymorphism/arkanoid/ball.hpp +++ b/seminar13_polymorphism/arkanoid/ball.hpp @@ -13,9 +13,6 @@ struct Ball sf::Vector2f position; sf::Vector2f velocity; - /* Every bit is responsible for ball being affected by some effect */ - char affectedBy = 0; - Ball(float radius, sf::Vector2f position, sf::Vector2f velocity); void update(float dt); diff --git a/seminar13_polymorphism/arkanoid/bonus.cpp b/seminar13_polymorphism/arkanoid/bonus.cpp index 641af55..389e658 100644 --- a/seminar13_polymorphism/arkanoid/bonus.cpp +++ b/seminar13_polymorphism/arkanoid/bonus.cpp @@ -53,17 +53,48 @@ void TripleBallBonus::activate(Arkanoid& game) int numBalls = game.m_balls.size(); std::list::iterator it = game.m_balls.begin(); + bool isSlowed = false; + bool toApply = true; + Effect* slowing_effect = nullptr; + for (auto it = game.m_effects.begin(); it != game.m_effects.end();) { + if ((*it)->effectId == 0) { + isSlowed = true; + slowing_effect = *it; + break; + } + it++; + } for (int i = 0; i < numBalls; i++) { - float angle = rand() % 1000 * (2 * M_PI / 1000); - float vx = Ball::initialVelocity * sin(angle); - float vy = Ball::initialVelocity * cos(angle); - game.addBall({game.m_initialBall.radius, (*it).position, {vx, vy}}); + float angle, vx, vy; + if (game.isMaxBalls()) { + toApply = false; + } - angle = rand() % 1000 * (2 * M_PI / 1000); - vx = Ball::initialVelocity * sin(angle); - vy = Ball::initialVelocity * cos(angle); - game.addBall({game.m_initialBall.radius, (*it).position, {vx, vy}}); + if (toApply) { + angle = rand() % 1000 * (2 * M_PI / 1000); + vx = Ball::initialVelocity * sin(angle); + vy = Ball::initialVelocity * cos(angle); + game.addBall({game.m_initialBall.radius, (*it).position, {vx, vy}}); + + if (isSlowed) { + slowing_effect->activate(game.m_balls.back()); + } + } + + if (game.isMaxBalls()) { + toApply = false; + } + + if (toApply) { + angle = rand() % 1000 * (2 * M_PI / 1000); + vx = Ball::initialVelocity * sin(angle); + vy = Ball::initialVelocity * cos(angle); + game.addBall({game.m_initialBall.radius, (*it).position, {vx, vy}}); + if (isSlowed) { + slowing_effect->activate(game.m_balls.back()); + } + } it++; } @@ -90,7 +121,9 @@ void EnlargePaddleBonus::draw(sf::RenderWindow& window) const void EnlargePaddleBonus::activate(Arkanoid& game) { - game.m_paddle.size.x *= 1.5; + if (game.m_paddle.size.x < 300) { + game.m_paddle.size.x *= 1.5; + } } EnlargePaddleBonus::~EnlargePaddleBonus() {} @@ -113,7 +146,9 @@ void ShrinkPaddleBonus::draw(sf::RenderWindow& window) const } void ShrinkPaddleBonus::activate(Arkanoid& game) { - game.m_paddle.size.x *= 0.8; + if (game.m_paddle.size.x > 40) { + game.m_paddle.size.x *= 0.8; + } } ShrinkPaddleBonus::~ShrinkPaddleBonus() {} @@ -137,8 +172,19 @@ void SlowingBonus::draw(sf::RenderWindow& window) const } void SlowingBonus::activate(Arkanoid& game) { - game.m_effects.push_back(new SlowingEffect(game.m_time, 10)); - game.m_effects.back()->activate(game); + bool isAlreadySlowed = false; + for (auto it = game.m_effects.begin(); it != game.m_effects.end();) { + if ((*it)->effectId == 0) { + (*it)->mDuration += mDuration; + isAlreadySlowed = true; + break; + } + it++; + } + if (!isAlreadySlowed) { + game.m_effects.push_back(new SlowingEffect(game.m_time, mDuration)); + game.m_effects.back()->activate(game); + } } SlowingBonus::~SlowingBonus() {} @@ -147,7 +193,7 @@ SlowingBonus::~SlowingBonus() {} * Effects * */ -Effect::Effect(double start_time, double duration) : mStartTime(start_time), mDuration(duration) {}; +Effect::Effect(char id, double start_time, double duration) : effectId(id), mStartTime(start_time), mDuration(duration) {}; bool Effect::isExpired(double time) { if (mStartTime + mDuration > time) @@ -155,27 +201,30 @@ bool Effect::isExpired(double time) { return true; } -SlowingEffect::SlowingEffect(double start_time, double duration) : Effect(start_time, duration) {}; +SlowingEffect::SlowingEffect(double start_time, double duration) : Effect(0, start_time, duration) {}; void SlowingEffect::activate(Arkanoid& game) { - std::cout << "Activated slow motion" << std::endl; for (Ball& ball : game.m_balls) { - //std::cout << "meow" << std::endl; - if (!(ball.affectedBy & 0b00000001)) { - ball.affectedBy |= 0b00000001; + //if (!(ball.affectedBy & 0b00000001)) { + //ball.affectedBy |= 0b00000001; ball.velocity = sf::Vector2f{ball.velocity.x * mSlowingFactor, ball.velocity.y * mSlowingFactor}; - } + //} } } +void SlowingEffect::activate(Ball& ball) { + //if (!(ball.affectedBy & 0b00000001)) { + //ball.affectedBy |= 0b00000001; + ball.velocity = sf::Vector2f{ball.velocity.x * mSlowingFactor, ball.velocity.y * mSlowingFactor}; +} + void SlowingEffect::deactivate(Arkanoid& game) { - std::cout << "Deactivated slow motion" << std::endl; for (Ball& ball : game.m_balls) { - if (ball.affectedBy & 0b00000001) { + //if (ball.affectedBy & 0b00000001) { ball.velocity = sf::Vector2f{ball.velocity.x / mSlowingFactor, ball.velocity.y / mSlowingFactor}; - ball.affectedBy &= 0b11111110; - } + // ball.affectedBy &= 0b11111110; + //} } } diff --git a/seminar13_polymorphism/arkanoid/bonus.hpp b/seminar13_polymorphism/arkanoid/bonus.hpp index 3333330..6f410c2 100644 --- a/seminar13_polymorphism/arkanoid/bonus.hpp +++ b/seminar13_polymorphism/arkanoid/bonus.hpp @@ -66,20 +66,28 @@ public: class Effect { private: + char effectId; double mStartTime; double mDuration; public: - Effect(double start_time, double duration); + Effect(char id, double start_time, double duration); virtual void activate(Arkanoid& game) {}; + virtual void activate(Ball& ball) {}; virtual void deactivate(Arkanoid& game) {}; bool isExpired(double time); + + friend class SlowingBonus; + friend class TripleBallBonus; + friend class Arkanoid; }; class SlowingEffect : public Effect { private: double mSlowingFactor = 0.1; + char id = 0; public: SlowingEffect(double start_time, double duration); void activate(Arkanoid& game); + void activate(Ball& ball); void deactivate(Arkanoid& game); };