Python Forum
[PyGame] Creating Map Obstacles
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] Creating Map Obstacles
#1
I saved the image without paying for it, however, I don't intend to use it for anything but learning how to use PyGame. I am a beginner.

When the code is executed, the rectangle object controlled by the player can't go through the fence, however, when the fence is against the top or bottom of the rectangle object, it can't move left or right, and when the fence is against the left or right of the rectangle object, it can't move up or down. How Do I fix this?

Sorry if the code isn't very organized or clear, and thank you in advance!

Map sprite found here: https://www.scirra.com/store/2d-game-gra...t-pack-184

# Allows the usage of the PyGame library
import pygame

# Initializes PyGame
pygame.init()

# RGB Colors
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)

# Coordinates of the rectangle (player) object
x = 507
y = 60

# Bad Coordinates (Fence)
# bad_coordinates = bad_x, bad_y = range(447, 528), 150

# Directions
up = False
down = False
left = False
right = False

# Height and width of the window
height = 320
width = 720

# Barrier
minimum_x = 342

# Initializes the window's title, width, and height
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("New Game")
# Loads the background image
farm_image = pygame.image.load("farm_sprite.png").convert()

# Keeps the while loop running
done = False

# Boolean to identify whether the player has unlocked the currently locked area
unlocked = False

# Creates a clock object to keep track of time
clock = pygame.time.Clock()

# Keeps the program running
while not done:

    # Allows the user to exit by pressing the X button without throwing an error
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    # Fence Rectangles
    fence = [
        pygame.draw.rect(screen, red, pygame.Rect(455, 65, 20, 85)),
        pygame.draw.rect(screen, red, pygame.Rect(390, 65, 85, 20)),
        pygame.draw.rect(screen, red, pygame.Rect(390, 0, 20, 85)),
        pygame.draw.rect(screen, red, pygame.Rect(395, 0, 240, 20)),
        pygame.draw.rect(screen, red, pygame.Rect(615, 0, 20, 150)),
        pygame.draw.rect(screen, red, pygame.Rect(580, 130, 40, 20)),
        pygame.draw.rect(screen, red, pygame.Rect(455, 130, 80, 20))
    ]

    # Assigns a list of the possible pressed keys to a variable
    pressed = pygame.key.get_pressed()

    # If the UP key is pressed, move the player upwards
    if pressed[pygame.K_UP]:
        if y != 3 and (char.collidelist(fence)) == -1 or down is True:
            up = True
            down = False
            y -= 3

    # If the DOWN key is pressed, move the player downwards
    if pressed[pygame.K_DOWN]:
        if y != 279 and (char.collidelist(fence)) == -1 or up is True:
            down = True
            up = False
            y += 3

    # If the LEFT key is pressed, move the player to the left
    if pressed[pygame.K_LEFT]:
        if x != minimum_x and not unlocked and (char.collidelist(fence)) == -1 or right is True:
            left = True
            right = False
            x -= 3

        # If the area is unlocked, allow the player to move in the area, as well as create a new barrier
        """
        elif unlocked and (char.collidelist(fence)) == -1 or right is True:
            if x != 3:
                x -= 3
        """

    # If the RIGHT key is pressed, move the player to the right
    if pressed[pygame.K_RIGHT]:
        if x != 693 and (char.collidelist(fence)) == -1 or left is True:
            right = True
            left = False
            x += 3

    # Place the background image on the window
    screen.blit(farm_image, [0, 0])

    # Draw the player object onto the screen
    char = pygame.draw.rect(screen, red, pygame.Rect(x, y, 25, 40))
    
    # Update the full Surface to the screen
    pygame.display.flip()

    # Run the program at 60 frames per second
    clock.tick(60)
Reply
#2
can you provide farm_sprite.png so we can run it
Recommended Tutorials:
Reply
#3
[Image: rpg_tileset_promo_720.png]
(farm_sprite.png)
Reply
#4
You need to move collision out of moving. Then handle it after sprite has been moved.
Right now it collides and never told how to get uncollided. So once collided it stuck forever.
Collision could be solve in two ways. When collided move back to old position or displace sprite.

