seminar13 - arkanoid, working slow motion bonus

master
nihonium 2 years ago
parent a6b1bccd37
commit 7697130f21
No known key found for this signature in database
GPG Key ID: 0251623741027CFC

@ -16,19 +16,23 @@ void Arkanoid::addRandomBonus(sf::Vector2f position)
int max_rand = 10000; int max_rand = 10000;
if ((rand() % max_rand) * 1.0f / max_rand < m_bonusProbability) if ((rand() % max_rand) * 1.0f / max_rand < m_bonusProbability)
{ {
m_bonuses.push_back(new TripleBallBonus(position)); int max = 4; int min = 1;
} int range = max - min + 1;
if ((rand() % max_rand) * 1.0f / max_rand < m_bonusProbability) int num = rand() % range + min;
{ switch (num) {
m_bonuses.push_back(new EnlargePaddleBonus(position)); case 1:
} m_bonuses.push_back(new TripleBallBonus(position));
if ((rand() % max_rand) * 1.0f / max_rand < m_bonusProbability) break;
{ case 2:
m_bonuses.push_back(new ShrinkPaddleBonus(position)); m_bonuses.push_back(new EnlargePaddleBonus(position));
} break;
if ((rand() % max_rand) * 1.0f / max_rand < m_bonusProbability) case 3:
{ m_bonuses.push_back(new ShrinkPaddleBonus(position));
m_bonuses.push_back(new SlowingBonus(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); m_balls.push_back(ball);
} }
bool Arkanoid::isMaxBalls()
{
return m_balls.size() == kMaxNumBalls - 1;
}
// Эта функция вызывается каждый кадр // Эта функция вызывается каждый кадр
void Arkanoid::update(const sf::RenderWindow& window, float dt) 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) if (m_gameState == GameState::running && m_balls.size() == 0)
{ {
m_effects.clear();
m_gameState = GameState::stuck; m_gameState = GameState::stuck;
m_numLives--; 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();) for (auto it = m_effects.begin(); it != m_effects.end();)
{ {
std::cout << "meow1" << std::endl;
if ((*it)->isExpired(m_time)) if ((*it)->isExpired(m_time))
{ {
(*it)->deactivate(*this); (*it)->deactivate(*this);

@ -74,6 +74,7 @@ public:
void draw(sf::RenderWindow& window); void draw(sf::RenderWindow& window);
void onMousePressed(sf::Event& event); void onMousePressed(sf::Event& event);
bool isMaxBalls();
// Класс бонус должен быть дружественным, так как он может менять внутреннее состояние игры // Класс бонус должен быть дружественным, так как он может менять внутреннее состояние игры
friend class Bonus; friend class Bonus;

@ -13,9 +13,6 @@ struct Ball
sf::Vector2f position; sf::Vector2f position;
sf::Vector2f velocity; 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); Ball(float radius, sf::Vector2f position, sf::Vector2f velocity);
void update(float dt); void update(float dt);

@ -53,17 +53,48 @@ void TripleBallBonus::activate(Arkanoid& game)
int numBalls = game.m_balls.size(); int numBalls = game.m_balls.size();
std::list<Ball>::iterator it = game.m_balls.begin(); std::list<Ball>::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++) for (int i = 0; i < numBalls; i++)
{ {
float angle = rand() % 1000 * (2 * M_PI / 1000); float angle, vx, vy;
float vx = Ball::initialVelocity * sin(angle); if (game.isMaxBalls()) {
float vy = Ball::initialVelocity * cos(angle); toApply = false;
game.addBall({game.m_initialBall.radius, (*it).position, {vx, vy}}); }
angle = rand() % 1000 * (2 * M_PI / 1000); if (toApply) {
vx = Ball::initialVelocity * sin(angle); angle = rand() % 1000 * (2 * M_PI / 1000);
vy = Ball::initialVelocity * cos(angle); vx = Ball::initialVelocity * sin(angle);
game.addBall({game.m_initialBall.radius, (*it).position, {vx, vy}}); 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++; it++;
} }
@ -90,7 +121,9 @@ void EnlargePaddleBonus::draw(sf::RenderWindow& window) const
void EnlargePaddleBonus::activate(Arkanoid& game) 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() {} EnlargePaddleBonus::~EnlargePaddleBonus() {}
@ -113,7 +146,9 @@ void ShrinkPaddleBonus::draw(sf::RenderWindow& window) const
} }
void ShrinkPaddleBonus::activate(Arkanoid& game) 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() {} ShrinkPaddleBonus::~ShrinkPaddleBonus() {}
@ -137,8 +172,19 @@ void SlowingBonus::draw(sf::RenderWindow& window) const
} }
void SlowingBonus::activate(Arkanoid& game) void SlowingBonus::activate(Arkanoid& game)
{ {
game.m_effects.push_back(new SlowingEffect(game.m_time, 10)); bool isAlreadySlowed = false;
game.m_effects.back()->activate(game); 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() {} SlowingBonus::~SlowingBonus() {}
@ -147,7 +193,7 @@ SlowingBonus::~SlowingBonus() {}
* Effects * 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) { bool Effect::isExpired(double time) {
if (mStartTime + mDuration > time) if (mStartTime + mDuration > time)
@ -155,27 +201,30 @@ bool Effect::isExpired(double time) {
return true; 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) { void SlowingEffect::activate(Arkanoid& game) {
std::cout << "Activated slow motion" << std::endl;
for (Ball& ball : game.m_balls) for (Ball& ball : game.m_balls)
{ {
//std::cout << "meow" << std::endl; //if (!(ball.affectedBy & 0b00000001)) {
if (!(ball.affectedBy & 0b00000001)) { //ball.affectedBy |= 0b00000001;
ball.affectedBy |= 0b00000001;
ball.velocity = sf::Vector2f{ball.velocity.x * mSlowingFactor, ball.velocity.y * mSlowingFactor}; 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) { void SlowingEffect::deactivate(Arkanoid& game) {
std::cout << "Deactivated slow motion" << std::endl;
for (Ball& ball : game.m_balls) 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.velocity = sf::Vector2f{ball.velocity.x / mSlowingFactor, ball.velocity.y / mSlowingFactor};
ball.affectedBy &= 0b11111110; // ball.affectedBy &= 0b11111110;
} //}
} }
} }

@ -66,20 +66,28 @@ public:
class Effect { class Effect {
private: private:
char effectId;
double mStartTime; double mStartTime;
double mDuration; double mDuration;
public: public:
Effect(double start_time, double duration); Effect(char id, double start_time, double duration);
virtual void activate(Arkanoid& game) {}; virtual void activate(Arkanoid& game) {};
virtual void activate(Ball& ball) {};
virtual void deactivate(Arkanoid& game) {}; virtual void deactivate(Arkanoid& game) {};
bool isExpired(double time); bool isExpired(double time);
friend class SlowingBonus;
friend class TripleBallBonus;
friend class Arkanoid;
}; };
class SlowingEffect : public Effect { class SlowingEffect : public Effect {
private: private:
double mSlowingFactor = 0.1; double mSlowingFactor = 0.1;
char id = 0;
public: public:
SlowingEffect(double start_time, double duration); SlowingEffect(double start_time, double duration);
void activate(Arkanoid& game); void activate(Arkanoid& game);
void activate(Ball& ball);
void deactivate(Arkanoid& game); void deactivate(Arkanoid& game);
}; };