AttributeError: 'Hero' object has no attribute 'image_getrect' - python

So I am learning to code on python with pygame. I am currently following a series of video tutorials for coding games.
I have followed the tutors code to the letter and checked and double checked (to the point of even checking his base code file.
But when I try to run the game I get this error:
File "/home/dev/PycharmProjects/Game5_Catch_Cookie/modules/hero.py", line 16, in init
self.rect = self.image_getrect()
so line 16 in the hero class set up code looks like:
class Hero(pygame.sprite.Sprite):
def __init__(self, images, position=[375, 520], **kwargs):
pygame.sprite.Sprite.__init__(self)
self.images_right = images[:5]
self.images_left = images[5:]
self.images = self.images_right.copy()
self.image = self.images[0]
self.mask = pygame.mask.from_surface(self.image)
self.rect = self.image_getrect() <------------- Line 16
self.rect.left, self.rect.top = position
self.direction = 'right'
self.speed = 8
self.switch_frame_count = 0
self.switch_frame_freq = 1
self.frame_index =0
I'm not sure what to do about this or how to fix it so the game I'm trying to learn to code works properly.

Instead of
self.rect = self.image_getrect()
You need to write
self.rect = self.image.get_rect()

Related

How do I move variables between Classes and functions without them changing?

I am fairly new to OOP and pygame, so these may be some stupid and basic questions - but I've been stuck on this for days so anything would help.
I am creating a variable called position3 within Gun.shoot(), I want this variable to move to Bullet.reposition() as Bullet.reposition is called upon. I then want the position3 variable to move to the Bullet.update() function, which gets called upon by a different process elsewhere in the code. During this whole process, the position3 variable should not change but should stay the same. I have managed to get the position3 variable to move to Bullet.reposition() from Gun.shoot(), however I can now not get it into Bullet.update(). Help!
class Bullet(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((5,5))
self.image.fill(red)
self.rect = self.image.get_rect()
# self.rect.center = (200,200)
self.positionofm = (23,0)
self.pos = vec(300,300)
self.centerlocation = vec(0,0)
self.position3 = vec(0,0)
def update(self):
self.position3 = reposition.position3
print("update",self.position3)
# self.rect.center = self.position3
self.centerlocation = random.randint(200,400),random.randint(200,400)
self.rect.center =(self.centerlocation)
def reposition(self,position3):
print("repositioning")
self.centerlocation = random.randint(200,400),random.randint(200,400)
self.rect.move(position3)
print("regular",position3)
self.position3 = position3
print("First update",self.position3)
class Gun(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((30,5), pg.SRCALPHA)
self.image.fill(black)
self.rect = self.image.get_rect()
self.original_image = self.image
self.rect.center = (WIDTH/2 , HEIGHT/2)
self.pos = vec(WIDTH / 2, HEIGHT / 2)
self.offset = vec(20, 0)
self.angle=0
self.position2=vec(0,0)
# self.bullet = Bullet()
def shoot(self):
self.BulletEndPos=vec(0,0)
self.BulletEndPos=vec(pg.mouse.get_pos())
# print(self.BulletEndPos,"akshgdjasgdas")
position2x=self.position2[0]
position2y=self.position2[1]
position3=vec(0,0)
position3=(math.floor(position2x)),(math.floor(position2y))
Bullet.reposition(self, position3)
Well your code snippet already has everything you need there you just need to remove the line
self.position3 = reposition.position3
Given that reposition is not an object and will not hold a attribute
The value for position3 is already updated for the object on the reposition method and written in the Bullet object attribute. Another way you could do it would be to rewrite update() somewhat like this:
def update(self, position3= None):
position_3 = position3 if position3 is not None else self.position3
print("update",position_3)
# self.rect.center = position_3
self.centerlocation = random.randint(200,400),random.randint(200,400)
self.rect.center =(self.centerlocation)
This gives you more freedom to pass position3 somewhere else in the code if needed while retaining the logic.
Now just to clarify a few things:
When you write a class you are just declaring the overall structure of the class and not creating any instance of it.
The self keyword refers to the referred instance of the class object, so you need to create an instance of the object that can keep those variables.
Keeping that in mind on your last line of method shoot you are doing nothing, has there is no bullet created to be repositioned and updated. So you kinda need to change your Gun class to this:
class Gun(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((30,5), pg.SRCALPHA)
self.image.fill(black)
self.rect = self.image.get_rect()
self.original_image = self.image
self.rect.center = (WIDTH/2 , HEIGHT/2)
self.pos = vec(WIDTH / 2, HEIGHT / 2)
self.offset = vec(20, 0)
self.angle=0
self.position2=vec(0,0)
self.bullet = Bullet()
def shoot(self):
self.BulletEndPos=vec(0,0)
self.BulletEndPos=vec(pg.mouse.get_pos())
# print(self.BulletEndPos,"akshgdjasgdas")
position2x=self.position2[0]
position2y=self.position2[1]
position3=vec(0,0)
position3=(math.floor(position2x)),(math.floor(position2y))
self.bullet.reposition(self, position3)
OOP might be confusing at times especially at the beginning so you can try some other resources online (e.g. https://www.tutorialspoint.com/python3/python_classes_objects.htm)

AttributeError: 'class' object has no attribute 'rect'

I have this class:
class Comet(pygame.sprite.Sprite):
def ___init___(self):
super().__init__()
self.image = pygame.Surface((100,250))
self.image.fill(cometL)
self.rect = self.image.get_rect()
self.rect.y = 800
self.rect.x = 100
def update(self):
self.rect.y -= 1+2*speed
def reset(self):
self.rect.x = randint(0,700)
self.rect.y = randint(1000,2000)
I try to use it here:
comet1 = Comet()
comet1.rect.x = 100
comet1.rect.y = 800
comets.add(comet1)
But when i do I get this error:
File "", line 36, in
comet1.rect.x = 100
AttributeError: 'comet' object has no attribute 'rect'
Even though the class does (I think, i'm kinda new to classes)
Your definition for __init__ is wrong. You used three underscores (___init___), so this function is not called during instantiation of the class.
This means that the line self.rect = self.image.get_rect() isn't called and so there is no rect attribute.

How to define and play sound effects within the class

This is a the class of a sprite that goes left and right on the screen, when it hits the boundaries, it makes a "boing" sound and goes the opposite direction, everything works perfectly fine except for there is no boing sound when it hits the edge
class MySprite(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("vegetables.gif")
self.image = self.image.convert()
self.rect = self.image.get_rect()
self.rect.left = 0
self.rect.top = 167
self.__direction = 10
def update(self):
self.rect.left += self.__direction
sound = pygame.mixer.Sound("Bounce.mp3")
sound.set_volume(0.5)
if (self.rect.left < 0) or (self.rect.right > screen.get_width()):
sound.play()
self.__direction = -self.__direction
If you want the class to play its own sound, just load it like any attribute on __init__.
class MySprite(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("vegetables.gif")
self.image = self.image.convert()
self.sound = pygame.mixer.Sound("Bounce.mp3") #like this
self.rect = self.image.get_rect()
self.rect.left = 0
self.rect.top = 167
self.__direction = 10
Then whenever it's correct to do so, just call self.sound.play().
def update(self):
self.rect.left += self.__direction
if (self.rect.left < 0) or (self.rect.right > screen.get_width()):
self.sound.play() #as seen here
self.__direction = -self.__direction
For whatever it's worth - if you're going to do it in this way (have the sprite play its own sounds, etc), I would recommend loading them beforehand and then passing them as arguments (perhaps default arguments to avoid errors), such that each instance of the class might call a unique sound if need be.
So in your code prior to these classes, one could do something like:
JumpSound = pygame.Mixer.Sound("jump.wav")
BonkSound = pygame.Mixer.Sound("bonk.wav")
#etc etc etc...
...and then later on, pass the sounds as arguments:
class MySprite(pygame.sprite.Sprite):
def __init__(self, jumpsound, bonksound):
#...your other code precedes...
self.jumpsound = jumpsound
self.bonksound = bonksound
#...your other code continues...
myHero = MySprite(JumpSound, BonkSound)
The names are a little bit lousy b/c they are the same barring the CamelCasing, but forgetting that, this is probably a much cleaner approach. You can set your volume on the sounds way before they are passed into the sprites, along with whatever other changes you feel are necessary before the sprite gets ahold of them.

self.rect not found?

I have a program that is simply made to move an image around. I try to state the self.rect as part of a load_png() call, but it simply does not like it. THe reason I think this will work is from http://www.pygame.org/docs/tut/tom/games6.html, saying that this should work:
def __init__(self, side):
pygame.sprite.Sprite.__init__(self)
self.image, self.rect = load_png('bat.png')
screen = pygame.display.get_surface()
self.area = screen.get_rect()
self.side = side
self.speed = 10
self.state = "still"
self.reinit()
Here is my code, which according to the pygame tutorial from its own website, should work:
def _init_(self):
pygame.sprite.Sprite._init_(self)
self.state = 'still'
self.image = pygame.image.load('goodGuy.png')
self.rect = self.image.get_rect()
screen = pygame.display.getSurface()
And it gives me this error:
Traceback (most recent call last):
File "C:\Python25\RPG.py", line 37, in <module>
screen.blit(screen, Guy.rect, Guy.rect)
AttributeError: 'goodGuy' object has no attribute 'rect'
If you guys need all of my code, comment blew and I will edit it.
You don't have a load_png function defined.
You need to create the pygame image object before you can access its rect property.
self.image = pygame.image.load(file)
Then you can assign the rect value using
self.rect = self.image.get_rect()
Or you could create the load_png function as per the example you linked.
There is no load_png function built-in to python or pygame. I imagine that the tutorial you are referring to defined it manually somewhere. What you want is pygame.image.load(filename) and then you can call get_rect() on the returned Surface object. The complete code would be as follows:
self.image = pygame.image.load('bat.png')
self.rect = self.image.get_rect()
Your second problem is that you've defined the function _init_, but you need double underscores: __init__.
Also, you need to post the code where the error is actually occurring.

Trying to create a group of button sprites

Good day,
I have like 15 images I need to be buttons. I have buttons working with a Box() (Box - looks like this)
class Box(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((35, 30))
self.image = self.image.convert()
self.image.fill((255, 0, 0))
self.rect = self.image.get_rect()
self.rect.centerx = 25
self.rect.centery = 505
self.dx = 10
self.dy = 10
I am trying to make the buttons work with image sprites. So I attempted to copy the class style of the box and do the same for my Icons.. code looks like this...
class Icons(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("images/airbrushIC.gif").convert()
self.rect = self.image.get_rect()
self.rect.x = 25
self.rect.y = 550
the code in the main()
rect = image.get_rect()
rect.x = 25
rect.y = 550
ic1 = Icons((screen.get_rect().x, screen.get_rect().y))
screen.blit(ic1.image, ic1.rect)
pygame.display.update()
This code produces a positional (accepts 1 argument but 2 are there) error or an image is not referenced error (inside the Icon class).
I'm unsure if this is the right way to go about this anyways.. I know for sure that I need to load all the images (as sprites)... store them in an array... and then have my mouse check if it is clicking one of the items in the array using a for loop.
Thanks.
You are trying to pass an argument into Icons(), but your __init__() method takes no arguments. If you wanted to pass those onto the Sprite() constructor, then you probably wanted something like:
class Icons(pygame.sprite.Sprite):
def __init__(self, *args):
pygame.sprite.Sprite.__init__(self, *args)
...
This accepts any number of extra arguments (*args) using the star operator, then passes them into the sprite constructor.

Categories

Resources