The up, down, left, and right variables aren't needed.

Fence locations should be outside of main loop.
    # Fence Rectangles
    fence = [
        pygame.draw.rect(screen, red, pygame.Rect(455, 65, 20, 85)),
        pygame.draw.rect(screen, red, pygame.Rect(390, 65, 85, 20)),
        pygame.draw.rect(screen, red, pygame.Rect(390, 0, 20, 85)),
        pygame.draw.rect(screen, red, pygame.Rect(395, 0, 240, 20)),
        pygame.draw.rect(screen, red, pygame.Rect(615, 0, 20, 150)),
        pygame.draw.rect(screen, red, pygame.Rect(580, 130, 40, 20)),
        pygame.draw.rect(screen, red, pygame.Rect(455, 130, 80, 20))
    ]
outside of main loop. Build sequence once.
fences = (
    pygame.Rect(455, 65, 20, 85),
    pygame.Rect(390, 65, 85, 20),
    pygame.Rect(390, 0, 20, 85),
    pygame.Rect(395, 0, 240, 20),
    pygame.Rect(615, 0, 20, 150),
    pygame.Rect(580, 130, 40, 20),
    pygame.Rect(455, 130, 80, 20))
Fence draw code
for fence in fences:
    pygame.draw.rect(screen, pygame.Color('red'), fence)
You can also look into pygame.Vector2 or just use pygame.Rect for player movement.
char = pygame.Rect(507, 60, 25, 40)
# mainloop
moved = None
if pressed[pygame.K_UP] and not press[pygame.K_DOWN]:
    moved = char.move(0, -3)
# ...

# if no collision allow movement
if moved:
    if moved.collidelist(fences) == -1:
        char = moved
99 percent of computer problems exists between chair and keyboard.
Reply
#5
So now my code looks like this:
# Allows the usage of the PyGame library
import pygame

# Initializes PyGame
pygame.init()

# RGB Colors
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)


# Coordinates of the rectangle (player) object
x = 507
y = 60

# Bad Coordinates (Fence)
# bad_coordinates = bad_x, bad_y = range(447, 528), 150

# Height and width of the window
height = 320
width = 720

# Barrier
minimum_x = 342

# Initializes the window's title, width, and height
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("New Game")
# Loads the background image
farm_image = pygame.image.load("farm_sprite.png").convert()
# Fence Rectangles

fences = (
    pygame.Rect(455, 65, 20, 85),
    pygame.Rect(390, 65, 85, 20),
    pygame.Rect(390, 0, 20, 85),
    pygame.Rect(395, 0, 240, 20),
    pygame.Rect(615, 0, 20, 150),
    pygame.Rect(580, 130, 40, 20),
    pygame.Rect(455, 130, 80, 20)
)

# Puts the fences on the screen
for fence in fences:
    pygame.draw.rect(screen, pygame.Color('red'), fence)

# Draw the player object onto the screen
char = pygame.Rect(507, 60, 25, 40)

# Keeps the while loop running
done = False

# Boolean to identify whether the player has unlocked the currently locked area
unlocked = False

# Creates a clock object to keep track of time
clock = pygame.time.Clock()

# Keeps the program running
while not done:

    moved = None

    # Allows the user to exit by pressing the X button without throwing an error
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    # Assigns a list of the possible pressed keys to a variable
    pressed = pygame.key.get_pressed()

    # If the UP key is pressed, move the player upwards
    if pressed[pygame.K_UP] and not pressed[pygame.K_DOWN]:
        if y != 3:
            moved = char.move(0, -3)

    # If the DOWN key is pressed, move the player downwards
    if pressed[pygame.K_DOWN] and not pressed[pygame.K_UP]:
        if y != 279:
            moved = char.move(0, 3)

    # If the LEFT key is pressed, move the player to the left
    if pressed[pygame.K_LEFT] and not pressed[pygame.K_RIGHT]:
        if x != minimum_x and not unlocked:
            moved = char.move(-3, 0)

        # If the area is unlocked, allow the player to move in the area, as well as create a new barrier
        elif unlocked:
            if x != 3:
                moved = char.move(-3, 0)

    # If the RIGHT key is pressed, move the player to the right
    if pressed[pygame.K_RIGHT] and not pressed[pygame.K_LEFT]:
        if x != 693:
            moved = char.move(3, 0)

    if moved:
        if moved.collidelist(fences) == -1:
            char = moved

    # Place the background image on the window
    screen.blit(farm_image, [0, 0])

    # Update the full Surface to the screen
    pygame.display.flip()

    # Run the program at 60 frames per second
    clock.tick(60)
