Platfromer on pygame: string has no attribute 'get_rect' while trying to make border for game

Viewed 36

I'm quite new to pygame and am currently doing a school project. My problem is that i have been attempting to create a border for my game so my charectar cant go out from the screen.

Heres my code so far:

# This imports the Pygame Module / loads pygame keywords
import pygame
# This lets python use my file system
import sys
# This helps python identify my OS, which is Windows 10
import os

"""
Variables
"""
img = 'PlayerSprite1'
# This is the basic set screen width and height / 320x320 pixels
worldx = 1271
worldy = 957
world = pygame.display.set_mode([worldx, worldy])

# This is for the frame rate and animation cycles, in order
fps = 30
ani = 4

# These are the color definitions - Red, Green, Blue (RGB)
RED = (0, 0, 0)
GREEN = (128, 128, 128)
BLUE = (128, 128, 128)

# This is used in order to make the sprites color block be 'invisible', in order for it to blend into the background
ALPHA = (00, 00, 00)
ALPHA1 = (255, 255, 255)

"""
Objects
"""

'Individual sprite classes:  '


class Player(pygame.sprite.Sprite):

    # Spawn the player's sprite/ character/ main player's sprite
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        # These variables will be to track frames and movements
        self.movex = 0  # This is to monitor movement along X
        self.movey = 0  # This is to monitor movement along Y
        self.frame = 0  # This counts frames
        self.health = 10  # This counts health
        self.images = []
        for i in range(1, 5):
            # This loads the image from the selected directory in the pycharm folder
            img = pygame.image.load(os.path.join('images', 'PlayerSprite1' + str(i) + '.png')).convert()
            img.convert_alpha()  # This is used to optimize alpha
            img.set_colorkey(ALPHA)  # This is used to set alpha
            self.images.append(img)
            self.image = self.images[0]
            self.rect = self.image.get_rect()

    # This controls the players sprites movement
    def control(self, x, y):
        self.movex += x
        self.movey += y

    # This updates the sprites position, by redefining its position, designated by self.rect.x and self.rect.y,
    # to its current position plus whatever amount movex or movey is
    def update(self):
        self.rect.x = self.rect.x + self.movex
        self.rect.y = self.rect.y + self.movey

        # This is for moving left
        if self.movex < 0:
            self.frame += 1
            if self.frame > 3 * ani:
                self.frame = 0
            self.image = self.images[self.frame // ani]
            hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
            for enemy in hit_list:
                self.health -= 1
                print(self.health)

        # This is for moving right
        if self.movex > 0:
            self.frame += 1
            if self.frame > 3 * ani:
                self.frame = 0
            self.image = self.images[self.frame // ani]


# This class is for the main antagonistic sprite in opposition to players sprite
class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        # These variables will be to track frames and movements
        self.movex = 0  # This is to monitor movement along X
        self.movey = 0  # This is to monitor movement along Y
        self.frame = 0  # This counts frames
        self.images = []
        self.counter = 0
        for i in range(1, 4):
            # This loads the image from the selected directory in the pycharm folder
            img = pygame.image.load(os.path.join('images', 'antagonist' + str(i) + '.png')).convert()
            img.convert_alpha()  # This is used to optimize alpha
            img.set_colorkey(ALPHA1)  # This is used to set alpha
            self.images.append(img)
            self.image = self.images[0]
            self.rect = self.image.get_rect()
            # This is to alter the scale of this sprite in order for it to fit into the overall pixel scale of the game
            # THIS IS NOT YET DONE, DO ASAP
            pygame.transform.scale(pygame.image.load(os.path.join('images', 'antagonist' + str(i) + '.png')), (13, 29))

    def move(self):
        distance = 80
        speed = 8

        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


'These classes are for levels:  '


# This class is for level one of the game ( NOT YET DONE )
class Level():
    def bad(lvl, eloc):
        if lvl == 1:
            enemy = Enemy()
            eloc = 0
            eloc = 1
            img = 'antagonist1.png'
            enemy_list = pygame.sprite.Group()
            enemy_list.add(enemy)
        if lvl == 2:
            print("Level " + str(lvl))

        return enemy_list


'These classes are for Platforms'





"""
Setup
"""
# This creates the boundaries for the sprite so it dosnt go outside the borders


# This is used for various loops, mainly for keeping the main loop, in loop
main = True

# This is for the internal clock and for pygame to initialize
clock = pygame.time.Clock()
pygame.init()

# This is to set up the Main background
backdrop = pygame.image.load(os.path.join('images', 'Main Background.jpg'))
backdropbox = world.get_rect()



# This is to bring the actual '123' sprite into the game, or the 'game world'
player = Player()  # This spawns player's sprite
player.rect.x = 10  # go to x
player.rect.y = 12  # go to y
player_list = pygame.sprite.Group()
player_list.add(player)
steps = 10  # This is how many pixels the sprite will move


# This is to add the Main antagonistic enemy sprite into the 'actual' game and further create a 'group' for a sort of
# wave, which will be a core mechanic of the game
enemy = Enemy()  # This spawns the antagonist
enemy.rect.x = 10
enemy.rect.y = 12
enemy_list = pygame.sprite.Group()  # This creates the antagonist group
enemy_list.add(enemy)  # This adds the antagonist to the group

eloc = []
eloc = [300, 0]
enemy_list = Level.bad(1, eloc)

"""
Main Loop
"""
# This is to make sure the background does not just appear for a singular millisecond
world.blit(backdrop, backdropbox)
player.update()  # This updates the players position to make the character move from pixel to pixel, making it appear
# as it is moving

# This, similar to the above is to make sure the player's sprite does not just appear for a singular millisecond
player_list.draw(world)  # draw player
enemy_list.draw(world)  # refresh enemies
pygame.display.flip()
clock.tick(fps)

# This is the main loop, which keeps the game's execution in a loop, in order to keep it on the screen and operating
# for longer then a couple milliseconds
while main:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            try:
                sys.exit()
            finally:
                main = False

        # These next two sections add keybindings, this time being changed by replacing the print statements with the
        # player's sprite name, including the .control function, and how many steps to move with each loop
        if event.type == pygame.KEYDOWN:
            if event.key == ord('q'):
                pygame.quit()
                try:
                    sys.exit()
                finally:
                    main = False
            if event.key == pygame.K_LEFT or event.key == ord('a'):
                player.control(-steps, 0)
            if event.key == pygame.K_RIGHT or event.key == ord('d'):
                player.control(steps, 0)
            if event.key == pygame.K_DOWN or event.key == ord('s'):
                player.control(-steps, 0)
            if event.key == pygame.K_UP or event.key == ord('w'):
                player.control(-steps, 0)

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == ord('a'):
                player.control(steps, 0)
            if event.key == pygame.K_RIGHT or event.key == ord('d'):
                player.control(-steps, 0)
            if event.key == pygame.K_DOWN or event.key == ord('s'):
                player.control(-steps, 0)
            if event.key == pygame.K_UP or event.key == ord('w'):
                player.control(-steps, 0)


        world.blit(backdrop, backdropbox)
        img_rect = img.get_rect(topleft=[100, 200])
        world.blit(img, img_rect)
        player.update()
        player_list.draw(world)
        enemy_list.draw(world)
        for e in enemy_list:
            e.move()
        pygame.display.flip()
        clock.tick(fps)

I know it has somthing to do with classes and localisation of code and ive tried to fix that many times but it never seems to work, either not working once executed or never even executing. If anyone has any suggestions, that would be great! Also apoligies for the very messy and unorganised code, if anyone has any further tips on how i should improve my code, though not neccesary, I'll be in your debt!

1 Answers

To get rid of the error message just out-comment the lines causing it as follows:

    world.blit(backdrop, backdropbox)
    # img_rect = img.get_rect(topleft=[100, 200])
    # world.blit(img, img_rect)
    player.update()

This will do no harm to the game as these lines do nothing else ( if img is an actual pygame image ) as drawing an image to the screen which appears to have no function in the game.

Then see what the code does and how to achieve with it what you want.

With a running code you can investigate its behavior while changing and updating the code and so make further progress.

Another option is to actually display an image if this image was intended to be a border, but for this you need to assign a pygame image to img as follows:

    world.blit(backdrop, backdropbox)
    img = pygame.image.load('border.png').convert()
    img_rect = img.get_rect(topleft=[100, 200])
    world.blit(img, img_rect)
    player.update()

Notice that the player and enemy images will overlay the border.png image as they will be drawn later in the game while main loop. Move the code displaying this image after the code updating the player and enemy if you want the border not to be covered by the player or enemy sprites.

This above is my guess what you are after and hope it helps you to make further progress.

Related