Добавление физики шару в 2д игре

вот я решил сделать программку, в которой шар катается по экрану, его можно кидать по экрану, а он будет отталкиваться от стенок и так далее. Естественно у меня появились проблемы, т.к. чтобы это сделать знаний не хватает...

вот код:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class BallApp(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.Tool)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
        self.setGeometry(0, 0, QtWidgets.QDesktopWidget().screenGeometry().width(),
                         QtWidgets.QDesktopWidget().screenGeometry().height())

        self.ball_radius = 30  # радиус шара
        self.ball_color = QtGui.QColor(0, 0, 0)  # черный цвет
        self.outer_color = QtGui.QColor(255, 255, 255)  # белая обводка
        self.ball_pos = QtCore.QPoint(self.width() // 2, 0)  # начальная позиция шара
        self.velocity = QtCore.QPoint(0, 0)
        self.is_dragging = False
        self.offset = QtCore.QPoint(0, 0)

        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.update_ball_position)
        self.timer.start(16)

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)

        # Рисуем шар
        painter.setBrush(self.ball_color)
        painter.setPen(QtGui.QPen(self.outer_color, 1))
        painter.drawEllipse(self.ball_pos.x() - self.ball_radius, self.ball_pos.y() - self.ball_radius,
                            self.ball_radius * 2, self.ball_radius * 2)

    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            if self.is_ball_at(event.pos()):
                self.is_dragging = True
                self.offset = event.pos() - self.ball_pos
                self.velocity = QtCore.QPoint(0, 0)  # Остановить шар

        # Закрытие программы
        if event.button() == QtCore.Qt.RightButton:
            QtCore.QCoreApplication.quit()  # Завершение работы приложения

    def mouseMoveEvent(self, event):
        if self.is_dragging:
            self.ball_pos = event.pos() - self.offset

    def mouseReleaseEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton and self.is_dragging:
            self.is_dragging = False
            self.velocity = event.pos() - self.ball_pos
            self.ball_pos += self.velocity

    def is_ball_at(self, pos):
        return (self.ball_pos.x() - self.ball_radius <= pos.x() <= self.ball_pos.x() + self.ball_radius and
                self.ball_pos.y() - self.ball_radius <= pos.y() <= self.ball_pos.y() + self.ball_radius)

    def update_ball_position(self):
        # Упругость
        if not self.is_dragging:
            if self.ball_pos.y() + self.ball_radius < self.height():
                self.velocity.setY(self.velocity.y() + 1)  # гравитация
            else:
                self.velocity.setY(int(-self.velocity.y() * 0.7))  # отскок с потерей энергии
                self.ball_pos.setY(self.height() - self.ball_radius)

            self.ball_pos += self.velocity

            # Отталкивание от краев
            if self.ball_pos.x() < 0:
                self.ball_pos.setX(0)
                self.velocity.setX(-self.velocity.x())  # Отскок в другую сторону
            elif self.ball_pos.x() > self.width() - self.ball_radius * 2:
                self.ball_pos.setX(self.width() - self.ball_radius * 2)
                self.velocity.setX(-self.velocity.x())  # Отскок в другую сторону

            self.ball_pos.setY(max(0, min(self.ball_pos.y(), self.height() - self.ball_radius)))

        self.update()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = BallApp()
    window.showFullScreen()
    sys.exit(app.exec_())

как мне сделать так, чтобы я курсором мог кидать этот шар? Чтобы шар после отпускания левой кнопки мыши летел в ту сторону, в которую двигался курсор, чтобы летел с той скоростью, с которой двигался курсор или например курсор остановился, я отпустил кнопку и шар просто полетел вертикально вниз.

Также как мне добавить физику шару? Чтобы шар при полете вверх немного замедлялся, при полете вниз ускорялся, чтобы он летел не слишком прямо, а немного дугообразно, ну как в реальности?

Также я не смог сделать так, чтобы шар при полной его остановке остановился окончательно, вместо этого он продолжает кататься по нижней части экрана бесконечно долго.

Я буду вам признателен, если вы мне объясните что к чему и как.


Ответы (0 шт):