如何在 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);
}
}
QGraphicsItem
有 collidingItems
方法,使用 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
我正在使用 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);
}
}
QGraphicsItem
有 collidingItems
方法,使用 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