Difference between revisions of "Collisions"
(Created page with "==Rectangular Collision== The sprite class has built in methods to handle collision detection, one of the methods is collide_rect. For this example we are going to create 2 sp...") |
(→Rectangular Collision) |
||
Line 8: | Line 8: | ||
def update(self, new_position): | def update(self, new_position): | ||
self.rect.topleft = new_position | self.rect.topleft = new_position | ||
+ | |||
+ | def draw(self, screen): | ||
+ | screen.blit(self.image, self.rect) | ||
def __init__(self, initial_position): | def __init__(self, initial_position): | ||
Line 28: | Line 31: | ||
def update(self, new_position): | def update(self, new_position): | ||
self.rect.topleft = new_position | self.rect.topleft = new_position | ||
+ | |||
+ | def draw(self, screen): | ||
+ | screen.blit(self.image, self.rect) | ||
def __init__(self, initial_position): | def __init__(self, initial_position): | ||
Line 51: | Line 57: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | Now in the game loop we can make the player move (you can't have collisions if you can't move): | + | Now in the game loop we can make the player move (you can't have collisions if you can't move). h.update(h, pos) will change the position of the hero object: |
+ | |||
+ | <syntaxhighlight lang=python> | ||
+ | for events in pygame.event.get(): #get all pygame events | ||
+ | if events.type == pygame.KEYDOWN: | ||
+ | if events.key == pygame.K_LEFT: | ||
+ | pos[0]=pos[0]-10 # pos[0] should be first item in the tuple | ||
+ | elif events.key == pygame.K_RIGHT: | ||
+ | pos[0]=pos[0]+10 # pos[0] should be first item in the tuple | ||
+ | elif events.key == pygame.K_UP: | ||
+ | pos[1]=pos[1]-10 # pos[1] should be second item in the tuple | ||
+ | elif events.key == pygame.K_DOWN: | ||
+ | pos[1]=pos[1]+10 # pos[1] should be second item in the tuple | ||
+ | h.update(h, pos) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Now we have moved you can check if this position collides with another sprite: | ||
<syntaxhighlight lang=python> | <syntaxhighlight lang=python> | ||
Line 64: | Line 86: | ||
elif events.key == pygame.K_DOWN: | elif events.key == pygame.K_DOWN: | ||
pos[1]=pos[1]+10 # pos[1] should be second item in the tuple | pos[1]=pos[1]+10 # pos[1] should be second item in the tuple | ||
+ | h.update(h, pos) | ||
+ | |||
+ | if pygame.sprite.collide_rect(b, h): | ||
+ | print("collision") | ||
+ | else: | ||
+ | print("no collision") | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Remember for this to work we also need to blit each object to the screen and we also need to update the display: | ||
+ | |||
+ | <syntaxhighlight lang=python> | ||
+ | h.draw(self, SCREEN) | ||
+ | e.draw(self, Screen) | ||
+ | pygame.display.update() | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==Per Pixel Collision== | ||
+ | You can use masks in pygame, this will create an image of a single colour which essentially fills the non transparent parts of the sprite. Follow the instructions above to create a rectangular based collision example. in the init method for each sprite class add the following line: | ||
− | + | <syntaxhighlight lang=python> | |
+ | self.mask = pygame.mask.from_surface(self.image) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Now change the if statement which checks for a collision to use this instead: | ||
+ | |||
+ | <syntaxhighlight lang=python> | ||
+ | if pygame.sprite.spritecollide(b1, b2, False, pygame.sprite.collide_mask): | ||
+ | print ("sprites have collided!") | ||
+ | else: | ||
+ | print("no collision") | ||
</syntaxhighlight> | </syntaxhighlight> |
Revision as of 10:17, 14 March 2018
Rectangular Collision
The sprite class has built in methods to handle collision detection, one of the methods is collide_rect. For this example we are going to create 2 sprite based classes first, one for the enemy and one for the player:
class HeroSprite(pygame.sprite.Sprite):
image = None
def update(self, new_position):
self.rect.topleft = new_position
def draw(self, screen):
screen.blit(self.image, self.rect)
def __init__(self, initial_position):
pygame.sprite.Sprite.__init__(self) # run the init for the base class
if HeroSprite.image is None:
HeroSprite.image = pygame.image.load("hero.png") # load image for sprite
self.image = HeroSprite.image # set image for the sprite
self.rect = self.image.get_rect() # set rectangle for sprite
self.rect.topleft = initial_position # set position to value passed into method
self.going_down = True # Start going downwards
self.next_update_time = 0 # update() hasn’t been called yet.
The code above will load the image for the sprite, set its position and its bounds (rect). We can create another for the enemy:
class EnemySprite(pygame.sprite.Sprite):
image = None
def update(self, new_position):
self.rect.topleft = new_position
def draw(self, screen):
screen.blit(self.image, self.rect)
def __init__(self, initial_position):
pygame.sprite.Sprite.__init__(self) # run the init for the base class
if EnemySprite.image is None:
HEnemySprite.image = pygame.image.load("Enemy.png") # load image for sprite
self.image = EnemySprite.image # set image for the sprite
self.rect = self.image.get_rect() # set rectangle for sprite
self.rect.topleft = initial_position # set position to value passed into method
self.going_down = True # Start going downwards
self.next_update_time = 0 # update() hasn’t been called yet.
Before the game loop you can now create an instance of each class, and run the init method for each:
e = EnemySprite
e.__init__(e, [100,100])
pos = [0,0]
h = HeroSprite
h.__init__(h, pos)
Now in the game loop we can make the player move (you can't have collisions if you can't move). h.update(h, pos) will change the position of the hero object:
for events in pygame.event.get(): #get all pygame events
if events.type == pygame.KEYDOWN:
if events.key == pygame.K_LEFT:
pos[0]=pos[0]-10 # pos[0] should be first item in the tuple
elif events.key == pygame.K_RIGHT:
pos[0]=pos[0]+10 # pos[0] should be first item in the tuple
elif events.key == pygame.K_UP:
pos[1]=pos[1]-10 # pos[1] should be second item in the tuple
elif events.key == pygame.K_DOWN:
pos[1]=pos[1]+10 # pos[1] should be second item in the tuple
h.update(h, pos)
Now we have moved you can check if this position collides with another sprite:
for events in pygame.event.get(): #get all pygame events
if events.type == pygame.KEYDOWN:
if events.key == pygame.K_LEFT:
pos[0]=pos[0]-10 # pos[0] should be first item in the tuple
elif events.key == pygame.K_RIGHT:
pos[0]=pos[0]+10 # pos[0] should be first item in the tuple
elif events.key == pygame.K_UP:
pos[1]=pos[1]-10 # pos[1] should be second item in the tuple
elif events.key == pygame.K_DOWN:
pos[1]=pos[1]+10 # pos[1] should be second item in the tuple
h.update(h, pos)
if pygame.sprite.collide_rect(b, h):
print("collision")
else:
print("no collision")
Remember for this to work we also need to blit each object to the screen and we also need to update the display:
h.draw(self, SCREEN)
e.draw(self, Screen)
pygame.display.update()
Per Pixel Collision
You can use masks in pygame, this will create an image of a single colour which essentially fills the non transparent parts of the sprite. Follow the instructions above to create a rectangular based collision example. in the init method for each sprite class add the following line:
self.mask = pygame.mask.from_surface(self.image)
Now change the if statement which checks for a collision to use this instead:
if pygame.sprite.spritecollide(b1, b2, False, pygame.sprite.collide_mask):
print ("sprites have collided!")
else:
print("no collision")