4

I am trying to get collision to work but when the two rectangles collide they go a little bit into each other but I want the second rectangle to act like a wall. Does someone have any idea how I could fix this? Or is there maybe a better way to add collision to my game? This is what I have right now.

import pygame

pygame.init()
screen = pygame.display.set_mode((1000, 800))
pygame.display.set_caption("Squarey")
done = False
is_red = True
x = 30
y = 30
x2 = 100
y2 = 30
clock = pygame.time.Clock()
WHITE = (255,255,255)
RED = (255,0,0)

charImg = pygame.image.load('character.png')



rect1 = pygame.Rect(30, 30, 60, 60)

rect2 = pygame.Rect(100, 100, 60, 60)

x_change = 0
y_change = 0

while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True


#movement
      #left
    if event.type == pygame.KEYDOWN:
      if event.key == pygame.K_LEFT:
        x_change = -5
        y_change = 0

        #right
      elif event.key == pygame.K_RIGHT:
        x_change = 5
        y_change = 0
      #key release left and right
    if event.type == pygame.KEYUP:
      if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
        x_change = 0
        y_change = 0


      #up    
    if event.type == pygame.KEYDOWN:
      if event.key == pygame.K_UP:
        y_change = -5
        x_change = 0


        #down
      elif event.key == pygame.K_DOWN:
        y_change = 5
        x_change = 0


      #key release up and down
    if event.type == pygame.KEYUP:
      if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
        y_change = 0
        x_change = 0 
    rect1.x = rect1.x + x_change
    rect1.y = rect1.y + y_change

    screen.fill((0, 0, 0))

    pygame.draw.rect(screen, WHITE, rect1)
    pygame.draw.rect(screen, RED, rect2)

    if rect1.bottom > screen.get_rect().bottom:
      rect1.center = screen.get_rect().center

    #if rect1.colliderect(rect2):
    if rect1.colliderect(rect2):
      #print("Collision !!")

      rect1.x = rect1.x - x_change
      rect1.y = rect1.y - y_change

    pygame.display.flip()
    clock.tick(60)

pygame.quit()
Geordyd
  • 165
  • 2
  • 10
  • Most likely you are rendering each frame before calculating the collision detection. You need to reverse these two steps. – Code-Apprentice Dec 13 '17 at 23:22
  • make all calculations before `screen.fill((0, 0, 0))` – furas Dec 13 '17 at 23:42
  • 1
    BTW: to make collision with two walls - ie. on left and on bottom - better first change only rect.x, next check collisions, next change only rect.y and check collisions again. Do it because `colliderect` doesn't inform if you collide only on left or only on bottom or on both. See examples in [Lab 16: Pygame Platformer Examples](http://programarcadegames.com/index.php?&chapter=example_code_platformera) – furas Dec 13 '17 at 23:45
  • Thanks for the quick help. It is working right now. – Geordyd Dec 13 '17 at 23:59

2 Answers2

1

you are drawing the rectangles before setting them back when they hit each other so they move into each other for a moment. Make sure to do all drawing after calculations have been made.

Shark Coding
  • 143
  • 1
  • 10
1

The only problem with your program is that you are drawing rect before checking for collision.

Since, there aren't many answers I am writing one for others. You would require two variables x and y to store the previous position i.e. position before the collision. Then you would need to check if the two rectangles have collided using Rect.colliderect. If they have collided reset the current position to the previous position, then draw the wall.

import pygame

pygame.init()
screen = pygame.display.set_mode((1000, 800))

done = False

clock = pygame.time.Clock()

WHITE = (255,255,255)
RED = (255,0,0)

rect1 = pygame.Rect(30, 30, 60, 60)
rect2 = pygame.Rect(100, 100, 60, 60)

previous_x, previous_y = 0, 0
x_change, y_change = 0, 0

speed = 5

while not done:

    screen.fill((0, 0, 0))

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

        if event.type == pygame.KEYDOWN:

            if event.key == pygame.K_LEFT:
                x_change = -speed
                y_change = 0

            if event.key == pygame.K_RIGHT:
                x_change = speed
                y_change = 0

            if event.key == pygame.K_UP:
                y_change = -speed
                x_change = 0

            if event.key == pygame.K_DOWN:
                y_change = speed
                x_change = 0

        if event.type == pygame.KEYUP:
            x_change = 0
            y_change = 0

    previous_x = rect1.x
    previous_y = rect1.y

    rect1.x = rect1.x + x_change
    rect1.y = rect1.y + y_change

    if rect1.colliderect(rect2):
        print("Collision")
        rect1.x = previous_x
        rect1.y = previous_y

    pygame.draw.rect(screen, WHITE, rect1)
    pygame.draw.rect(screen, RED, rect2)

    pygame.display.flip()
    clock.tick(60)

pygame.quit()

If you have many walls store all of their rect in a list. Then use pygame's Rect.collidelist to check if there is any collision.(note: collidelist returns -1 if there is no collision). If there are any then reset to the previous position.

Art
  • 2,836
  • 4
  • 17
  • 34