Python Forum
Problem with collision detection... - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: Game Development (https://python-forum.io/forum-11.html)
+--- Thread: Problem with collision detection... (/thread-22414.html)



Problem with collision detection... - michael1789 - Nov-12-2019

Hello,

This is a piece of my current project. It is in my "class Player()". It's pretty standard, but not working. The "walls" group is defined globally at the top, and when tested has sprites in it, yet my player sprite just moves right through walls and I don't get any errors.



    def move(self, dx=0, dy=0):
        
        if not self.collide_with_walls(dx, dy):
            self.rect.x += dx * tile_size
            self.rect.y += dy * tile_size
        
    
    def collide_with_walls(self, dx=0, dy=0):
        
        for wall in walls:
            if wall.rect.x==self.rect.x + dx and wall.rect.y == self.rect.y + dy:
                
                return True
        return False



RE: Problem with collision detection... - ThomasL - Nov-12-2019

Your condition
if wall.rect.x==self.rect.x + dx and wall.rect.y == self.rect.y + dy:
seems never to be True.
Are you sure to test for equality? Maybe you need to test for being within a range?
Without more code it´s difficult to help, it´s just guessing.


RE: Problem with collision detection... - michael1789 - Nov-12-2019

Here is the whole thing. It runs and makes the map, puts my player and he can move around fine... he just ignores the walls entirely.

How do I "test for equality"? I've used "print" to look at what I know how to.

import pygame
import random
import time

pygame.init()

blue = (5, 5, 200)
green = (4, 80, 4)
red = (250, 0, 0)
grey = (30, 30, 30)
black = (0, 0, 0)
brown = (100, 100, 5)
width = 600
height = 600
tile_size = 25


wallimage = pygame.image.load("C:/Users/owner/Desktop/python3/dungeongraphics/wall1.png")
heroimage = pygame.image.load("C:/Users/owner/Desktop/python3/dungeongraphics/hero_1.png")
diggers = pygame.sprite.Group()
players = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
base_tiles = pygame.sprite.Group()
floor_tiles = pygame.sprite.Group()        
walls = pygame.sprite.Group()


class Player(pygame.sprite.Sprite):
    def __init__(self, game, x, y):
        
    
        
        pygame.sprite.Sprite.__init__(self)
        self.game = game
        self.image = pygame.transform.scale(heroimage, (tile_size, tile_size)) 
        
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

    def move(self, dx=0, dy=0):
        
        if not self.collide_with_walls(dx, dy):
            self.rect.x += dx * tile_size
            self.rect.y += dy * tile_size
        
    def collide_with_walls(self, dx=0, dy=0):
        print(walls)
        for wall in walls:
            if wall.rect.x==self.rect.x + dx and wall.rect.y == self.rect.y + dy:
                
                return True
        return False
    
   
    
    def update(self):
        
        self.rect.x = self.x * TILESIZE
        self.rect.y = self.y * TILESIZE



class Floor(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.game = game
        self.image = pygame.Surface((tile_size, tile_size))
        self.image.fill(brown)
        self.rect = self.image.get_rect()   
        self.rect.x = x
        self.rect.y = y
        
        
        
        

class Base(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.game = game
        self.colour = grey
        self.image = pygame.draw.rect(game.window, (self.colour), (x, y, tile_size, tile_size), 0)
        self.rect = pygame.Rect(x, y, tile_size, tile_size)
        self.x = x
        self.y = y
        pygame.display.flip()
        
class Wall(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.colour = red
        
        self.game = game
        
        self.image = pygame.transform.scale(wallimage, (tile_size, tile_size)) 
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        
        pygame.display.flip()


class Digger(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
     
    
        
        self.image = pygame.Surface((tile_size, tile_size))
        self.image.fill(red)
        self.rect = self.image.get_rect()   #pygame.Rect(self.rectx, self.recty, tile_size, tile_size)
        self.rect.x = x
        self.rect.y = y
        
def Make_map():
    
    for x in range(0, width, tile_size):
        for y in range(0, height, tile_size):
            
            base = Base(x, y)
            base_tiles.add(base)
     
    digger = Digger((width / 2), (height / 2))
    
    diggers.add(digger)
    all_sprites.add(digger)
    
    for i in range(70): 
        
        (dx, dy) = random.choice([(0, tile_size), (0, -tile_size), (-tile_size, 0), (tile_size, 0)])
   
        digger.rect.x = digger.rect.x + dx
        digger.rect.y = digger.rect.y + dy
        pygame.sprite.spritecollide(digger, floor_tiles, True)
        floor = Floor(digger.rect.x, digger.rect.y)
        all_sprites.add(floor)
        floor_tiles.add(floor)
        
        pygame.sprite.spritecollide(digger, base_tiles, True)
        
        
        all_sprites.draw(game.window)   
        pygame.display.update()    
        time.sleep(.01)    
        
    for floor in floor_tiles:
         
        for delta_x, delta_y in ((tile_size, 0), (0, tile_size), (-tile_size, 0), (0, -tile_size), (-tile_size, tile_size), (tile_size, -tile_size), (-tile_size, -tile_size), (tile_size, tile_size)):
      
            floor.rect.x = floor.rect.x + delta_x
            floor.rect.y = floor.rect.y + delta_y
            hits = pygame.sprite.spritecollide(floor, base_tiles, False)
            
            floor.rect.x = floor.rect.x - delta_x
            floor.rect.y = floor.rect.y - delta_y
            
            for hit in hits:
               
                wall = Wall(hit.rect.x, hit.rect.y)       
                all_sprites.add(wall)
                walls.add(wall)
            time.sleep(.01)        
    floor = Floor((width / 2), (height / 2))
    all_sprites.add(floor)
    floor_tiles.add(floor)        
                
class Game():
    def __init__(self):
        pygame.init()
        self.window = pygame.display.set_mode((width, height))
        pygame.display.set_caption("Dungeon")
        self.clock = pygame.time.Clock()
        pygame.key.set_repeat(500, 100)
        
    def New(self):
        
        Make_map()
       
        self.player = Player(game, (width / 2), (height / 2))
        all_sprites.add(self.player)
        players.add(self.player)
        self.run()
        all_sprites.draw(window)
        pygame.display.flip()
        
        
        
        

        
        
    def run(self):
        playing = True
        while playing:
               
            self.update()
            
            self.draw()
            self.events()
            

    def quit(self):
        pygame.quit()
        sys.exit()

    def update(self):
        print("update")
        all_sprites.draw(game.window)
        
        
           

    def draw(self):
        print("draw")
        self.window.fill(black)
        all_sprites.draw(self.window)
        pygame.display.flip()
  

    def events(self):
        # catch all events here
        
        check = True
        while check:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.quit()
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        self.quit()
                    if event.key == pygame.K_LEFT:
                        self.player.move(dx=-1)
                        check = False
                    if event.key == pygame.K_RIGHT:
                        self.player.move(dx=1)
                        check = False
                    if event.key == pygame.K_UP:
                        self.player.move(dy=-1)
                        check = False
                    if event.key == pygame.K_DOWN:
                        self.player.move(dy=1)
                        check = False





game = Game()
game.New()



RE: Problem with collision detection... - ThomasL - Nov-12-2019

For debugging print the values you are comparing and look at the values that are printed when player hits a wall.

    def collide_with_walls(self, dx=0, dy=0):
        for wall in walls:
            print(wall.rect.x, self.rect.x+dx, wall.rect.y, self.rect.y+dy)
            if wall.rect.x==self.rect.x + dx and wall.rect.y == self.rect.y + dy:
                return True
        return False



RE: Problem with collision detection... - michael1789 - Nov-12-2019

They are all wrong and changing at strange intervals. I clearly have my "* tile_size" in wrong spots.

Thank you!