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;
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);

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

@ -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);

@ -53,17 +53,48 @@ void TripleBallBonus::activate(Arkanoid& game)
int numBalls = game.m_balls.size();
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++)
{
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;
//}
}
}

@ -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);
};