Ik heb een lijst met opsommingstekens en een lijst met sprites gemaakt met behulp van de onderstaande klassen. Hoe kan ik detecteren of een kogel botst met een sprite en vervolgens die sprite en de kogel verwijderen?
#Define the sprite class
class Sprite:
def __init__(self,x,y, name):
self.x=x
self.y=y
self.image = pygame.image.load(name)
self.rect = self.image.get_rect()
def render(self):
window.blit(self.image, (self.x,self.y))
# Define the bullet class to create bullets
class Bullet:
def __init__(self,x,y):
self.x = x + 23
self.y = y
self.bullet = pygame.image.load("user_bullet.BMP")
self.rect = self.bullet.get_rect()
def render(self):
window.blit(self.bullet, (self.x, self.y))
Antwoord 1, autoriteit 100%
In PyGame kan basisbotsingsdetectie worden gedaan met pygame.Rect
objecten. Het object rect
biedt verschillende methoden voor het detecteren van botsingen tussen objecten. Merk op dat zelfs de botsing van een rechthoekig object met een cirkelvormig object zoals een peddel en een bal in het spel Pongruwweg kan worden gedetecteerd door een botsing tussen twee rechthoekige objecten, de peddel en de begrenzende rechthoek van de bal.
Enkele voorbeelden:
-
Test of een punt binnen een rechthoek ligt
repl.it/@Rabbid76/PyGame-collidepoint
import pygame pygame.init() window = pygame.display.set_mode((250, 250)) rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(100, 100) run = True while run: for event in pygame.event.get(): if event.type == pygame.QUIT: run = False point = pygame.mouse.get_pos() collide = rect.collidepoint(point) color = (255, 0, 0) if collide else (255, 255, 255) window.fill(0) pygame.draw.rect(window, color, rect) pygame.display.flip() pygame.quit() exit()
-
Test of twee rechthoeken elkaar overlappen
Zie ook Hoe u botsingen kunt detecteren tussen twee rechthoekige objecten of afbeeldingen in pygame
repl.it/@Rabbid76/PyGame-colliderect
import pygame pygame.init() window = pygame.display.set_mode((250, 250)) rect1 = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75) rect2 = pygame.Rect(0, 0, 75, 75) run = True while run: for event in pygame.event.get(): if event.type == pygame.QUIT: run = False rect2.center = pygame.mouse.get_pos() collide = rect1.colliderect(rect2) color = (255, 0, 0) if collide else (255, 255, 255) window.fill(0) pygame.draw.rect(window, color, rect1) pygame.draw.rect(window, (0, 255, 0), rect2, 6, 1) pygame.display.flip() pygame.quit() exit()
Verder pygame.Rect.collidelist
en pygame.Rect.collidelistall
kan worden gebruikt voor de botsingstest tussen een rechthoek en een lijst met rechthoeken. pygame.Rect.collidedict
en pygame.Rect.collidedictall
kan worden gebruikt voor de botsingstest tussen een rechthoek en een woordenboek van rechthoeken.
De botsing van pygame.sprite.Sprite
en pygame.sprite.Group
kunnen worden gedetecteerd door pygame.sprite.spritecollide()
, pygame.sprite.groupcollide()
of pygame.sprite.spritecollideany()
. Bij gebruik van deze methoden kan het algoritme voor botsingsdetectie worden gespecificeerd door het argument collided
:
Het botsende argument is een callback-functie die wordt gebruikt om te berekenen of twee sprites botsen.
Mogelijke collided
callables zijn collide_rect
, collide_rect_ratio
, collide_circle
, collide_circle_ratio
, collide_mask
Enkele voorbeelden:
-
repl.it/@Rabbid76/PyGame-spritecollide
import pygame pygame.init() window = pygame.display.set_mode((250, 250)) sprite1 = pygame.sprite.Sprite() sprite1.image = pygame.Surface((75, 75)) sprite1.image.fill((255, 0, 0)) sprite1.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75) sprite2 = pygame.sprite.Sprite() sprite2.image = pygame.Surface((75, 75)) sprite2.image.fill((0, 255, 0)) sprite2.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75) all_group = pygame.sprite.Group([sprite2, sprite1]) test_group = pygame.sprite.Group(sprite2) run = True while run: for event in pygame.event.get(): if event.type == pygame.QUIT: run = False sprite1.rect.center = pygame.mouse.get_pos() collide = pygame.sprite.spritecollide(sprite1, test_group, False) window.fill(0) all_group.draw(window) for s in collide: pygame.draw.rect(window, (255, 255, 255), s.rect, 5, 1) pygame.display.flip() pygame.quit() exit()
Voor een botsing met maskers zie Hoe kan ik een botsingsmasker?of Pygame-maskerbotsing
Zie ook Collision and Intersection
-
pygame.sprite.spritecollide()
/collide_circle
repl.it/@Rabbid76/PyGame-spritecollidecollidecircle
import pygame pygame.init() window = pygame.display.set_mode((250, 250)) sprite1 = pygame.sprite.Sprite() sprite1.image = pygame.Surface((80, 80), pygame.SRCALPHA) pygame.draw.circle(sprite1.image, (255, 0, 0), (40, 40), 40) sprite1.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(40, 40) sprite2 = pygame.sprite.Sprite() sprite2.image = pygame.Surface((80, 89), pygame.SRCALPHA) pygame.draw.circle(sprite2.image, (0, 255, 0), (40, 40), 40) sprite2.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(80, 80) all_group = pygame.sprite.Group([sprite2, sprite1]) test_group = pygame.sprite.Group(sprite2) run = True while run: for event in pygame.event.get(): if event.type == pygame.QUIT: run = False sprite1.rect.center = pygame.mouse.get_pos() collide = pygame.sprite.spritecollide(sprite1, test_group, False, pygame.sprite.collide_circle) window.fill(0) all_group.draw(window) for s in collide: pygame.draw.circle(window, (255, 255, 255), s.rect.center, s.rect.width // 2, 5) pygame.display.flip() pygame.quit() exit()
Wat betekent dit allemaal voor je code?
pygame.Surface.get_rect.get_rect()
retourneert een rechthoek met de grootte van het Surfaceobject, dat altijd begint bij (0, 0) aangezien een Surfaceobject geen positie heeft. De positie van de rechthoek kan worden gespecificeerd door een trefwoordargument. Het midden van de rechthoek kan bijvoorbeeld worden opgegeven met het trefwoordargument center
. Dit trefwoordargument wordt toegepast op de attributen van de pygame.Rect
voordat het wordt geretourneerd (zie pygame.Rect
voor een volledige lijst van de trefwoordargumenten).
Zie *Waarom geeft mijn botsingstest altijd ‘true’ en waarom is de positie van de rechthoek van de afbeelding altijd verkeerd (0, 0)?
Je hebt de kenmerken x
en y
van Sprite
en Bullet
helemaal niet nodig. Gebruik in plaats daarvan de positie van het kenmerk rect
:
#Define the sprite class
class Sprite:
def __init__(self, x, y, name):
self.image = pygame.image.load(name)
self.rect = self.image.get_rect(topleft = (x, y))
def render(self):
window.blit(self.image, self.rect)
# Define the bullet class to create bullets
class Bullet:
def __init__(self, x, y):
self.bullet = pygame.image.load("user_bullet.BMP")
self.rect = self.bullet.get_rect(topleft = (x + 23, y))
def render(self):
window.blit(self.bullet, self.rect)
Gebruik pygame.Rect.colliderect()
om botsingen te detecteren tussen instanties van Sprite
en Bullet
.
Zie Hoe botsingen tussen twee rechthoekige objecten of Afbeeldingen in Pygame :
my_sprite = Sprite(sx, sy, name)
my_bullet = Bullet(by, by)
while True:
# [...]
if my_sprite.rect.colliderect(my_bullet.rect):
printe("hit")
Antwoord 2, Autoriteit 46%
Vanaf wat ik begrijp van Pygame, hoeft u alleen maar te controleren of de twee rechthoeken elkaar overlappen met behulp van de colliderect
METHODE. Een manier om het te doen is om een methode in uw Bullet
Class te hebben die controleert op botsingen:
def is_collided_with(self, sprite):
return self.rect.colliderect(sprite.rect)
dan kunt u het noemen zoals:
sprite = Sprite(10, 10, 'my_sprite')
bullet = Bullet(20, 10)
if bullet.is_collided_with(sprite):
print('collision!')
bullet.kill()
sprite.kill()
Antwoord 3, Autoriteit 14%
Er is een heel eenvoudige methode voor wat u probeert te doen met behulp van ingebouwde methoden.
hier is een voorbeeld.
import pygame
import sys
class Sprite(pygame.sprite.Sprite):
def __init__(self, pos):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20, 20])
self.image.fill((255, 0, 0))
self.rect = self.image.get_rect()
self.rect.center = pos
def main():
pygame.init()
clock = pygame.time.Clock()
fps = 50
bg = [255, 255, 255]
size =[200, 200]
screen = pygame.display.set_mode(size)
player = Sprite([40, 50])
player.move = [pygame.K_LEFT, pygame.K_RIGHT, pygame.K_UP, pygame.K_DOWN]
player.vx = 5
player.vy = 5
wall = Sprite([100, 60])
wall_group = pygame.sprite.Group()
wall_group.add(wall)
player_group = pygame.sprite.Group()
player_group.add(player)
# I added loop for a better exit from the game
loop = 1
while loop:
for event in pygame.event.get():
if event.type == pygame.QUIT:
loop = 0
key = pygame.key.get_pressed()
for i in range(2):
if key[player.move[i]]:
player.rect.x += player.vx * [-1, 1][i]
for i in range(2):
if key[player.move[2:4][i]]:
player.rect.y += player.vy * [-1, 1][i]
screen.fill(bg)
# first parameter takes a single sprite
# second parameter takes sprite groups
# third parameter is a do kill command if true
# all group objects colliding with the first parameter object will be
# destroyed. The first parameter could be bullets and the second one
# targets although the bullet is not destroyed but can be done with
# simple trick bellow
hit = pygame.sprite.spritecollide(player, wall_group, True)
if hit:
# if collision is detected call a function in your case destroy
# bullet
player.image.fill((255, 255, 255))
player_group.draw(screen)
wall_group.draw(screen)
pygame.display.update()
clock.tick(fps)
pygame.quit()
# sys.exit
if __name__ == '__main__':
main()
Antwoord 4
Maak een groep voor de opsommingstekens en voeg de opsommingstekens toe aan de groep.
Wat ik zou doen is dit:
In de klas voor de speler:
def collideWithBullet(self):
if pygame.sprite.spritecollideany(self, 'groupName'):
print("CollideWithBullet!!")
return True
En ergens in de hoofdlus:
def run(self):
if self.player.collideWithBullet():
print("Game Over")
Hopelijk werkt dat voor jou!!!