I know I need to clean the code up, but I'll do that later.

@Windspar, I followed your instructions, and I think I followed them correctly. One problem though - how do I get the player to show on the screen?
Reply
#6
after screen.blit(farm_image, (0, 0))
pygame.draw.rect(screen, pygame.Color('red'), char)

this need to go in main loop. After screen.blit(farm_image, (0,0))
# Puts the fences on the screen
for fence in fences:
    pygame.draw.rect(screen, pygame.Color('red'), fence)

Romove this. No longer used.
# Coordinates of the rectangle (player) object
x = 507
y = 60

If you want to make sure object stay on screen.
# Initializes the window's title, width, and height
screen = pygame.display.set_mode((720, 320))
rect = screen.get_rect()
if moved:
    if moved.collidelist(fences) == -1 and rect.contains(moved):
        char = moved
Pygame Rect

If you don't do method above.
if pressed[pygame.K_UP] and not pressed[pygame.K_DOWN]:
    if y != 3:
        moved = char.move(0, -3)
Change to.
if pressed[pygame.K_UP] and not pressed[pygame.K_DOWN]:
    if char.y != 3:
        moved = char.move(0, -3)
If you did rect for stay on screen.
if pressed[pygame.K_UP] and not pressed[pygame.K_DOWN]:
    moved = char.move(0, -3)
99 percent of computer problems exists between chair and keyboard.
Reply
#7
(Jun-06-2019, 08:45 PM)Windspar Wrote: after screen.blit(farm_image, (0, 0))
pygame.draw.rect(screen, pygame.Color('red'), char)

this need to go in main loop. After screen.blit(farm_image, (0,0))
# Puts the fences on the screen for fence in fences: pygame.draw.rect(screen, pygame.Color('red'), fence)

Romove this. No longer used.
# Coordinates of the rectangle (player) object x = 507 y = 60

If you want to make sure object stay on screen.
# Initializes the window's title, width, and height screen = pygame.display.set_mode((720, 320)) rect = screen.get_rect()
if moved: if moved.collidelist(fences) == -1 and rect.contains(moved): char = moved
Pygame Rect
If you don't do method above.
if pressed[pygame.K_UP] and not pressed[pygame.K_DOWN]: if y != 3: moved = char.move(0, -3)
Change to.
if pressed[pygame.K_UP] and not pressed[pygame.K_DOWN]: if char.y != 3: moved = char.move(0, -3)
If you did rect for stay on screen.
if pressed[pygame.K_UP] and not pressed[pygame.K_DOWN]: moved = char.move(0, -3)

My Code Now:
# Allows the usage of the PyGame library
import pygame

# Initializes PyGame
pygame.init()

# RGB Colors
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)

# Bad Coordinates (Fence)
# bad_coordinates = bad_x, bad_y = range(447, 528), 150

# Barrier
minimum_x = 342

# Initializes the window's title, width, and height
screen = pygame.display.set_mode((720, 320))
pygame.display.set_caption("New Game")
# Loads the background image
farm_image = pygame.image.load("farm_sprite.png").convert()
# Fence Rectangles
fences = (
    pygame.Rect(455, 65, 20, 85),
    pygame.Rect(390, 65, 85, 20),
    pygame.Rect(390, 0, 20, 85),
    pygame.Rect(395, 0, 240, 20),
    pygame.Rect(615, 0, 20, 150),
    pygame.Rect(580, 130, 40, 20),
    pygame.Rect(455, 130, 80, 20)
)

