How to create a border in Pygame

14.2k Views Asked by At

I would like to know how to create a border in Pygame to stop the user controlled object from exiting the screen. Right now, I only have it so python prints some text when the user controlled object has come near one of the 4 sides.

Here is my code so far.

import pygame
from pygame.locals import *
pygame.init()

#Display Stuff 
screenx = 1000
screeny = 900
screen = pygame.display.set_mode((screenx,screeny))
pygame.display.set_caption('Block Runner')
clock = pygame.time.Clock()
image = pygame.image.load('square.png')




#Color Stuff
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
white = (255,255,255)
black = (0,0,0)


#Variables
x_blocky = 50
y_blocky = 750
blocky_y_move = 0
blocky_x_move = 0



#Animations
def Blocky(x_blocky, y_blocky, image):
screen.blit(image,(x_blocky,y_blocky))

#Game Loop

game_over = False
while not game_over:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                blocky_y_move = -3
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_UP:
                blocky_y_move = 0

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_DOWN:
                blocky_y_move = 3
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_DOWN:
                blocky_y_move = 0

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                blocky_x_move = 3
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_RIGHT:
                blocky_x_move = 0

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                blocky_x_move = -3
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT:
                blocky_x_move = 0

        if x_blocky > 870 or x_blocky < 0:
            print(' X Border')


        if y_blocky > 750 or y_blocky < 2:
            print(' Y Border')



    y_blocky += blocky_y_move
    x_blocky += blocky_x_move


    screen.fill(white)
    Blocky(x_blocky, y_blocky, image)
    pygame.display.update()
clock.tick(60)
4

There are 4 best solutions below

0
On

You can set the boundaries using the min and max functions.

Here is the concept:

We have a pygame object that moves in all four directions; lets say the user holds down the LEFT arrow key, so that the object reaches the top of the screen. The y-coordinate of the top of the screen will always be 0, so we want the object to come to a stop at y-coordinate 0.

This may seem as simple as:

if char.rect.y > 0:
    char.rect.y -= char.speed

But this will result in a bug ig char.speed is greater than 1. Like when the object is at y-coordinate 5, and its speed is 10; the condition still allows for one more step for the object, resulting in the object coming 5 pixels out of the pygame window. What we want to do is more like:

if char.rect.y > 0:
    char.rect.y -= char.speed
if char.rect.y < 0:
    char.rect.y = 0

to push the object back into the boundaries. The above block of code can be simplified with the max function:

self.rect.y = max([self.rect.y - self.speed, 0])

For the object moving down:

if char.rect.y < HEIGHT - char.height:
    char.rect.y += char.speed
if char.rect.y > HEIGHT - char.height:
    char.rect.y = HEIGHT - char.height

or, the more efficient and clean method:

self.rect.y = min([self.rect.y + self.speed, HEIGHT - self.height])

For going left and right, simply replace the ys and height (and HEIGHT) from two lines above with xs and widths (and WIDTH).

All together:

import pygame

pygame.init()

WIDTH = 600
HEIGHT = 600
wn = pygame.display.set_mode((WIDTH, HEIGHT))

class Player:
    def __init__(self):
        self.speed = 1
        self.width = 20
        self.height = 20
        self.color = (255, 255, 0)
        self.rect = pygame.Rect((WIDTH - self.width) / 2, (HEIGHT - self.height) / 2, 20, 20)

    def up(self):
        self.rect.y = max([self.rect.y - self.speed, 0])
        
    def down(self):
        self.rect.y = min([self.rect.y + self.speed, HEIGHT - self.height])
        
    def left(self):
        self.rect.x = max([self.rect.x - self.speed, 0])
        
    def right(self):
        self.rect.x = min([self.rect.x + self.speed, WIDTH - self.width])
        
    def draw(self):
        pygame.draw.rect(wn, self.color, self.rect)

char = Player()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
    keys = pygame.key.get_pressed()
    if keys[pygame.K_UP]:
        char.up()
    if keys[pygame.K_DOWN]:
        char.down()
    if keys[pygame.K_LEFT]:
        char.left()
    if keys[pygame.K_RIGHT]:
        char.right()
    wn.fill((0, 0, 0))
    char.draw()
    pygame.display.update()

enter image description here

Good luck!

2
On

Well, simply don't increase your move variable any further, if you detect that the user object is near or at the border. Or reverse the move direction, depending on your general intent.

    if x_blocky > 870 or x_blocky < 0:
        print(' X Border')
        blocky_x_move = 0


    if y_blocky > 750 or y_blocky < 2:
        print(' Y Border')
        blocky_y_move = 0
0
On

Don't use integers to store your position. Use a Rect.

So instead of

x_blocky = 50
y_blocky = 750

use

blocky_pos = pygame.rect.Rect(50, 750)

Now you can simply use

blocky_pos.move_ip(blocky_x_move, blocky_y_move)

to move your object.

After moving, you can simply call clamp/clamp_ip to ensure the blocky_pos Rect is always inside the screen.

blocky_pos.clamp_ip(screen.get_rect())

Also, you don't need to define basic colors yourself, you could simply use pygame.color.Color('Red') for example.

I also suggest you use pygame.key.get_pressed() to get all pressed keys to see how to move your object instead of creating 1000 lines of event handling code.

0
On

Also, you have some redundant code with your keyboard movement. Instead of writing

if event.type == KEYDOWN:

over and over again, group the KEYUP if statements and KEYDOWN if statements.

if event.type == pygame.KEYDOWN:
    if event.key == pygame.K_UP:
        blocky_y_move = -3
    elif event.key == pygame.K_DOWN:
        blocky_y_move = +3

etc, and:

if event.type == pygame.KEYUP:
    if event.key == pygame.K_UP:
        blocky_y_move = 0
    elif event.type == pygame.K_DOWN:
        blocky_y_move = 0

etc