Not letting the character move out of the window [duplicate]

I tried using this kind of code:

if circleX - 16 == 0:
    circleX = 16
elif circleY - 16 == 0:
    circleY = 16
elif circleY + 16 == 500:
    circleY = 484
elif circleX + 16 == 500:
    circleX = 484
elif circleY - 16 == 0 and circleX - 16 == 0:
    circleY = 16
    circleX = 16
elif circleY + 16 == 500 and circleX + 16 == 500:
    circleX = 484
    circleY = 484
elif circleY + 16 == 500 and circleX - 16 == 0:
    circleY = 484
    circleX = 16
elif circleY - 16 == 0 and circleX + 16 == 500:
    circleX = 484
    circleY = 16

But it doesn't seem to work, what am i doing wrong?


Solution 1:

I recommend to use a pygame.Rect object to limit the a circle to the bounds of the window In the following window is the display Surface :

radius = 16
clampRect = window.get_rect().inflate(-radius*2, -radius*2)
circleX = max(clampRect.left, min(clampRect.right, circleX))
circleY = max(clampRect.top, min(clampRect.bottom, circleY))

Explanation:

get_rect() generates a pygame.Rect with the size oft the pygame.Surface which is associated to the display. inflate() generates a new rectangle with the size changed by the diameter oft the circle, where the rectangle remains centered around its current center.
In the following, min and max are used to clamp the center of the circle in the area defined by the rectangle.

Solution 2:

You could avoid sameness relation comparison == for boundary. I use <= or >= for compare boundary.

I do not know about your code and context, but I suppose circleX, circleY has been changed on other method.

If it change variables as like circleX += 20, it can be passed all if-condition. or if it was called too fast by some events on thread environment, we can not trust the value of circleX.

I recommend to compare as following:

if circleX - 16 <= 0:  # Left border
    circleX = 16
elif circleY - 16 <= 0:  # Top
    circleY = 16
elif circleY + 16 >= 500:  # Bottom
    circleY = 484
elif circleX + 16 >= 500:  # Right
    circleX = 484
elif circleY - 16 <= 0 and circleX - 16 <= 0:  # Top Left corner
    circleY = 16
    circleX = 16
elif circleY + 16 >= 500 and circleX + 16 >= 500:  # Bottom right
    circleX = 484
    circleY = 484
elif circleY + 16 >= 500 and circleX - 16 <= 0:  # Bottom left
    circleY = 484
    circleX = 16
elif circleY - 16 <= 0 and circleX + 16 >= 500:  # Top right
    circleX = 484
    circleY = 16

and it can be shorten by using less if condition:

if circleX - 16 <= 0:      # Left border
    circleX = 16
    if circleY - 16 <= 0:  # Top Left corner
        circleY = 16
elif circleY - 16 <= 0:      # Top
    circleY = 16
    if circleX + 16 >= 500:  # Top right
        circleX = 484
elif circleY + 16 >= 500:  # Bottom
    circleY = 484
    if circleX - 16 <= 0:  # Bottom left
        circleX = 16
elif circleX + 16 >= 500:    # Right
    circleX = 484
    if circleY + 16 >= 500:  # Bottom right
        circleY = 484

BUT, more short code in my personal favorite is:

circleX = min(max(16, circleX), 484)
circleY = min(max(16, circleY), 484)