Python Forum
[PyGame] How to define spritecollisions?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] How to define spritecollisions?
#1
So I have this test environment that I use whenever I'm trying to learn new stuff, lately it's been going on into alot of pygame. I'm currently trying to figure out how to use/define spritecollisions and I'm just really confused and stuck, therefore coming here to ask for help as a newb.

Now, I don't want to just dump some code and ask for help just like that, i want to try to explain what I've tried so far and what I'm trying to do specifically.

So what I want to do is create a function that detects collisions between the player (controlled by me) and the mob (enemy non moving object) and i want my pygame to automatically shut of if it detects a collision between the two. So, initially, since it's a static object I just could define an if statement, say something like "if player.x == mob.x pygame.quit(). However, that's not the solution that I want, because I've done that in previous projects and it's just really bad code, especially if i figure out later i want to move it somewhere...

So what have I tried? well, the two first functions in the codesheet below, are my two attemps at creating this detection. I'm not sure if i'm thinking wrong about this but I figured i couldn't define those functions inside the player or mob class because then it wont detect the other class definitions because they're separated. Therefore I went for the solution below, and defined the functions outside a class.

According to the examples i have searched up, there are different ways to do this, but those two below seemed to be accurate for my type of game so hence I went for those funcs as definitions, but they are clearly wrong. I'm just not sure if calling the player and mob in the func without further specification is the wrong way to approach this?

I could explain further, but I'm creating so much text from just this one problem Huh that I want to save everyones time...



import pygame
import tkinter as tk
from tkinter import messagebox
import os

'''Color definitions'''
BLACK = (0,0,0)
BLUE = (10,10,128)
GREEN = (5,200,0)
RED = (255,100,100)

#Screen width

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600


def checkCollision(self,Player,mobs):
    col = pygame.sprite.collide_rect(Player, mobs)
    if col == True:
        pygame.quit()



def col(self):
    super.__init__()
    collision = pygame.sprite.spritecollide_mask(Player, mobs)
    if collision:
        pygame.quit()

#player class/main class
class Player(pygame.sprite.Sprite):

    def __init__(self,x,y):
        super().__init__()
        #surface decides how big my player is
        self.image = pygame.Surface([50,45])
        #fill decides the color of my player
        self.image.fill(BLUE)
        #Player definitions, went for rect object and turning on x and y functions
        self.rect = self.image.get_rect()
        self.rect.y = y
        self.rect.x = x
        #self.player = Player
        #self.mobs = mobs

        self.change_x = 0
        self.change_y = 0
        self.walls = None
    ''' Doesn't work
    def checkCollision(self,Player,Mobs):
        col = pygame.sprite.collide_rect(Player, Mobs)
        if col == True:
            pygame.quit()
            '''

    def changespeed(self,x,y):
        self.change_x += x
        self.change_y += y

    def update(self):
        self.rect.x += self.change_x

        #bad code
        #if self.rect.x >= 270 and self.rect.y > 160 < 165 and self.rect.x <275:
            #pygame.quit()

        #collision = pygame.sprite.spritecollideany(Player, mobs)
        #if collision:
            #pygame.quit()
        #hits = pygame.sprite.spritecollide(self.player, self.mobs, False)


        block_hit_list = pygame.sprite.spritecollide(self,self.walls, False)
        for block in block_hit_list:
            if self.change_x > 0:
                self.rect.right = block.rect.left
            else:
                self.rect.left = block.rect.right

        self.rect.y += self.change_y

        block_hit_list = pygame.sprite.spritecollide(self,self.walls,False)
        for block in block_hit_list:

            if self.change_y > 0:
                self.rect.bottom = block.rect.top
            else:
                self.rect.top = block.rect.bottom


#wall class
class Wall(pygame.sprite.Sprite):
    def __init__(self,x,y,width,height):
        super().__init__()

        self.image = pygame.Surface([width, height])
        self.image.fill(GREEN)

        self.rect = self.image.get_rect()
        self.rect.y = y
        self.rect.x = x


class Mob(pygame.sprite.Sprite):

    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((30, 40))
        self.image.fill(RED)
        self.rect = self.image.get_rect()
        self.rect.x = 270
        self.rect.y = 150
        self.speedy = 0
        self.mob = mobs

    def update(self):
        self.rect.y += self.speedy
        if self.rect.top > SCREEN_HEIGHT:
            self.rect.x = 150
            self.rect.y = 150
            self.speedy = 0





#Definitions
pygame.init()
screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])
pygame.display.set_caption('Sandbox')
all_sprite_list = pygame.sprite.Group()


#walls
wall_list = pygame.sprite.Group()

'''Very important to remember this...
first coord = x, second Y third, length fourth, height'''
#Left wall
wall = Wall(0,0,10,600)
wall_list.add(wall)
all_sprite_list.add(wall)
#top wall
wall = Wall(10,0,790,10)
wall_list.add(wall)
all_sprite_list.add(wall)

#Right wall
wall = Wall (790,0,10,600)
wall_list.add(wall)
all_sprite_list.add(wall)

#Bottom wall
wall = Wall (0,590,1000,300)
wall_list.add(wall)
all_sprite_list.add(wall)

#Create the player
player = Player(50,50)
player.walls = wall_list
all_sprite_list.add(player)

clock = pygame.time.Clock()

mobs = pygame.sprite.Group()
wall_list.add(mobs)
all_sprite_list.add(mobs)



for i in range(1):
    m = Mob()
    all_sprite_list.add(m)
    mobs.add(m)



done = False

#Keybindings + run statement
while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_a:
                player.changespeed(-3, 0)
            elif event.key == pygame.K_d:
                player.changespeed(3, 0)
            elif event.key == pygame.K_w:
                player.changespeed(0, -3)
            elif event.key == pygame.K_s:
                player.changespeed(0, 3)

        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_a:
                player.changespeed(3, 0)
            elif event.key == pygame.K_d:
                player.changespeed(-3, 0)
            elif event.key == pygame.K_w:
                player.changespeed(0, 3)
            elif event.key == pygame.K_s:
                player.changespeed(0, -3)



    '''these updates needs to be indented like this in order to actually work'''

    all_sprite_list.update()

    screen.fill(BLACK)

    all_sprite_list.draw(screen)

    pygame.display.flip()

    clock.tick(60)


pygame.quit()
Reply
#2
You could have something in the player.update() like this

hit = pygame.sprite.spritecollideany(self, mobs)
if hit:
    pygame.quit()
Reply
#3
Yeah that solution works nice + I learned something for next time. Thanks! :D
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020