# Draw the player object onto the screen
char = pygame.Rect(507, 60, 25, 40)

# Keeps the while loop running
done = False

# Boolean to identify whether the player has unlocked the currently locked area
unlocked = False

# Creates a clock object to keep track of time
clock = pygame.time.Clock()

# Keeps the program running
while not done:

    moved = None

    # Allows the user to exit by pressing the X button without throwing an error
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    # Assigns a list of the possible pressed keys to a variable
    pressed = pygame.key.get_pressed()

    # If the UP key is pressed, move the player upwards
    if pressed[pygame.K_UP] and not pressed[pygame.K_DOWN]:
        if char.y != 3:
            moved = char.move(0, -3)

    # If the DOWN key is pressed, move the player downwards
    if pressed[pygame.K_DOWN] and not pressed[pygame.K_UP]:
        if char.y != 279:
            moved = char.move(0, 3)

    # If the LEFT key is pressed, move the player to the left
    if pressed[pygame.K_LEFT] and not pressed[pygame.K_RIGHT]:
        if char.x != minimum_x and not unlocked:
            moved = char.move(-3, 0)

        # If the area is unlocked, allow the player to move in the area, as well as create a new barrier
        elif unlocked:
            if char.x != 3:
                moved = char.move(-3, 0)

    # If the RIGHT key is pressed, move the player to the right
    if pressed[pygame.K_RIGHT] and not pressed[pygame.K_LEFT]:
        if char.x != 693:
            moved = char.move(3, 0)

    if moved:
        if moved.collidelist(fences) == -1:
            char = moved

    # Place the background image on the window
    screen.blit(farm_image, [0, 0])

    # Puts the fences on the screen
    for fence in fences:
        pygame.draw.rect(screen, pygame.Color('red'), fence)

    pygame.draw.rect(screen, pygame.Color('red'), char)

    # Update the full Surface to the screen
    pygame.display.flip()

    # Run the program at 60 frames per second
    clock.tick(60)
I'm pretty sure I followed your instructions, yet, I can't press the up and right keys at the same time. I can only do one or the other, same goes for up-left, down-left, and down-right. And when I am pressing right-up, right-down, left-up, or left-down, while the the player is against a wall, it won't move.

How would I fix this? Did I not follow your instructions correctly?

P.S. - Thanks for helping me out!
Reply
#8
I over looked that.
speed = 3
movement = pygame.Vector2(0, 0)
# If the UP key is pressed, move the player upwards
    if pressed[pygame.K_UP] and not pressed[pygame.K_DOWN]:
        if char.y != 3:
            movement.y -= speed
 
    # If the DOWN key is pressed, move the player downwards
    if pressed[pygame.K_DOWN] and not pressed[pygame.K_UP]:
        if char.y != 279:
            movement.y += speed
 
    # If the LEFT key is pressed, move the player to the left
    if pressed[pygame.K_LEFT] and not pressed[pygame.K_RIGHT]:
        if char.x != minimum_x and not unlocked:
            movement.x -= speed

    # If the RIGHT key is pressed, move the player to the right
    if pressed[pygame.K_RIGHT] and not pressed[pygame.K_LEFT]:
        if char.x != 693:
            movement.x += speed

    if movement.x != 0 or movement.y != 0:
        moved = char.move(movement.x, movement.y)
        if moved.collidelist(fences) == -1:
            char = moved
or
speed = 3
movement = pygame.Vector2(0, 0)
# If the UP key is pressed, move the player upwards
    if pressed[pygame.K_UP] and not pressed[pygame.K_DOWN]:
        movement.y -= speed
 
    # If the DOWN key is pressed, move the player downwards
    if pressed[pygame.K_DOWN] and not pressed[pygame.K_UP]:        
        movement.y += speed
 
    # If the LEFT key is pressed, move the player to the left
    if pressed[pygame.K_LEFT] and not pressed[pygame.K_RIGHT]:
        movement.x -= speed

    # If the RIGHT key is pressed, move the player to the right
    if pressed[pygame.K_RIGHT] and not pressed[pygame.K_LEFT]:
        movement.x += speed

    if movement.x != 0 or movement.y != 0:
        # Deflate. Where 3 pixels away from edge
        rect = screen.get_rect().inflate(-6, -6) 
        moved = char.move(movement.x, movement.y)
        if moved.collidelist(fences) == -1 and rect.contains(moved):
            char = moved
