117 lines
3.8 KiB
Python
117 lines
3.8 KiB
Python
from decimal import Decimal
|
|
|
|
from PyQt5.QtCore import Qt, QBasicTimer, QTimerEvent
|
|
from PyQt5.QtGui import QPainter, QPaintEvent, QKeyEvent, QPen, QColor, QFont, QFontMetrics
|
|
from PyQt5.QtWidgets import QWidget, QApplication
|
|
|
|
from physics import calculate_collision
|
|
|
|
|
|
class Window(QWidget):
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
self.setWindowTitle("Pi Collisions")
|
|
self.setFixedSize(640, 480)
|
|
|
|
self.m1: int = 1
|
|
self.v1: Decimal = Decimal(0)
|
|
self.x1: Decimal = Decimal(150)
|
|
self.s1: int = 50
|
|
|
|
self.m2: int = 100 ** 1
|
|
self.v2: Decimal = Decimal(-1)
|
|
self.x2: Decimal = Decimal(300)
|
|
self.s2: int = 100
|
|
|
|
self.t: Decimal = Decimal(0)
|
|
self.wall: bool = False
|
|
|
|
self.timer: QBasicTimer = QBasicTimer()
|
|
self.timer.start(20, self)
|
|
|
|
self.counter: int = 0
|
|
|
|
self.show()
|
|
|
|
def timerEvent(self, e: QTimerEvent):
|
|
if e.timerId() == self.timer.timerId():
|
|
self.tick()
|
|
self.repaint()
|
|
|
|
def tick(self):
|
|
target_time: Decimal = self.t + 1
|
|
|
|
while self.t < target_time:
|
|
if 0 <= self.v1 <= self.v2:
|
|
self.x1 += self.v1
|
|
self.x2 += self.v2
|
|
self.t += 1
|
|
break
|
|
if self.wall:
|
|
# left block collides with wall
|
|
time_wall_collision: Decimal = self.x1 / -self.v1
|
|
if time_wall_collision > 1:
|
|
self.x1 += self.v1
|
|
self.x2 += self.v2
|
|
self.t += 1
|
|
break
|
|
self.x1 += time_wall_collision * self.v1
|
|
self.x2 += time_wall_collision * self.v2
|
|
self.v1 *= -1
|
|
self.t += time_wall_collision
|
|
else:
|
|
# blocks collide with each other
|
|
time_block_collision: Decimal = (self.s1 + self.x1 - self.x2) / (self.v2 - self.v1)
|
|
if time_block_collision > 1:
|
|
self.x1 += self.v1
|
|
self.x2 += self.v2
|
|
self.t += 1
|
|
break
|
|
self.x1 += time_block_collision * self.v1
|
|
self.x2 += time_block_collision * self.v2
|
|
self.v1, self.v2 = calculate_collision(self.m1, self.v1, self.m2, self.v2)
|
|
self.t += time_block_collision
|
|
self.counter += 1
|
|
self.wall = not self.wall
|
|
|
|
def keyReleaseEvent(self, e: QKeyEvent):
|
|
if e.key() == Qt.Key_Q:
|
|
self.close()
|
|
|
|
def paintEvent(self, _: QPaintEvent):
|
|
qp: QPainter = QPainter(self)
|
|
qp.setPen(Qt.white)
|
|
qp.setBrush(Qt.white)
|
|
qp.drawRect(self.rect())
|
|
|
|
qp.setPen(QPen(Qt.black, 5))
|
|
qp.drawLine(50, 0, 50, self.height())
|
|
qp.drawLine(0, self.height() - 50, self.width(), self.height() - 50)
|
|
|
|
qp.setPen(QPen(Qt.black, 2))
|
|
qp.setBrush(QColor("#444444"))
|
|
|
|
qp.drawRect(50 + int(self.x1), self.height() - 52 - self.s1, self.s1, self.s1)
|
|
qp.drawRect(50 + int(self.x2), self.height() - 52 - self.s2, self.s2, self.s2)
|
|
|
|
f: QFont = QFont()
|
|
f.setPixelSize(32)
|
|
qp.setFont(f)
|
|
t: str = str(self.counter)
|
|
qp.drawText(self.width() - 10 - QFontMetrics(f).width(t), 32, t)
|
|
|
|
f.setPixelSize(20)
|
|
qp.setFont(f)
|
|
t: str = f"{self.v1:.2f}"
|
|
w: int = QFontMetrics(f).width(t)
|
|
qp.drawText(50 + int(self.x1) + self.s1 // 2 - w // 2, self.height() - 60 - self.s1, t)
|
|
t: str = f"{self.v2:.2f}"
|
|
w: int = QFontMetrics(f).width(t)
|
|
qp.drawText(50 + int(self.x2) + self.s2 // 2 - w // 2, self.height() - 60 - self.s2, t)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
qa: QApplication = QApplication([])
|
|
w: Window = Window()
|
|
qa.exec_()
|