Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PyGame-Character Goes Off Screen

Tags:

python

pygame

I am trying to make a game with pygame but I can't figure out how to keep my character from going off screen(set a limit). I have a .png image controlled by user input, but it's possible for the character to go off the visible screen area normally. I can't figure out how to do this. I made a rectangle around the window, (pygame.draw.rect) but I can't assign the rect to a variable so I can create a collision. I also tried this:

if not character.get_rect() in screen.get_rect():
    print("error")

But it didn't work, just spammed the python console with "error" messages.

(i checked the other post with this question but nothing worked/didn't get it)

So my question is, how can I keep my character from going offscreen, and which is the best way to do that?

~thanks

EDIT: My game doesn't have a scrolling playfield/camera. (just a fixed view on the whole window)

like image 711
llp Avatar asked Feb 15 '23 07:02

llp


2 Answers

if not character.get_rect() in screen.get_rect():
    print("error")

I see what you are trying here. If you want to check if a Rect is inside another one, use contains():

contains()
test if one rectangle is inside another
contains(Rect) -> bool
Returns true when the argument is completely inside the Rect.

If you simply want to stop the movement on the edges on the screen, an easy solution is to use clamp_ip():

clamp_ip()
moves the rectangle inside another, in place
clamp_ip(Rect) -> None
Same as the Rect.clamp() [Returns a new rectangle that is moved to be completely inside the argument Rect. If the rectangle is too large to fit inside, it is centered inside the argument Rect, but its size is not changed.] method, but operates in place.

Here's a simple example where you can't move the black rect outside the screen:

import pygame
pygame.init()
screen=pygame.display.set_mode((400, 400))
screen_rect=screen.get_rect()
player=pygame.Rect(180, 180, 20, 20)
run=True
while run:
    for e in pygame.event.get():
        if e.type == pygame.QUIT: run = False
    keys = pygame.key.get_pressed()
    if keys[pygame.K_w]: player.move_ip(0, -1)
    if keys[pygame.K_a]: player.move_ip(-1, 0)
    if keys[pygame.K_s]: player.move_ip(0, 1)
    if keys[pygame.K_d]: player.move_ip(1, 0)
    player.clamp_ip(screen_rect) # ensure player is inside screen
    screen.fill((255,255,255))
    pygame.draw.rect(screen, (0,0,0), player)
    pygame.display.flip()
like image 116
sloth Avatar answered Feb 26 '23 20:02

sloth


When you used pygame.draw.rect, you didn't actually create a "physical" boundary- you just set the colour of the pixels on the screen in a rectangular shape.

If you know the size of the screen, and the displacement of all of the objects on the screen (only applicable if your game has a scrolling playfield or camera), then you can do something like this:

# In the lines of code where you have the player move around
# I assume you might be doing something like this
if keys[pygame.K_RIGHT]:
    player.move(player.getSpeed(),0) # giving the x and y displacements
if keys[pygame.K_LEFT]:
    player.move(-player.getSpeed(),0)

...

class Player:
    ...
    def move(self, dx, dy):
        newX = self.x + dx
        newY = self.y + dy
        self.x = max(0, min(newX, SCREEN_WIDTH)) # you handle where to store screen width
        self.y = max(0, min(newY, SCREEN_HEIGHT))

Note that a useful tool for you to get the size of the Pygame window is pygame.display.get_surface().get_size() which will give you a tuple of the width and height. It is still better, however, to avoid calling this every time you need to know the boundaries of the player. That is, you should store the width and height of the window for later retrieval.

like image 23
SimonT Avatar answered Feb 26 '23 20:02

SimonT