Question

I have been trying to add collision detection for a while now and just can't seem to do it..

To draw my map I'm just using x,y coords:

from setup import *

treeload = "Images/tree.jpg"
tree = pygame.image.load(treeload).convert_alpha()

class drawtree:

     def __init__(self, x, width, step1, y, height, step2):

        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.step1 = step1
        self.step2 = step2

    def draw(self):

        for x in range(self.x, self.x+self.width, self.step1):
            for y in range(self.y, self.y+self.height, self.step2):
                window.blit(tree, (x,y))

t1 = drawtree(100, 100, 20, 0, 90, 30)
t2 = drawtree(400, 300, 20, 0, 90, 30)
t3 = drawtree(100, 270, 20, 450, 150, 30)
t4 = drawtree(400, 300, 20, 450, 150, 30)

trees = [t1, t2, t3 ,t4]

Using this method I came up with this detection:

from setup import *
from drawtree import *
from player import *

def wall_detect(x1, y1, w1, h1, x2, y2, w2, h2):
    if (x2+w2>=x1>=x2 and y2+h2>=y1>=y2):
        return True
    elif (x2+w2>=x1+w1>=x2 and y2+h2>=y1>=y2):
        return True
    elif (x2+w2>=x1>=x2 and y2+h2>=y1+h1>=y2):
        return True
    elif (x2+w2>=x1+w1>=x2 and y2+h2>=y1+h1>=y2):
        return True
    else:
        return False

I have been trying to use for loops to loop through trees to detect if player (a rectangle) crosses into the trees but I cant think of anything.

I've tried

    for i in trees:
        collision = wall_detect(player.x, player.y, player.width, player.height, i.x, i.y, i.width, i.height)
    player.update(collision)

player.update(collision) changes the rectangle to red if collision = true and leaves it black if false.

I've tried using for and if e.g:

for i in trees:
        if wall_detect(player.x, player.y, player.width, player.height, i.x, i.y, i.width, i.height) == wall_detect(player.x, player.y, player.width, player.height, t1.x, t1.y, t1.width, t1.height):
            collision = wall_detect(player.x, player.y, player.width, player.height, t1.x, t1.y, t1.width, t1.height)
           player.update(collision)

        if wall_detect(player.x, player.y, player.width, player.height, i.x, i.y, i.width, i.height) == wall_detect(player.x, player.y, player.width, player.height, t2.x, t2.y, t2.width, t2.height):
            collision = wall_detect(player.x, player.y, player.width, player.height, t2.x, t2.y, t2.width, t2.height)
            player.update(collision)

etc.. but that doesn't work, it only for with 1 if statement and the rest commented out.

Was it helpful?

Solution

One problem is with the nature of this loop:

for i in trees:
    collision = wall_detect(player.x, player.y, player.width, player.height, i.x, i.y, i.width, i.height)
player.update(collision)

Suppose the player collides with the first tree in trees. Then collision will be True, but the for loop continues. So collision will only end up being True if the player is colliding with the last tree in your list. There are multiple ways to fix this.

# Change the assignment to check if it is already true
collision = False
for i in trees:
    collision = collision or wall_detect(...

or

# Exit the loop if it is true
for i in trees:
    collision = wall_detect(...)
    if collision:
        break

or

# Turn it into a function that returns when it is true
def walls_detect(player, trees):
    for tree in trees:
        if wall_detect(...):
            return True
    return False

...
# Call it like this
player.update(walls_detect(player, trees))

Your logic for when collisions occur looks right to me, though it can also be simplified quite a bit:

def wall_detect(x1, y1, w1, h1, x2, y2, w2, h2):
    return (x2+w2>=x1>=x2 or x2+w2>=x1+w1>=x2) and (y2+h2>=y1>=y2 or y2+h2>=y1+h1>=y2)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top