u03-jumping_ball/src/ball.cpp
2025-03-24 18:58:08 +01:00

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