99 percent of computer problems exists between chair and keyboard.
Reply
#9
(Jun-07-2019, 07:53 PM)Windspar Wrote: I over looked that.
speed = 3 movement = pygame.Vector2(0, 0) # If the UP key is pressed, move the player upwards if pressed[pygame.K_UP] and not pressed[pygame.K_DOWN]: if char.y != 3: movement.y -= speed # If the DOWN key is pressed, move the player downwards if pressed[pygame.K_DOWN] and not pressed[pygame.K_UP]: if char.y != 279: movement.y += speed # If the LEFT key is pressed, move the player to the left if pressed[pygame.K_LEFT] and not pressed[pygame.K_RIGHT]: if char.x != minimum_x and not unlocked: movement.x -= speed # If the RIGHT key is pressed, move the player to the right if pressed[pygame.K_RIGHT] and not pressed[pygame.K_LEFT]: if char.x != 693: movement.x += speed if movement.x != 0 or movement.y != 0: moved = char.move(movement.x, movement.y) if moved.collidelist(fences) == -1: char = moved
or
speed = 3 movement = pygame.Vector2(0, 0) # If the UP key is pressed, move the player upwards if pressed[pygame.K_UP] and not pressed[pygame.K_DOWN]: movement.y -= speed # If the DOWN key is pressed, move the player downwards if pressed[pygame.K_DOWN] and not pressed[pygame.K_UP]: movement.y += speed # If the LEFT key is pressed, move the player to the left if pressed[pygame.K_LEFT] and not pressed[pygame.K_RIGHT]: movement.x -= speed # If the RIGHT key is pressed, move the player to the right if pressed[pygame.K_RIGHT] and not pressed[pygame.K_LEFT]: movement.x += speed if movement.x != 0 or movement.y != 0: # Deflate. Where 3 pixels away from edge rect = screen.get_rect().inflate(-6, -6) moved = char.move(movement.x, movement.y) if moved.collidelist(fences) == -1 and rect.contains(moved): char = moved

It still doesn't seem to work for me for some reason.

# Allows the usage of the PyGame library
import pygame

# Initializes PyGame
pygame.init()

# RGB Colors
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)

# Bad Coordinates (Fence)
# bad_coordinates = bad_x, bad_y = range(447, 528), 150

# Barrier
minimum_x = 342

# Initializes the window's title, width, and height
screen = pygame.display.set_mode((720, 320))
pygame.display.set_caption("New Game")
# Loads the background image
farm_image = pygame.image.load("farm_sprite.png").convert()
# Fence Rectangles
fences = (
    pygame.Rect(455, 65, 20, 85),
    pygame.Rect(390, 65, 85, 20),
    pygame.Rect(390, 0, 20, 85),
    pygame.Rect(395, 0, 240, 20),
    pygame.Rect(615, 0, 20, 150),
    pygame.Rect(580, 130, 40, 20),
    pygame.Rect(455, 130, 80, 20)
)

# Draw the player object onto the screen
char = pygame.Rect(507, 60, 25, 40)

# Keeps the while loop running
done = False

# Boolean to identify whether the player has unlocked the currently locked area
unlocked = False

# Creates a clock object to keep track of time
clock = pygame.time.Clock()

