0

I'm trying to create a bird's-eye-view game (e.g. hotline miami) in pygame. I've gotten stuck at the collision detection. I'm trying to to see if the player hits a block on the left, right, in front or behind . I've gotten only to doing the 'in front' collision but that doesn't work; the player will hit the block 'head first', stop, but is then able to move through the block if he spams the arrow key. I know what the problem is (in the if else statement in the collision detection) but I can't for the life of me find the solution. Everything I tried doesn't seem to work. Help! Any help would be greatly appreciated, thanks in advance! (btw this is my first time on stack overflow, so sorry if I'm not asking the question well) (I removed some of the unnecessary code like the pygame.init() and variables)

def drawBlock(block_width,block_height,x,y):
    pygame.draw.rect(gameDisplay, red, [x,y,block_width,block_height])

def gameLoop(x,y):

    while not gameExit:


        level =  ["W","W","W","W","W","W","W","W","W","W","W","W",
                  "N","N","N","N","N","N","N","N","N","N","N","N","L",
                  "N","N","N","N","N","N","N","N","N","N","N","N","L",
                  "N","N","N","N","P","N","N","N","N","N","N","N","L",                                       
                  "N","N","N","N","N","N","N","N","N","N","N","N","L",                                     
                  "N","N","N","N","N","N","N","N","N","N","N","N","L",
                  "N","N","N","N","N","N","N","N","N","N","N","N","L",
                  "N","N","N","N","N","N","N","N","N","N","N","N","L",
                  "N","N","N","N","N","N","N","N","N","P","N","N","L",
                  "N","N","N","N","P","N","N","N","N","N","N","N","L",
                  "N","N","N","N","N","N","N","N","N","N","N","N","L","S"]    
#EVENT HANDLING

        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if canMoveUp:
                    if event.key == pygame.K_UP:
                        y_change = -player_movement

                if canMoveDown:
                    if event.key == pygame.K_DOWN:
                        y_change = player_movement


                if event.key == pygame.K_LEFT:
                    x_change = -player_movement

                if event.key == pygame.K_RIGHT:
                    x_change = player_movement

            if event.type == pygame.KEYUP:
                if event.key == pygame.K_UP or event.key == pygame.K_DOWN: 
                    y_change = 0
                if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                    x_change = 0

        pX += x_change
        pY += y_change

        gameDisplay.fill(black)


#CALCULATING THE SIZE OF THE BLOCKS SO THEY FIT W/ A VARIETY OF RESOLUTIONS


        if calculateBlockX:

            for element in level:
                if element == "W":
                    W_count += 1
                if element == "S":
                    block_width = (display_width/W_count) 
                    calculateBlockX = False

        if calculateBlockY:

            for element in level:
                if element == "L":
                    L_count += 1
                if element == "S":
                    block_height = (display_height/L_count)
                    calculateBlockY = False


#COUNTING HOW MANY BLOCKS THERE ARE IN THE LEVEL ARRAY (P)

        if P_countFunction:
            for element in level:
                if element == "P":
                    P_count += 1
                if element == "S":
                    print(P_count)
                    P_countFunction = False


#ALL THE X AND Ys OF ALL THE BLOCKS IN THE LEVEL, AND ACTUALLY DRAWING THEM

        blockXY = []

        for element in level:
            if element == "N":
                 x += block_width
            if element == "L":                                              
                 y += block_height
                 x = 0
            if element == "P": 
                drawBlock(block_width,block_height,x,y)                
                blockXY.append(x)
                blockXY.append(y)
                if appendBlockXY:
                    if len(collisionArray) > P_count:
                        del(collisionArray[P_count])
                        print(collisionArray)
                        appendBlockXY = False
                    collisionArray.append(blockXY)
                blockXY = []
                x += block_width
            if element == "S":
                y = 0

#COLLISION DETECTION              

        for XnY in collisionArray:

                if pX >= XnY[0] and pX <= XnY[0] + block_width and pY + playerSize <= XnY[1] or pX + playerSize >= XnY[0] and pX <= XnY[0] + block_width:

                    if pY - block_height == XnY[1]:
                        canMoveUp = False
                        y_change = 0

                    if pY - block_height != XnY[1]:
                        canMoveUp = True
                else:
                    if pY - block_height >= XnY[1]: 
                        canMoveUp = True



        #gameDisplay.blit(img,[pX,pY])

        pygame.draw.rect(gameDisplay, green, [pX,pY,playerSize,playerSize])

        clock.tick(60)

        pygame.display.update()


    pygame.quit()
    quit()

gameLoop(x,y)        

pygame.display.update()
TMJ
  • 21
  • 5
  • add 4 spaces to all lines of code - SO use this spaces to recognize code and highlight it. – furas Dec 27 '15 at 18:46
  • Hello and welcome to stackoverflow. Please read how to create a [minimal example](http://stackoverflow.com/help/mcve) that we can work with. Surely not all your code is related to the error/problem. Trust me, nobody will read your question if you just paste everything. – timgeb Dec 27 '15 at 18:46
  • Oh right, I was just thinking people might need to see the whole code, but I'll edit out the unnecessary stuff. – TMJ Dec 27 '15 at 18:50
  • Thanks btw for fixing the code block! – TMJ Dec 27 '15 at 18:50
  • btw: pygame has `pygame.Rect` class and use it to collision detection - `pygame.Rect.colliderect`, etc. And `Rect` has field `right` - it is `x + width` - so you don't have to do `XnY[0] + block_width` or `pY + playerSize` – furas Dec 27 '15 at 18:58
  • http://stackoverflow.com/questions/20180594/pygame-collision-by-sides-of-sprite – furas Dec 27 '15 at 19:00
  • Hmmm i looked at the link but it doesn't seem to solve the problem... It strikes me that pygame doesn't have any functions to detect this, it seems like a fairly common thing to need to to do. Perhaps there's an easy way to do it but because I have multiple blocks in the level they 'interfere' with each other when it comes down to the collision detection. – TMJ Dec 27 '15 at 20:03

1 Answers1

0

Your collision detection is written in a way that allows the last iteration to override all earlier checks. Instead of that, have canMoveUp set to True before the loop, and the loop should only set it to False or leave it alone.

HalfKiloByte
  • 116
  • 1
  • 3
  • Ohhhh of course I see now what you are saying... it finally works!!! Thank you so much you have no idea how much this helped me I've been stuck on this problem for days thanks again! – TMJ Dec 31 '15 at 14:08