gnaw
gnaw

Reputation: 395

Pygame sprites escaping border

I am making a survival-based rpg game, but when I move the player sprite it would move out of the wall. I implemented a basic function to prevent this from happening, and it works.

if player.rect.x<0:
    player.rect.x=0
if player.rect.x>total_level_width:
    player.rect.x=total_level_width
if player.rect.y<0:
    player.rect.y=0
if player.rect.y>total_level_height:
    player.rect.y=total_level_height

It prevents the player sprite from moving out of the walls, but the sprite can still pass through the bottom and right walls.

Any help is welcome!

Thank you!

Full code:

import pygame
import random

black=(0,0,0)
white=(255,255,255)
green=(0,128,0)
skin=(255,224,189)

class Player(pygame.sprite.Sprite):
    def __init__(self,x,y):
        super(Player,self).__init__()
        self.image=pygame.Surface([25, 25])
        self.image.fill(skin)
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        self.change_x=0
        self.change_y=0
        self.speed=7

    def changespeed(self,x,y):
        self.change_x += x
        self.change_y += y

    def update(self):
        self.rect.x += self.change_x
        self.rect.y += self.change_y

class Tree(pygame.sprite.Sprite):
    def __init__(self,x,y):
        super(Tree,self).__init__()
        self.image=pygame.Surface([40, 40])
        pygame.draw.circle(self.image,green,(x,y),30,10)
        self.image.fill(green)
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        self.wood=20

    def update(self):
        pass

class Camera(object):
    def __init__(self,camera_func,width,height):
        self.camera_func=camera_func
        self.state=pygame.Rect(0,0,width,height)

    def apply(self,target):
        return target.rect.move(self.state.topleft)

    def update(self,target):
        self.state=self.camera_func(self.state,target.rect)

def complex_camera(camera, target_rect):
    l,t,_, _=target_rect
    _,_, w, h=camera
    l,t,_,_=-l+screen_width/2, -t+screen_height/2, w, h

    l = min(0, l)                           
    l = max(-(camera.width-screen_width), l)
    t = max(-(camera.height-screen_height), t)
    t = min(0, t)                           

    return pygame.Rect(l, t, w, h)

pygame.init()

screen_width=800
screen_height=600
screen=pygame.display.set_mode([screen_width,screen_height])

pygame.display.set_caption('Survive')

total_level_width=screen_width*5
total_level_height=screen_height*5
camera = Camera(complex_camera, total_level_width, total_level_height)

#sprites1 includes the player
#sprites2 includes trees

player=Player(20,20)
sprites1=pygame.sprite.Group()
sprites1.add(player)

sprites2=pygame.sprite.Group()
for i in range(2000):
    tree=Tree(random.randint(100,7900),random.randint(100,5900))
    sprites2.add(tree)

clock=pygame.time.Clock()
done=False

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

        elif event.type==pygame.KEYDOWN:
            if event.key==pygame.K_a:
                player.changespeed(-(player.speed), 0)
            elif event.key==pygame.K_d:
                player.changespeed(player.speed, 0)
            elif event.key==pygame.K_w:
                player.changespeed(0, -(player.speed))
            elif event.key==pygame.K_s:
                player.changespeed(0, player.speed)

        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_a:
                player.changespeed(player.speed, 0)
            elif event.key == pygame.K_d:
                player.changespeed(-(player.speed), 0)
            elif event.key == pygame.K_w:
                player.changespeed(0, player.speed)
            elif event.key == pygame.K_s:
                player.changespeed(0, -(player.speed))

    camera.update(player)
    sprites1.update()
    sprites2.update()

    if player.rect.x<0:
        player.rect.x=0
    if player.rect.x>total_level_width:
        player.rect.x=total_level_width
    if player.rect.y<0:
        player.rect.y=0
    if player.rect.y>total_level_height:
        player.rect.y=total_level_height

    screen.fill(white)
    for e in sprites1:
        screen.blit(e.image, camera.apply(e)) 
    for e in sprites2:
        screen.blit(e.image, camera.apply(e)) 

    pygame.display.flip()

    clock.tick(60)

pygame.quit()

Upvotes: 0

Views: 462

Answers (2)

Mercury Platinum
Mercury Platinum

Reputation: 1569

A even easier method of implementing a game area is to define a rect, and in the update function of that sprite, use pygame.Rect.clamp_ip(Rect_name) Heres an example

playarea = pygame.Rect(100, 100)
# inside of the player class...
def update():
    pygame.Rect.clamp_ip(playarea)

Upvotes: 1

furas
furas

Reputation: 142641

Rect() has other useful fields

x,y
top, left, bottom, right
topleft, bottomleft, topright, bottomright
midtop, midleft, midbottom, midright
center, centerx, centery
size, width, height
w,h

So you can use right and bottom

if player.rect.right  > total_level_width:
    player.rect.right = total_level_width

if player.rect.bottom > total_level_height:
    player.rect.bottom = total_level_height

Upvotes: 1

Related Questions