0
\$\begingroup\$

I'm making my first game of Pygame. I'm going to create groups for making collisions but when I add an object to the group, I get an error in sprite.py (Pygame's Files)

AttributeError: 'pygame.Surface' object has no attribute 'add_internal' 

Why I get this error?
There is a simplest way to make collisions?

There is my code:

import pygame from pygame.locals import * import sys import os import time width = 950 height = 500 Game = False GameOver = False keyboard = pygame.key.get_pressed()[K_UP] def main(): pygame.init() screen = pygame.display.set_mode((width, height)) pygame.display.set_caption('Flappy Dog') background = pygame.image.load(os.path.join("Images", "Background_00.png")).convert() FlappyDog = pygame.image.load(os.path.join("Images", "Flappy.png")).convert_alpha() Play = pygame.image.load(os.path.join("Images", "Play.png")).convert_alpha() Dog0 = pygame.image.load(os.path.join("Images", "Dog0.png")).convert_alpha() Dog1 = pygame.image.load(os.path.join("Images", "Dog1.png")).convert_alpha() SpikeUp0 = pygame.image.load(os.path.join("Images", "SpikeUp0.png")).convert_alpha() SpikeUp1 = pygame.image.load(os.path.join("Images", "SpikeUp1.png")).convert_alpha() SpikeDown0 = pygame.image.load(os.path.join("Images", "SpikeDown0.png")).convert_alpha() SpikeDown1 = pygame.image.load(os.path.join("Images", "SpikeDown1.png")).convert_alpha() GameOver = pygame.image.load(os.path.join("Images", "Game-Over.png")).convert_alpha() Replay = pygame.image.load(os.path.join("Images", "Replay.png")).convert_alpha() Bone = pygame.image.load(os.path.join("Images", "Bone.png")).convert_alpha() Game = True Dog1_pos_x = 100 Dog1_pos_y = 100 screen.blit(background, (0, 0)) screen.blit(FlappyDog, (0, 0)) screen.blit(Bone, (550, 100)) screen.blit(Play, (600, 350)) screen.blit(Dog0, (5, 240)) bones = pygame.sprite.Group() bones.add(Bone) # <-- Error here Dog = pygame.sprite.Group() Dog.add(Dog1) pygame.display.update() while True: if GameOver == true: screen.blit(background, (0, 0)) screen.blit(GameOver, (20, 50)) if pygame.sprite.gropucollide(Dog, Bones, True, True): Game = False GameOver = True while Game == True: pygame.event.pump() if pygame.key.get_pressed()[K_UP]: for i in range(10): # Up Dog1_pos_y = Dog1_pos_y -1 screen.blit(background, (0, 0)) screen.blit(Dog1, (Dog1_pos_x, Dog1_pos_y)) screen.blit(SpikeDown0, (0, 436)) screen.blit(SpikeUp0, (0, 0)) pygame.display.update() pygame.time.delay(1) else: # Down Dog1_pos_y = Dog1_pos_y +1 screen.blit(background, (0, 0)) screen.blit(Dog1, (Dog1_pos_x, Dog1_pos_y)) screen.blit(SpikeDown0, (0, 436)) screen.blit(SpikeUp0, (0, 0)) pygame.display.update() pygame.time.delay(1) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() pygame.display.update() if __name__ == "__main__": main() 
\$\endgroup\$
5
  • \$\begingroup\$ Did you search for existing Q&A discussing similar errors? How have you tried applying these existing answers to your case? \$\endgroup\$ Commented Mar 18, 2019 at 18:42
  • \$\begingroup\$ Yes, In the first URL, in the code that is "fine", i'ts exactly the same, only that change the object name. I don't know why I obtain the error. \$\endgroup\$ Commented Mar 18, 2019 at 19:50
  • \$\begingroup\$ So, like in the answer at the first link, you tried creating a Sprite object to add each image to, then add your sprites to the group? Where did this go wrong for you? \$\endgroup\$ Commented Mar 18, 2019 at 20:01
  • \$\begingroup\$ I dont know. Pygame says that the error is here bonesSpikes.add (SpikeDown0) and in a pygame file (Sprite.py) \$\endgroup\$ Commented Mar 18, 2019 at 20:26
  • \$\begingroup\$ Right, because SpikeDown0 is a Surface, and you're trying to add it to a group made to contain Sprite objects. Did you follow the linked answer and try something like SpikeDown0Sprite = pygame.sprite.Sprite() SpikeDown0Sprite.image = SpikeDown0 ... boneSpikes.add(SpikeDown0Sprite)? \$\endgroup\$ Commented Mar 18, 2019 at 21:31

1 Answer 1

0
\$\begingroup\$

Programming languages like Python have types, which determine what you can do with which piece of data. Using each variable in a way that's appropriate to its type is like putting a round peg in a round hole, or a square peg into a square hole.

When you try to do an operation that expects one type, but you give it a different, incompatible type, that's trying to shove a square peg into a round hole. The computer won't be able to make sense of the operation and it will throw an error.

That's what you have happening here. bones = pygame.sprite.Group() tells the computer "bones is a group that holds Sprite objects" (ie. it's a round hole to put round pegs into)

Bone = pygame.image.load(os.path.join("Images", "Bone.png")).convert_alpha() tells the computer "Bone is a Surface object loaded from an image like so..." (ie. it's a square peg to put into a square hole)

bones.add(Bone) says "take that square peg (Surface) and shove it into that round hole (group of Sprite objects)"

So the computer errors-out and tells you that the Bone variable's type, pygame.Surface, does not have the shape that the bones variable's type, pygame.sprite.Group needs for its add method. It wants a Sprite that has an add_internal attribute, but you gave it a Surface which doesn't have that attribute.

AttributeError: 'pygame.Surface' object has no attribute 'add_internal'

So, first you need to make Sprite objects from the Surface objects you loaded from your images - think of it like an adapter to turn the square peg into a round peg - like so:

boneSprite = pygame.sprite.Sprite() boneSprite.image = Bone boneSprite.rect = Bone.get_rect() 

Now that you have a Sprite that uses the Bone image, you can add it to your group like so:

bones.add(boneSprite) 

This will not generate errors, because we're putting a round peg into a round hole now.

As described in the comments, this is all explained in existing answers, so please take the time to search for existing documentation and read it thoroughly to solve your problems faster in future.

\$\endgroup\$
6
  • \$\begingroup\$ Ok, thanks. But now says that 'Sprite' Object has no attribute 'get_rect' \$\endgroup\$ Commented Mar 24, 2019 at 16:40
  • \$\begingroup\$ What exact line is throwing the error? \$\endgroup\$ Commented Mar 24, 2019 at 16:43
  • \$\begingroup\$ The line that produces the error is Bone.rect = Bone.image.get_rect() \$\endgroup\$ Commented Mar 24, 2019 at 16:50
  • \$\begingroup\$ You're mixing types again. See how the object on the left in my example is called boneSprite? That's to help you keep track of the fact that it's a sprite, not the original Bone surface. You want something that looks like (some Sprite).rect = (some Surface).get_rect(). See how the object on the left and object on the right are two different types? So you can't use the same Bone variable in both places. \$\endgroup\$ Commented Mar 24, 2019 at 16:53
  • \$\begingroup\$ Ok, but now how can I blit it to the screen. Because says that I can't blit and sprite. Sorry for inconvenences \$\endgroup\$ Commented Mar 24, 2019 at 17:02

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.