0

I am currently developing a platform game which depends on objects (in the form of platforms) to be their collision in order to prevent the player from exiting the window. Here's my code for collision with platforms/blocks:

#check for collision
self.in_air = True
for tile in world.tile_list:
    #collison x
    if tile[1].colliderect(self.rect.x + dx,self.rect.y , self.width, self.height):
        dx = 0
    # collision y
    if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height):
        # below ground?
        if self.vel_y < 0:
            dy = tile[1].bottom - self.rect.top
            self.vel_y = 0
        # above ground?
        elif self.vel_y >= 0:
            dy = tile[1].top - self.rect.bottom
            self.vel_y = 0
            self.in_air = False

However, this looks unprofessional and I would like to add code which introduces an invisible barrier which stops the player from leaving the screen. I have tried different methods but am currently unsure, any advice would be appreciated.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Ray
  • 13
  • 1
  • why is `tkinter` tagged? and what makes you think the code looks unprofessional? the only thing that stands out is the large indentation, which you should try to limit for purposes of easier reading and not making syntax errors or issues related to that (like having code outside of an if statement where it should have been because you have so many indents it is hard to keep track) (personally I would in this case make a projection of the rectangle and then use that rectangle as an argument to `.colliderect` instead of four numbers like this) – Matiiss Sep 14 '21 at 15:56

1 Answers1

0

If you only want to limit the player to a bounding rectangle, I recommend using pygame.Rect.clamp_ip

moves the rectangle inside another, in place

Define the bounding respectively border rectangle. If the player is limited to the screen, you can get a rectangle that defines the border from the display Surface with pygame.display.get_surface() and pygame.Surface.get_rect:

border_rect = pygame.display.get_surface().get_rect()

Clamp the player pygame.Rect by border_rect:

self.rect.clamp_ip(border_rect)

You can do this with 1 line of code:

self.rect.clamp_ip(pygame.display.get_surface().get_rect())

Minimal example

import pygame

pygame.init()
window = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()

rect = pygame.Rect(0, 0, 40, 40)
rect.center = window.get_rect().center
speed = 10

run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False    

    keys = pygame.key.get_pressed()
    rect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * speed
    rect.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * speed  
    rect.clamp_ip(pygame.display.get_surface().get_rect())    

    window.fill(0)
    pygame.draw.rect(window, (255, 0, 0), rect)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
exit()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • 1
    This worked perfectly, thanks a lot! Also that explanation was really in depth, much appreciated. – Ray Sep 14 '21 at 20:34