# Keeps the program running
while not done:

    moved = None

    # Allows the user to exit by pressing the X button without throwing an error
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    # Assigns a list of the possible pressed keys to a variable
    pressed = pygame.key.get_pressed()

    speed = 3
    movement = pygame.Vector2(0, 0)
    # If the UP key is pressed, move the player upwards
    if pressed[pygame.K_UP] and not pressed[pygame.K_DOWN]:
        movement.y -= speed

    # If the DOWN key is pressed, move the player downwards
    if pressed[pygame.K_DOWN] and not pressed[pygame.K_UP]:
        movement.y += speed

    # If the LEFT key is pressed, move the player to the left
    if pressed[pygame.K_LEFT] and not pressed[pygame.K_RIGHT]:
        movement.x -= speed

    # If the RIGHT key is pressed, move the player to the right
    if pressed[pygame.K_RIGHT] and not pressed[pygame.K_LEFT]:
        movement.x += speed

    if movement.x != 0 or movement.y != 0:
        # Deflate. Where 3 pixels away from edge
        rect = screen.get_rect().inflate(-6, -6)
        moved = char.move(movement.x, movement.y)
        if moved.collidelist(fences) == -1 and rect.contains(moved):
            char = moved

    # Place the background image on the window
    screen.blit(farm_image, [0, 0])

    # Puts the fences on the screen
    for fence in fences:
        pygame.draw.rect(screen, pygame.Color('red'), fence)

    pygame.draw.rect(screen, pygame.Color('red'), char)

    # Update the full Surface to the screen
    pygame.display.flip()

    # Run the program at 60 frames per second
    clock.tick(60)
Reply
#10
If you get any errors. Copy and paste them. Code below fully tested. It works.
# Allows the usage of the PyGame library
import pygame

# Initializes all PyGame modules
pygame.init()

# Barrier
minimum_x = 342

# Initializes the window's title, width, and height
pygame.display.set_caption("Farm Game")
screen = pygame.display.set_mode((720, 320))
# Loads the background image
farm_image = pygame.image.load("farm_sprite.png").convert()
# Fence Rectangles
fences = (
    pygame.Rect(455, 65, 20, 85),
    pygame.Rect(390, 65, 85, 20),
    pygame.Rect(390, 0, 20, 85),
    pygame.Rect(395, 0, 240, 20),
    pygame.Rect(615, 0, 20, 150),
    pygame.Rect(580, 130, 40, 20),
    pygame.Rect(455, 130, 80, 20)
)

# player coords
char = pygame.Rect(507, 60, 25, 40)

# Keeps the while loop running
done = False

# Boolean to identify whether the player has unlocked the currently locked area
unlocked = False

# Creates a clock object to keep track of time
clock = pygame.time.Clock()

# Keeps the program running
while not done:
    # Allows the user to exit by pressing the X button without throwing an error
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    #       Logic Area

    # Assigns a list of the possible pressed keys to a variable
    pressed = pygame.key.get_pressed()

    speed = 3
    movement = pygame.Vector2(0, 0)
    # If the UP key is pressed, move the player upwards
    if pressed[pygame.K_UP] and not pressed[pygame.K_DOWN]:
        movement.y -= speed

    # If the DOWN key is pressed, move the player downwards
    if pressed[pygame.K_DOWN] and not pressed[pygame.K_UP]:
        movement.y += speed

    # If the LEFT key is pressed, move the player to the left
    if pressed[pygame.K_LEFT] and not pressed[pygame.K_RIGHT]:
        movement.x -= speed

    # If the RIGHT key is pressed, move the player to the right
    if pressed[pygame.K_RIGHT] and not pressed[pygame.K_LEFT]:
        movement.x += speed

    if movement.x != 0 or movement.y != 0:
        # Deflate. Where 3 pixels away from edge
        rect = screen.get_rect().inflate(-6, -6)
        moved = char.move(movement.x, movement.y)
        if moved.collidelist(fences) == -1 and rect.contains(moved):
            char = moved

    # Draw Area
    # Place the background image on the window
    screen.blit(farm_image, (0, 0))

    # Puts the fences on the screen
    for fence in fences:
        pygame.draw.rect(screen, pygame.Color('red'), fence)

    pygame.draw.rect(screen, pygame.Color('red'), char)

    # Update the full Surface to the screen
    pygame.display.flip()

    # Run the program at 60 frames per second
    clock.tick(60)
99 percent of computer problems exists between chair and keyboard.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020