Iam making a simple game using PyQt, but i don’t know how i can detect the collisions between enemy and bullets, there is a C++ implementation, but i dont know how i can do that in PyQt. and it should be done in Bullet.py file. these are the files.
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 from PyQt6.QtWidgets import QGraphicsTextItem from PyQt6.QtCore import 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)
This is the C++ code, i want similiar of that for 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); } }
Advertisement
Answer
QGraphicsItem
has collidingItems
method that use QGraphicsItem.boundingRect()
to detect collisions. It is implemented for QGraphicsRectItem
. So you only need to call it and iterate over items.
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