ดูจากพฤติกรรมนอธิบายว่าอยู่เหนือมันเป็นคดีผู้สมัครสำหรับ 2D rigid ร่างฟิสิกส์,บางทีมันอาจจะสามารถทำได้โดยไม่ต้องแต่มันต้องเป็นเรื่องยากที่จะเอามันสมบูรณ์แบบ ฉันใช้ pymunk ในตัวอย่างเช่นเพราะฉันคุ้นเคยกับมันแต่เหมือนทบทวนคอนเซ็ปท์จะทำงานกับไลบรารีแบบใช้ร่.
ที่เกิดเหตุมี kinematic ศพต้องเป็นตัวแทนของเมาส์และวงกลมนี่เป็นตัวแทนโดยคลื่นเสียงบอกความศพตั้งแต่แรก ในขณะที่เป็นวงกลมเป็นการเลือกมัน switches ไปที่แมสซีฟไดนามิร่างกายและ constrained เพื่อนตัวชี้ของเมาส์มาอยู่เหโดย damped ฤดูใบไม้ผลิแล้ว มันคือตำแหน่งปรับปรุงที่พื้นที่ปรับปรุงโดยให้เวลาเธอเหยียบกันหมดเวลาทุกช่วงเวลา.
การซื้อขายทางธุรกิจริงๆแล้วมันไม่ถูกต้องในเชิงกฎระเบียวิธีเดียวกับที่ ItemIsMovable
ธงไม่ถูกเปิดใช้ซึ่งหมายความว่ามันไม่เคลื่อนไหทันด้วยการใช้เมาส์ มันใกล้ชิดกันมาแต่มันเป็นส่วนเล็กหน่วงเวลาถึงแม้ว่าคุณอาจจะชอบนี่ให้ดีขึ้นเห็นว่ามันจะมีปฏิกิริยาคอลลิชัน. (ยังไงก็ตามคุณสามารถสบายดี-รายอย่างที่พารามิเตอร์การเคลื่อนไหวได้เร็วขึ้น/ใกล้ชิดกับตัวชี้ของเมาส์มาอยู่เหว่าฉันทำ**).
อีกด้านนึงที่คอลลิชันเป็นจัดการได้ดีอยู่แล้วและจะสนับสนุนอื่นประเภทรูปร่าง
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import pymunk
class Circle(QGraphicsEllipseItem):
def __init__(self, r, **kwargs):
super().__init__(-r, -r, r * 2, r * 2, **kwargs)
self.setFlag(QGraphicsItem.ItemIsSelectable)
self.static = pymunk.Body(body_type=pymunk.Body.STATIC)
self.circle = pymunk.Circle(self.static, r)
self.circle.friction = 0
mass = 10
self.dynamic = pymunk.Body(mass, pymunk.moment_for_circle(mass, 0, r))
self.updatePos = lambda: self.setPos(*self.dynamic.position, dset=False)
def setPos(self, *pos, dset=True):
super().setPos(*pos)
if len(pos) == 1:
pos = pos[0].x(), pos[0].y()
self.static.position = pos
if dset:
self.dynamic.position = pos
def itemChange(self, change, value):
if change == QGraphicsItem.ItemSelectedChange:
space = self.circle.space
space.remove(self.circle.body, self.circle)
self.circle.body = self.dynamic if value else self.static
space.add(self.circle.body, self.circle)
return super().itemChange(change, value)
def paint(self, painter, option, widget):
option.state &= ~QStyle.State_Selected
super().paint(painter, option, widget)
class Scene(QGraphicsScene):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.space = pymunk.Space()
self.space.damping = 0.02
self.body = pymunk.Body(body_type=pymunk.Body.KINEMATIC)
self.space.add(self.body)
self.timer = QTimer(self, timerType=Qt.PreciseTimer, timeout=self.step)
self.selectionChanged.connect(self.setConstraint)
def setConstraint(self):
selected = self.selectedItems()
if selected:
shape = selected[0].circle
if not shape.body.constraints:
self.space.remove(*self.space.constraints)
spring = pymunk.DampedSpring(
self.body, shape.body, (0, 0), (0, 0),
rest_length=0, stiffness=100, damping=10)
spring.collide_bodies = False
self.space.add(spring)
def step(self):
for i in range(10):
self.space.step(1 / 30)
self.selectedItems()[0].updatePos()
def mousePressEvent(self, event):
super().mousePressEvent(event)
if self.selectedItems():
self.body.position = event.scenePos().x(), event.scenePos().y()
self.timer.start(1000 / 30)
def mouseMoveEvent(self, event):
super().mouseMoveEvent(event)
if self.selectedItems():
self.body.position = event.scenePos().x(), event.scenePos().y()
def mouseReleaseEvent(self, event):
super().mouseReleaseEvent(event)
self.timer.stop()
def addCircle(self, x, y, radius):
item = Circle(radius)
item.setPos(x, y)
self.addItem(item)
self.space.add(item.circle.body, item.circle)
return item
if __name__ == '__main__':
app = QApplication(sys.argv)
scene = Scene(0, 0, 1000, 800)
for i in range(7, 13):
item = scene.addCircle(150 * (i - 6), 400, i * 5)
item.setBrush(Qt.GlobalColor(i))
view = QGraphicsView(scene, renderHints=QPainter.Antialiasing)
view.show()
sys.exit(app.exec_())
**สามารถปรับต่อไปนี้:
- ฤดูใบไม้ผลิ
stiffness
แล้ว damping
- ร่างกาย
mass
แล้ว moment
ขอ inertia
- อวกาศ
damping
Space.step
เวลาก้าว/กี่เรียนต่อ QTimer หมดเวลา
- QTimer
interval