หลีกเลี่ยงคอลลิชันของ QGraphicsItem นรูปร่างได้ลอกเลียนย้ายโดยตัวชี้ของเมาส์มาอยู่เห

0

คำถาม

น่าสนใจอย่างถูกเลี้ยง มาที่นี่ เรื่องกันคอลลิชันขอต่อให้ของ QGraphicsEllipseItems ใน QGraphicsScene. คำถามที่จำกัดวงแคบจากขอบเขตไป 2 colliding รายการแต่งที่ใหญ่กว่าเป้าหมายยังคงยังคง, แล้วเรื่องให้มีจำนวนของคอลลิชัน?

นี่คือที่ต้องการพฤติกรรม:

  • เมื่อหนึ่งรายการอดคือลากเหนือรายการพวกเขาไม่ควรซ้อนทับแทนมัเตรเลียไหนจะเอเชียอีกหลายรอบๆพวกนั้นรายการใกล้ที่สุดเท่าที่เป็นไปได้เพื่อนตัวชี้ของเมาส์มาอยู่เห.
  • มันไม่ควรจะ"เคลื่อนย้า"ถ้ามันจะถูกบล็อคโดยรายการอื่น.
  • มันควรจะเป็นเรื่องเรียบเนียนและคาดเดาได้มีการเคลื่อนไหว

ที่นี่กลายเป็นสิ่งซับซ้อนที่จะหาที่ที่ดีที่สุด"ปลอดภัย"ตำแหน่งสำหรับวงเวทย์ในขณะที่มันเคลื่อนฉันอยากจะของขวัญอีกทางไว้ก่อนนี่ใช้เป็นฟิสิกส์ simulator กับเขา.

collision pymunk pyqt5 python
2021-11-23 02:01:24
1

คำตอบที่ดีที่สุด

3

ดูจากพฤติกรรมนอธิบายว่าอยู่เหนือมันเป็นคดีผู้สมัครสำหรับ 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
2021-12-01 01:57:12

นี่มันเยี่ยมมาก!!
drivereye

ในภาษาอื่นๆ

หน้านี้อยู่ในภาษาอื่นๆ

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................