ApparentlyJory
ApparentlyJory

Reputation: 35

How would you end the loop once the sprite has touched the wall?

So I've been struggling for a while to do this. I want the main loop to end/ the game to end once the player hits the border of the screen but can't seem to figure out how I would do this. Here's what I have so far:

import pygame
pygame.init()

class Player(pygame.sprite.Sprite):
    def __init__(self, color):
        super().__init__()
        self.image = pygame.Surface([25, 25])
        self.image.fill(color)
        self.color = color
        self.rect = self.image.get_rect()

    def moveRight(self, pixels):
        if self.rect.x + pixels > 500 - 25:
            self.rect.x = 500 - 25
        self.rect.x += pixels

    def moveLeft(self, pixels):
        if self.rect.x - pixels < 0:
            self.rect.x = 0
        else:
            self.rect.x -= pixels

    def moveUp(self, pixels):
        if self.rect.y - pixels < 0:
            self.rect.y = 0
        else:
            self.rect.y -= pixels

    def moveDown(self, pixels):
        if self.rect.y + pixels > 500 - 25:
            self.rect.y = 500 - 25
        else:
            self.rect.y += pixels

# Color
red = (255, 0, 0)
white = (255, 255, 255)

screen = pygame.display.set_mode([500,500])

# Sprite List
sprite_list = pygame.sprite.Group()
block_list = pygame.sprite.Group()

# Player
player = Player(red)
player.rect.x = 250
player.rect.y = 250
sprite_list.add(player)

notDone = True
clock = pygame.time.Clock()

while notDone:
    current_time = pygame.time.get_ticks()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            notDone = False

    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT] or keys[pygame.K_a]:
        player.moveLeft(3)
    if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
        player.moveRight(3)
    if keys[pygame.K_UP] or keys[pygame.K_w]:
        player.moveUp(3)
    if keys[pygame.K_DOWN] or keys[pygame.K_s]:
        player.moveDown(3)

    screen.fill(white)

    sprite_list.draw(screen)
    pygame.display.flip()

    clock.tick(60)

pygame.quit()

In my example, the player sprite can move up, down, left, and right. The character also cannot move past the border. Is there a way for the loop to end (as if a game over) once the sprite hits said border?

Upvotes: 1

Views: 63

Answers (2)

sloth
sloth

Reputation: 101072

If you want to end the game when the player rect hits the screen's edge, then there's no point in correcting the player's position if the player goes outside. It would be easier to use Rect.clamp_ip anyway.

As for quitting the game, the easiest way is to put your main loop in a function and just return in case you want to exit.

To check if a rect (like the player's) "leaves" another rect (like the rect of the screen), you can use the Rect.contains function.

import pygame


class Player(pygame.sprite.Sprite):
    def __init__(self, color):
        super().__init__()
        self.image = pygame.Surface([25, 25])
        self.image.fill(color)
        self.rect = self.image.get_rect()

    def moveRight(self, pixels):
        self.rect.x += pixels

    def moveLeft(self, pixels):
        self.rect.x -= pixels

    def moveUp(self, pixels):
        self.rect.y -= pixels

    def moveDown(self, pixels):
        self.rect.y += pixels

def main():
    pygame.init()
    screen = pygame.display.set_mode([500,500])

    # Sprite List
    sprite_list = pygame.sprite.Group()
    block_list = pygame.sprite.Group()

    # Player
    player = Player('red')
    player.rect.x = 250
    player.rect.y = 250
    sprite_list.add(player)

    clock = pygame.time.Clock()

    while True:
        current_time = pygame.time.get_ticks()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return

        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            player.moveLeft(3)
        if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            player.moveRight(3)
        if keys[pygame.K_UP] or keys[pygame.K_w]:
            player.moveUp(3)
        if keys[pygame.K_DOWN] or keys[pygame.K_s]:
            player.moveDown(3)

        if not screen.get_rect().contains(player.rect):
            return

        screen.fill('white')

        sprite_list.draw(screen)
        pygame.display.flip()

        clock.tick(60)

main()

Upvotes: 2

Rabbid76
Rabbid76

Reputation: 210968

The move* methods of the Player class must return a Boolean value that indicates whether the player hit the wall. Return True if the player hits the wall, False otherwise:

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

    def moveRight(self, pixels):
        if self.rect.x + pixels > 500 - 25:
            self.rect.x = 500 - 25
            return True
        self.rect.x += pixels
        return False

    def moveLeft(self, pixels):
        if self.rect.x - pixels < 0:
            self.rect.x = 0
            return True
        self.rect.x -= pixels
        return False

    def moveUp(self, pixels):
        if self.rect.y - pixels < 0:
            self.rect.y = 0
            return True
        self.rect.y -= pixels
        return False

    def moveDown(self, pixels):
        if self.rect.y + pixels > 500 - 25:
            self.rect.y = 500 - 25
            return True
        self.rect.y += pixels
        return False

Evaluate the return value in the application loop and set notDone = False if the player touches the wall:

while notDone:
    # [...]

    hit = False
   
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT] or keys[pygame.K_a]:
        hit = player.moveLeft(3)
    if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
        hit = player.moveRight(3)
    if keys[pygame.K_UP] or keys[pygame.K_w]:
        hit = player.moveUp(3)
    if keys[pygame.K_DOWN] or keys[pygame.K_s]:
        hit = player.moveDown(3)
    
    if hit:
        notDone = False

    # [...]

Complete example

import pygame
pygame.init()

class Player(pygame.sprite.Sprite):
    def __init__(self, color):
        super().__init__()
        self.image = pygame.Surface([25, 25])
        self.image.fill(color)
        self.color = color
        self.rect = self.image.get_rect()

    def moveRight(self, pixels):
        if self.rect.x + pixels > 500 - 25:
            self.rect.x = 500 - 25
            return True
        self.rect.x += pixels
        return False

    def moveLeft(self, pixels):
        if self.rect.x - pixels < 0:
            self.rect.x = 0
            return True
        self.rect.x -= pixels
        return False

    def moveUp(self, pixels):
        if self.rect.y - pixels < 0:
            self.rect.y = 0
            return True
        self.rect.y -= pixels
        return False

    def moveDown(self, pixels):
        if self.rect.y + pixels > 500 - 25:
            self.rect.y = 500 - 25
            return True
        self.rect.y += pixels
        return False

# Color
red = (255, 0, 0)
white = (255, 255, 255)

screen = pygame.display.set_mode([500,500])

# Sprite List
sprite_list = pygame.sprite.Group()
block_list = pygame.sprite.Group()

# Player
player = Player(red)
player.rect.x = 250
player.rect.y = 250
sprite_list.add(player)

notDone = True
clock = pygame.time.Clock()

while notDone:
    current_time = pygame.time.get_ticks()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            notDone = False

    hit = False
   
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT] or keys[pygame.K_a]:
        hit = player.moveLeft(3)
    if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
        hit = player.moveRight(3)
    if keys[pygame.K_UP] or keys[pygame.K_w]:
        hit = player.moveUp(3)
    if keys[pygame.K_DOWN] or keys[pygame.K_s]:
        hit = player.moveDown(3)
    
    if hit:
        notDone = False

    screen.fill(white)

    sprite_list.draw(screen)
    pygame.display.flip()

    clock.tick(60)

pygame.quit()

Upvotes: 1

Related Questions