Python Forum
[PyGame] Pygame is treating blob_group as a surface, when I need it to treat it as a Sprite.
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] Pygame is treating blob_group as a surface, when I need it to treat it as a Sprite.
#1
Hey all, I'm following along a pygame tutorial for a platforming game and have been stuck on this for a while now. I made sure to do exactly as the tutorial said and went over it many times. For some reason, my pygame keeps treating blob_group as a Surface object. I'm not sure why now, I have tried making blob_group a global, have checked for NameErrors, and tried moving around some lines of code. I've left below the error that I get returned to me, and the code that I have written so far.

import pygame
from pygame.locals import *

pygame.init()

screen_width = 400
screen_height = 400
tile_size = 20

clock = pygame.time.Clock()
fps = 60

screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Platformer')

#load images
bg_img = pygame.image.load("C:\img/sky.png")
blob_group = pygame.image.load("C:\img/blob.png")

class Player():
    def __init__(self, x, y):
        self.images_right = []
        self.images_left = []
        self.index = 0
        self.counter = 0
        for num in range(1, 3):
            img_right = pygame.image.load(f'C:\img/Man{num}.png')
            img_right = pygame.transform.scale(img_right, (20, 40))
            img_left = pygame.transform.flip(img_right, True, False)
            self.images_right.append(img_right)
            self.images_left.append(img_left)
        self.image = self.images_right[self.index]
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.width = self.image.get_width()
        self.height = self.image.get_height()
        self.vel_y = 0
        self.jumped = False
        self.direction = 0

    def update(self):
        dx = 0
        dy = 0
        walk_cooldown = 20

        #get keypresses
        key = pygame.key.get_pressed()
        if key[K_LEFT]:
            dx -= 2
            self.counter += 1
            self.direction = -1
        if key[K_SPACE] and self.jumped == False:
            self.vel_y = -15
            self.jumped = True
        if key[K_SPACE] == False:
            self.jumped = False
        if key[K_RIGHT]:
            dx += 2
            self.counter += 1
            self.direction = 1
        if key[K_LEFT] == False and key[K_RIGHT] == False:
            self.counter = 0
            self.index = 0
            if self.direction == 1:
                self.image = self.images_right[self.index]
            if self.direction == -1:
                self.image = self.images_left[self.index]

        #handle animation
        if self.counter > walk_cooldown:
            self.counter = 0
            self.index += 1
            if self.index >= len(self.images_right):
                self.index = 0
            if self.direction == 1:
                self.image = self.images_right[self.index]
            if self.direction == -1:
                self.image = self.images_left[self.index]

        #add gravity
        self.vel_y += 1
        if self.vel_y > 10:
            self.vel_y = 10
        dy += self.vel_y

        #check for collision
        for tile in world.tile_list:
            #check for collision in x direction
            if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height):
                dx = 0
            #check for collision in y direction
            if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height):
                #check if below the ground i.e. jumping
                if self.vel_y < 0:
                    dy = tile[1].bottom - self.rect.top
                    self.vel_y = 0
                #check if above the ground i.e. falling
                elif self.vel_y >= 0:
                    dy = tile[1].top - self.rect.bottom
                    self.vel_y = 0

        #update player coordinates
        self.rect.x += dx
        self.rect.y += dy

        if self.rect.bottom > screen_height:
            self.rect.bottom = screen_height
            dy = 0

        #draw player onto screen
        screen.blit(self.image, self.rect)
        pygame.draw.rect(screen, (255, 255, 255), self.rect, 1)

class World():
    def __init__ (self, data):
        self.tile_list = []

        #load images
        dirt_img = pygame.image.load("C:\img/dirt.png")
        grass_img = pygame.image.load("C:\img/grass.png")

        row_count = 0
        for row in data:
            col_count = 0
            for tile in row:
                if tile == 1:
                    img = pygame.transform.scale(dirt_img, (tile_size, tile_size))
                    img_rect = img.get_rect()
                    img_rect.x = col_count * tile_size
                    img_rect.y = row_count * tile_size
                    tile = (img, img_rect)
                    self.tile_list.append(tile)
                if tile == 2:
                    img = pygame.transform.scale(grass_img, (tile_size, tile_size))
                    img_rect = img.get_rect()
                    img_rect.x = col_count * tile_size
                    img_rect.y = row_count * tile_size
                    tile = (img, img_rect)
                    self.tile_list.append(tile)
                if tile == 3:
                    blob = Enemy(col_count * tile_size, row_count * tile_size + 15)
                    blob_group.add(blob)
                col_count += 1
            row_count += 1

    def draw(self):
        for tile in self.tile_list:
            screen.blit(tile[0], tile[1])
            pygame.draw.rect(screen, (255, 255, 255), tile[1], 1)


class Enemy(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("C:\img/blob.png")
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

world_data = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 2, 0, 2, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 1, 2, 1],
[1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
]

player = Player(20, screen_height -40)
world = World(world_data)

blob_group = pygame.sprite.Group()

run = True
while run:

    clock.tick(fps)

    screen.blit(bg_img, (0, 0))

    world.draw()

    blob_group.update()
    blob_group.draw(screen)

    player.update()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    pygame.display.update()

pygame.quit
The code above will produce the following feedback error:

Error:
line 145, in __init__ blob_group.add(blob) AttributeError: 'pygame.Surface' object has no attribute 'add'
This has been bugging me for a couple days now. So any and all help would be appreciated. Thanks.
Reply
#2
Line 18 you assign it to a loaded pygame image, which is a surface. Then you define your World class, and then call the world class. But right after that one line 187 you redefine it to a group. You should have this defined before World class definition.

You shouldn't use the same variable and change it mid program to some other object.
Recommended Tutorials:
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [PyGame] Surface and rectangle in pygame Fabrizio_fg 6 2,307 May-27-2023, 09:15 AM
Last Post: Fabrizio_fg
  [PyGame] Sprites just randomly appear and dissapear in my pygame.sprite.GoupeSingle trueShadoWrr 2 1,979 Feb-13-2023, 09:34 AM
Last Post: Vadanane
  Coloring a surface with transparency Sandor 4 2,313 Jan-02-2022, 08:11 AM
Last Post: Sandor
  Drawn line shift when that surface is copied to another in pygame Leo_Red 4 3,342 Feb-11-2021, 06:33 AM
Last Post: Leo_Red
  FileNotFoundError when I try putting sprite in Pygame zionkozisek 9 16,099 Dec-09-2020, 04:42 AM
Last Post: zionkozisek
  [PyGame] My Pygame Sprite not appearing... noodlespinbot 3 3,831 Oct-30-2020, 06:51 AM
Last Post: robinmurphy
  My Pygame Sprite not appearing... noodlespinbot 1 2,264 Apr-08-2020, 11:25 AM
Last Post: pyzyx3qwerty
  [PyGame] Sprite image.get_rect() moves sprite to 0, 0 michael1789 2 4,600 Dec-13-2019, 08:37 PM
Last Post: michael1789
  [PyGame] pygame.Surface.fill help Shemira 3 6,192 Nov-29-2019, 12:01 AM
Last Post: Shemira
  Pygame sprite not moving michael1789 1 2,832 Nov-10-2019, 03:54 AM
Last Post: michael1789

Forum Jump:

User Panel Messages

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