如何在 PyQt5 中检测碰撞

How to Detect collisions in PyQt5

我正在使用 PyQt 制作一个简单的游戏,但我不知道如何检测敌人和子弹之间的碰撞,有一个 C++ 实现,但我不知道如何在 PyQt 中做到这一点。它应该在 Bullet.py 文件中完成。 这些是文件。

Window.py

from PyQt6.QtWidgets import QGraphicsScene,QApplication, QGraphicsView, QGraphicsItem
from PyQt6.QtCore import Qt, QTimer
import sys
from Player import Player
from Enemy import Enemy


class Window(QGraphicsView):
    def __init__(self):
        super().__init__()

    self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
    self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)

    self.setFixedSize(800, 600)
    self.create_scene()

    self.show()




def create_scene(self):
    self.scene = QGraphicsScene()

    #create an item to put in the scene
    player = Player()

    #make rect focusable
    player.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsFocusable)
    player.setFocus()


    #by default QGraphicsRectItem has 0 length and width
    player.setRect(0,0, 100,100)

    #add item to the scene
    self.scene.addItem(player)

    #set size of the scene
    self.scene.setSceneRect(0, 0, 800, 600)

    #set the player at the botoom
    player.setPos(self.width() / 2, self.height() - player.rect().height())
     
     # create our score
    score = Score()
    self.scene.addItem(score)

    self.setScene(self.scene)

    self.timer = QTimer()
    self.timer.timeout.connect(self.spawn)
    self.timer.start(2000)


def spawn(self):
    enemy = Enemy()
    self.scene.addItem(enemy)


App = QApplication(sys.argv)
window = Window() 
sys.exit(App.exec())

Player.py

from PyQt6.QtWidgets import QGraphicsRectItem
from PyQt6.QtGui import QKeyEvent
from PyQt6.QtCore import Qt
from Bullet import MyBullet




class Player(QGraphicsRectItem):
    def __init__(self):
       super().__init__()



def keyPressEvent(self, event: QKeyEvent):
    if (event.key() == Qt.Key.Key_Left):

        if self.pos().x() > 0:
            self.setPos(self.x() - 10, self.y())

    elif (event.key() == Qt.Key.Key_Right):
        if (self.pos().x() + 100 < 800):
            self.setPos(self.x() + 10, self.y())


    elif (event.key() == Qt.Key.Key_Space):
        mybullet = MyBullet()
        mybullet.setPos(self.x(), self.y())
        self.scene().addItem(mybullet)

Enemy.py

from PyQt6.QtWidgets import QGraphicsRectItem
from random import randint
from PyQt6.QtCore import QTimer


class Enemy(QGraphicsRectItem):
    def __init__(self):
        super().__init__()

    random_number = randint(10,1000) % 700
    self.setPos(random_number , 0)


    self.setRect(0,0,100,100)

    self.timer = QTimer()
    self.timer.timeout.connect(self.move)
    self.timer.start(50)




def move(self):
    #move enemy to down
    self.setPos(self.x(), self.y()+5)

    if self.pos().y() + self.rect().height() < 0:
        self.scene().removeItem(self)
        print("Bullet deleted")

Bullet.py

from PyQt6.QtWidgets import QGraphicsRectItem, QGraphicsItem
from PyQt6.QtCore import QTimer
from Enemy import Enemy




class MyBullet(QGraphicsRectItem):
    def __init__(self):
        super().__init__()
    score = Score() 

    self.setRect(0,0,10,50)

    self.timer = QTimer()
    self.timer.timeout.connect(self.move)
    self.timer.start(50)


def move(self):
    
    #This is the place for the collision 
    colliding = self.collidingItems()
    for item in colliding:
        if isinstance(item, Enemy):
            #increase the score
            score.increase()
            self.scene().removeItem(item)
            self.scene().removeItem(self)


    self.setPos(self.x(), self.y() - 10)

    if self.pos().y() + self.rect().height() < 0:
        self.scene().removeItem(self)
        print("Bullet deleted")
       

Score.py 来自 PyQt6.QtWidgets 导入 QGraphicsTextItem 从 PyQt6.QtCore 导入 Qt

from PyQt6.QtGui import QFont

class Score(QGraphicsTextItem):

    def __init__(self):
       super().__init__()

    self.score = 0

    #draw the text
    self.setPlainText("Score : " + str(self.score))
    self.setDefaultTextColor(Qt.GlobalColor.red)
    self.setFont(QFont("Sanserif", 18))



def increase(self):
    self.score += 1
    self.setPlainText(str(self.score))
    print(self.score)

这是 C++ 代码,我想要 Python.

的类似代码
QList<QGraphicsItem *> colliding_items = collidingItems();
for (int i = 0, n = colliding_items.size(); i < n; ++i) {
    if (typeid(*(colliding_items[i])) == typeid(Enemy)) {
        scene->removeItem(colliding_items[i]);
        scene->removeItem(this);

    }
}

QGraphicsItemcollidingItems 方法,使用 QGraphicsItem.boundingRect() 检测碰撞。它是为 QGraphicsRectItem 实现的。所以你只需要调用它并迭代项目。

class MyBullet(QGraphicsRectItem):
    
    def move(self):
        colliding = self.collidingItems()
        for item in colliding:
            if isinstance(item, Enemy):
                self.scene().removeItem(item)
                self.scene().removeItem(self)
                return