Set sprite travel limit in pygame

Viewed 95

In my code, my sprite can move in an x-axis left and right. However, it can go off the screen. I would like to prevent it from going outside the screen. I don't know how to do that I have tried writing:

if event.key == pygame.K_LEFT and player.rect.x > 0:
    #player moves left

But it didn't work out. The player sprite just runs out of the screen and I can't make it come back. I'm open to all suggestions. Thanks in advance! I separated my code into three different files --> main.py:

import pygame
import os
import sys
import time
from pygame import mixer
from Sprite1 import *
from settings import *

'''
Setup
'''
pygame.init()

clock = pygame.time.Clock()

all_sprites = pygame.sprite.Group()
player = Player(all_sprites)
player.rect.x = 100
player.rect.y = 500

enemy_list = pygame.sprite.Group()   # create enemy group
enemy = Enemy(enemy_list)# spawn enemy
enemy.rect.x = 400
enemy.rect.y = 470


showStartScreen(surface)
x = 0
'''
Main loop
'''

main = True

while main == True:
    background = pygame.image.load(os.path.join('images', 'Bg.png')).convert()

    font = pygame.font.Font('freesansbold.ttf', 32)
    text = font.render('Health:', True, BLACK, surface)
    textRect = text.get_rect()
    textRect.center = (60, 30)

    rel_x = x % background.get_rect().width
    surface.blit(background, (rel_x - background.get_rect().width, 0))
    if rel_x < width:
        surface.blit(background, (rel_x, 0))

    if player.rect.x >= 560:
        x -= 10
    elif player.rect.x <= 400:
        x += 10

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
            main = False

        if event.type == pygame.KEYDOWN:

            if event.key == pygame.K_LEFT:
                player.control(-steps,0)

            if event.key == pygame.K_RIGHT:
                player.control(steps,0)

        if event.type == pygame.KEYUP:

            if event.key == pygame.K_LEFT:
                player.control(steps,0)

            if event.key == pygame.K_RIGHT:
                player.control(-steps,0)

    keys = pygame.key.get_pressed()
    if not(isJump):
        if keys[pygame.K_UP]:
            isJump = True
    else:
        if jumpCount >= -10:
            player.rect.y -= (jumpCount * abs(jumpCount)) * 1
            jumpCount -= 2
        else:
            jumpCount = 10
            isJump = False

    if player.rect.y > width:
        go_screen(surface)

    surface.blit(text, textRect)
    # dt = time since last tick in milliseconds.
    dt = clock.tick(60) / 1000
    all_sprites.update(dt, enemy_list)
    player.update(dt, enemy_list)
    enemy_list.update(dt, all_sprites)
    all_sprites.draw(surface) #refresh player position
    enemy_list.draw(surface)
    for e in enemy_list:
        e.move()
    pygame.display.flip()

settings.py:

import pygame
isJump = False
jumpCount = 10
width = 960
height = 720
FONT_NAME = 'arial'
fps = 40        # frame rate
pygame.display.set_caption('B.S.G.')
surface = pygame.display.set_mode((width, height))
PLAYER_ACC = 0.5
PLAYER_FRICTION = -0.12
PLAYER_GRAV = 0.8
PLAYER_JUMP = 20
PLAYER_LAYER = 2
PLATFORM_LAYER = 1
BLACK = (0, 0, 0)
steps = 10      # how fast to move

Sprite1:

import pygame
import sys
import os
import time
from pygame import mixer
from pygame.locals import *
from settings import *
vec = pygame.math.Vector2
clock = pygame.time.Clock()

def showStartScreen(surface):
    show = True
    while (show == True):
        background = pygame.image.load(os.path.join('images', 'Starting_scr.png'))
        surface.blit(background, (0,0))
        pygame.display.flip()
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONDOWN:
                show = False

def go_screen(surface):
    show = True
    while (show == True):
        background = pygame.image.load(os.path.join('images', 'GO_screen.png'))
        surface.blit(background, (0,0))
        pygame.display.flip()
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONDOWN:
                pygame.quit()
                sys.exit()


