96 lines
2.5 KiB
C++
96 lines
2.5 KiB
C++
#include "ball.h"
|
|
#include <QDebug>
|
|
#include <QRect>
|
|
#include <QWidget>
|
|
#include <qglobal.h>
|
|
#include <random>
|
|
|
|
#define RADIUS 15
|
|
#define TOP_MARGIN 35 // This is the menu bar height (no easy way to get programatically)
|
|
|
|
#define TICK_SPEED 10
|
|
|
|
#define MAX_X_SPEED 5.0
|
|
#define MIN_X_SPEED 2.0
|
|
#define MAX_Y_SPEED 8.0
|
|
#define MIN_Y_SPEED 4.0
|
|
|
|
#define GRAVITY 0.022
|
|
|
|
double getRandomDouble(double minValue, double maxValue);
|
|
|
|
Ball::Ball(QWidget* parent, std::shared_ptr<Platform> platform) : m_parent{parent}, m_platform{platform}, m_isSpawning{true} {
|
|
QRect rct = parent->rect();
|
|
|
|
m_x = rand() % (rct.width() - RADIUS * 2); // random x pos
|
|
m_y = rct.height() + 5; // start below the screen
|
|
|
|
// Random X speed, including rand direction
|
|
// (this isn't simply done with a negative minimum, as we
|
|
// don't want to allow speeds close to 0)
|
|
m_kx = getRandomDouble(MIN_X_SPEED, MAX_X_SPEED);
|
|
if (rand() % 2 == 0)
|
|
m_kx = -m_kx;
|
|
|
|
// Random Y speed (always starts going up / negative)
|
|
m_ky = -getRandomDouble(MIN_Y_SPEED, MAX_Y_SPEED);
|
|
|
|
start(TICK_SPEED);
|
|
}
|
|
|
|
void Ball::draw(QPainter& painter) {
|
|
painter.drawEllipse(m_x, m_y, RADIUS * 2.0, RADIUS * 2.0);
|
|
}
|
|
|
|
void Ball::timerEvent(QTimerEvent*) {
|
|
m_ky = std::min(m_ky + GRAVITY, MAX_Y_SPEED);
|
|
|
|
QRect rct = m_parent->rect();
|
|
|
|
// Horizontal wall collision
|
|
if (m_x < 0 || m_x > rct.width() - RADIUS * 2.0)
|
|
m_kx *= -1;
|
|
|
|
// Ceiling collision
|
|
if (m_y < TOP_MARGIN)
|
|
m_ky *= -1;
|
|
|
|
// Bottom collision (only if no longer spawning)
|
|
if (!m_isSpawning && m_y > rct.height() - RADIUS * 2.0) {
|
|
emit fellThrough(this);
|
|
stop();
|
|
m_parent->update();
|
|
return;
|
|
}
|
|
|
|
// Platform collision (only if no longer spawning)
|
|
if (!m_isSpawning && m_platform->rect().intersects(QRect(m_x, m_y, RADIUS * 2.0, RADIUS * 2.0))) {
|
|
emit caught(this);
|
|
stop();
|
|
m_parent->update();
|
|
return;
|
|
}
|
|
|
|
m_x += m_kx;
|
|
m_y += m_ky;
|
|
|
|
// Once we get above half point of the window, we're no longer "spawning"
|
|
if (m_isSpawning && m_y < rct.height() / 2.0 - RADIUS) {
|
|
m_isSpawning = false;
|
|
}
|
|
|
|
// Update the window
|
|
m_parent->update();
|
|
}
|
|
|
|
double getRandomDouble(double minValue, double maxValue) {
|
|
// Create a random device and a random engine
|
|
std::random_device rd;
|
|
std::mt19937 gen(rd());
|
|
|
|
// Define the range from 0 to maxValue
|
|
std::uniform_real_distribution<> dis(minValue, maxValue);
|
|
|
|
// Return the random value
|
|
return dis(gen);
|
|
}
|