class Player(pygame.sprite.Sprite):
    def __init__(self, all_sprites):
        pygame.sprite.Sprite.__init__(self)
        self.movex = 0
        self.movey = 0
        self.frame = 0
        self.health = 100
        self.jumping = False
        self.images = []
        self.imagesleft = []
        self.imagesright = []
        self.imagesdownl = []
        self.imagesdownr = []
        self.direction = "right"
        self.alpha = (0,0,0)
        self.ani = 4 # animation cycles
        self.all_sprites = all_sprites
        self.add(self.all_sprites)
        self.fire_timer = .1
        self.bullet_timer = .1
        self.pos = vec(40, height - 100)
        self.vel = vec(0, 0)
        self.counter = 0

        for i in range(1,5):
            img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
            img = pygame.transform.rotate(img, -90)
            img.convert_alpha()
            img.set_colorkey(self.alpha)
            self.imagesdownl.append(img)
            self.image = self.imagesdownl[0]
            self.rect  = self.image.get_rect()

        for i in range(1,5):
            img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
            img = pygame.transform.flip(img, False, True)
            img = pygame.transform.rotate(img, -90)
            img.convert_alpha()
            img.set_colorkey(self.alpha)
            self.imagesdownr.append(img)
            self.image = self.imagesdownr[0]
            self.rect  = self.image.get_rect()

        for i in range(1,5):
            img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
            img = pygame.transform.flip(img, True, False)
            img.convert_alpha()
            img.set_colorkey(self.alpha)
            self.imagesleft.append(img)
            self.image = self.imagesleft[0]
            self.rect  = self.image.get_rect()

        for i in range(1,5):
            img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
            img.convert_alpha()
            img.set_colorkey(self.alpha)
            self.imagesright.append(img)
            self.image = self.imagesright[0]
            self.rect  = self.image.get_rect()


    def control(self,x,y):
        '''
        control player movement
        '''
        self.movex += x
        self.movey -= y

    def update(self, dt, enemy_list):
        '''
        Update sprite position
        '''
        self.rect.x = self.rect.x + self.movex
        self.rect.y = self.rect.y + self.movey

        # moving left
        if self.movex < 0:
            self.frame += 1
            if self.frame > 3*self.ani:
                self.frame = 0
            self.image = self.imagesleft[self.frame//self.ani]
            self.direction = "left"

        # moving right
        if self.movex > 0:
            self.frame += 1
            if self.frame > 3*self.ani:
                self.frame = 0
            self.image = self.imagesright[self.frame//self.ani]
            self.direction = "right"

        enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
        for enemy in enemy_hit_list:
            self.health -= 10
            if self.direction == "left":
                self.rect.x += 100
            else:
                self.rect.x -= 100
            print(self.health)

        if self.health <= 0:
            distance = 20
            speed = 10

            if self.counter >= distance and self.counter <= distance*2:
                self.rect.y -= speed
            self.counter += 1
            if self.rect.y < 291:
                self.movey = 10
            if self.direction == "left":
                self.frame += 1
                if self.frame > 3*self.ani:
                    self.frame = 0
                self.image = self.imagesdownr[self.frame//self.ani]
            if self.direction == "right":
                self.frame += 1
                if self.frame > 3*self.ani:
                    self.frame = 0
                self.image = self.imagesdownl[self.frame//self.ani]

        if self.rect.y > height:
            self.kill()

        keys = pygame.key.get_pressed()
        if keys[pygame.K_SPACE]:
            self.bullet_timer -= dt  # Subtract the time since the last tick.

        if keys[pygame.K_x]:
            self.fire_timer -= dt

        if self.bullet_timer <= 0:
            self.bullet_timer = 100  # Bullet ready.
            if keys:  # Left mouse button.
                # Create a new bullet instance and add it to the groups.
                if self.direction == "right":
                    Bullet([self.rect.x + self.image.get_width(), self.rect.y + self.image.get_height()/2], self.direction, self.all_sprites)
                else:
                    Bullet([self.rect.x, self.rect.y + self.image.get_height()/2], self.direction, self.all_sprites)
                self.bullet_timer = .5  # Reset the timer.

        if self.fire_timer <= 0:
            self.fire_timer = 100
            if keys:
                if self.direction == "right":
                    Fire([self.rect.x + 170, self.rect.y + self.image.get_height()/2], self.direction, self.all_sprites)
                else:
                    Fire([self.rect.x - 90, self.rect.y + self.image.get_height()/2], self.direction, self.all_sprites)
                self.fire_timer = .1


class Enemy(pygame.sprite.Sprite):
    '''
    Spawn an enemy
    '''
    def __init__(self, enemy_list):
        pygame.sprite.Sprite.__init__(self)
        self.movex = 0
        self.movey = 0
        self.health = 50
        self.frame = 0
        self.alpha = (0,0,0)
        self.ani = 2 # animation cycles
        self.enemy_list = enemy_list
        self.add(self.enemy_list)
        self.counter = 0 # counter variable
        self.imagesleft = []
        self.imagesright = []
        for i in range(1,17):
            img = pygame.image.load(os.path.join('images','Bot' + str(i) + '.png')).convert()
            img.convert_alpha()
            img.set_colorkey(self.alpha)
            self.imagesleft.append(img)
            self.image = self.imagesleft[0]
            self.rect  = self.image.get_rect()
        for i in range(1,17):
            img = pygame.image.load(os.path.join('images','Bot' + str(i) + '.png')).convert()
            img = pygame.transform.flip(img, True, False)
            img.convert_alpha()
            img.set_colorkey(self.alpha)
            self.imagesright.append(img)
            self.image = self.imagesright[0]
            self.rect  = self.image.get_rect()

    def move(self):
        '''
        enemy movement
        '''
        distance = 30
        speed = 10

        if self.counter >= 0 and self.counter <= distance:
            self.rect.x += speed
            self.frame += 1
            if self.frame > 15*self.ani:
                self.frame = 0
            self.image = self.imagesright[self.frame//self.ani]

        elif self.counter >= distance and self.counter <= distance*2:
            self.rect.x -= speed
            self.frame += 1
            if self.frame > 15*self.ani:
                self.frame = 0
            self.image = self.imagesleft[self.frame//self.ani]
        else:
            self.counter = 0

        self.counter += 1

    def update(self, dt, all_sprites):
        self.rect.x = self.rect.x + self.movex
        self.rect.y = self.rect.y + self.movey
        bullet_list = pygame.sprite.spritecollide(self, all_sprites, True)
        for bullets in bullet_list:
            self.health -= 10
            print(self.health)
        if self.health <= 0:
            img = pygame.image.load(os.path.join('images','E_dead.png')).convert()
            img.convert_alpha()
            img.set_colorkey(self.alpha)
            self.image = img
            distance = 5
            speed = 10

            if self.counter >= 0 and self.counter <= distance:
                self.rect.x += speed

            elif self.counter >= distance and self.counter <= distance*2:
                self.rect.x -= speed
            else:
                self.counter = 0

            self.counter += 1
            self.movey = -20
        if self.rect.y < -50:
            self.kill()

class Bullet(pygame.sprite.Sprite):

    IMAGE = None
    FLIPPED_IMAGE = None

    def __init__(self, pos, direction, *sprite_groups):
        super().__init__(*sprite_groups)

        # cache images
        if not Bullet.IMAGE:
            Bullet.IMAGE = pygame.image.load(os.path.join('images','fireball.png'))
            Bullet.FLIPPED_IMAGE = pygame.transform.flip(Bullet.IMAGE, True, False)

        if direction == "right":
            self.vel = pygame.math.Vector2(750, 0)
            self.image = Bullet.IMAGE
        else:
            self.vel = pygame.math.Vector2(-750, 0)
            self.image = Bullet.FLIPPED_IMAGE

        self.pos = pygame.math.Vector2(pos)
        self.rect  = self.image.get_rect(center=pos)

    def update(self, dt, enemy_list):
        # Add the velocity to the position vector to move the sprite
        self.pos += self.vel * dt
        self.rect.center = self.pos  # Update the rect pos.
        if not pygame.display.get_surface().get_rect().colliderect(self.rect):
            self.kill()

class Fire(pygame.sprite.Sprite):

    IMAGE = None
    FLIPPED_IMAGE = None

    def __init__(self, pos, direction, *sprite_groups):
        super().__init__(*sprite_groups)

        # cache images
        if not Fire.IMAGE:
            Fire.IMAGE = pygame.image.load(os.path.join('images','fire_drag.png'))
            Fire.FLIPPED_IMAGE = pygame.transform.flip(Fire.IMAGE, True, False)

        if direction == "right":
            self.image = Fire.IMAGE
            self.vel = pygame.math.Vector2(0, 0)
        else:
            self.image = Fire.FLIPPED_IMAGE
            self.vel = pygame.math.Vector2(0, 0)
        self.pos = pygame.math.Vector2(pos)
        self.rect  = self.image.get_rect(center=pos)

    def update(self, dt, enemy_list):
        self.too = True
        self.pos += self.vel * dt

        self.rect.center = self.pos  # Update the rect pos.
        if self.too == True:
            self.kill()

Thanks again!

1 Answers

Player.control just set the moving direction of the player, but it doesn't move the player, so it is completely useless to omit the call of plyer.control(). You have to prevent and limit the movement of the player in the method update:

class Player(pygame.sprite.Sprite):
    # [...]

    def update(self, dt, enemy_list):
        
        self.rect.x += self.movex
        self.rect.y += self.movey

        if self.rect.left < 0:
            self.rect.left = 0
        elif self.rect.right > width:
            self.rect.right = width

        if self.rect.top < 0:
            self.rect.top = 0
        elif self.rect.bottom > height:
            self.rect.bottom = height
 
        # [...]
Related