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.
Related
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()
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)
I am trying to make a python library:
There is a class (game) in it is a function that defines a variable (display)
Then there is another class (char) in main, I want to access display in char
How do I do it?
In the past I have tried: self.display, global display, and game.display
class game():
def __init__(self, disp, width, height):
self.display = disp # VARIABLE I WANT TO ACCESS
self.height = height
self.width = width
class sprite():
def __init__(self, size, position, image):
self.image = image
self.size = size
self.rect = self.image.get_rect()
self.rect.x = position[0]
self.rect.y = position[1]
self.x = position[0]
self.y = position[1]
self.collisionDirection = 5
self.hasCollided = False
self.mask = pygame.mask.from_surface(self.image)
self.velocity = 0
def render(self):
self.rect.x = self.x
self.rect.y = self.y
self.mask = pygame.mask.from_surface(self.image)
display.blit(self.image, (self.x, self.y)) # WHERE I WANT TO ACCESS IT
I keep getting AttributeError what can I do?
You can pass the Game instance to another class. For example
# instantiate the game
g = game()
# create an instance of char
c = char(game)
assuming the __init__ of char() looks something like this:
class char():
def __init__(self, game):
# save a reference to the game object as an attribute
self.game = game
# now you can access the game's attributes
print(self.game.display)
Allow that the below example is contrived, and not likely the way you would design pen/paper, but it shows that there are a couple different ways that you can accomplish what you ask.
class Pen:
def __init__(self, thickness, color):
self.thickness = thickness
self.color = color
class Paper:
def __init__(self, pen: Pen):
self.pen = pen
def draw(self):
pen_color = self.pen.color
return pen_color
def draw2(self, pen: Pen):
pen_color = pen.color
return pen_color
red_pin = Pen(2, 'Red')
blue_pin = Pen(1, 'Blue')
paper = Paper(red_pin)
print(paper.draw()) # prints Red
print(paper.draw2(blue_pin)) # prints Blue
class GameObject:
def __init__(self, x=0, y=0, width=0, high=0, imName="", imAlpha=False ):
self.x = x # on screen
self.y = y
self.width = width
self.high = high
self.imageName = imName
self.imageAlpha = imAlpha
self.image
def loadImage(self):
self.image = pygame.image.load(self.imageName)
self.image = pygame.transform.scale(self.image, (self.width, self.high))
if self.imageAlpha == True:
self.image = self.image.convert_alpha()
else:
self.image = self.image.convert()
pygame.init()
player = GameObject(px0, py0, width, high, "player.png", True)
player.loadImage()
Any ideas why I have the following error?
AttributeError: GameObject instance has no attribute 'image'
It's bad practice not to do so, but you don't need to declare object attributes in the constructor (init). When you wrote self.image, it tried accessing an attribute that didn't exist yet.
I'd advise on doing self.image = None until you load it, but removing that line entirely would work as well.
In the last line of __init__, which is called when you define player, you are attempting to access self.image, which does not exist.
I'm trying to make a sprite using pygame, but when I try running the main game loop the error that comes up is
AttributeError: 'Paddle' object has no attribute 'rect'
however, to me it looks like I've already used self.rect = self.paddle.get_rect() so it should mean that I've already initialized it? Here's the code:
import pygame
class Paddle(pygame.sprite.Sprite):
def __init___(self, screen):
pygame.sprite.Sprite.__init__(self)
self.paddle = pygame.Surface((100, 40))
self.paddle = self.paddle.convert()
self.paddle.fill((0, 0, 0))
self.rect = self.paddle.get_rect()
self.rect.left = 200
self.rect.top = 400
self.__screen = screen
self.__dx = 0
def change_direction(self, xy_change):
self.__dx = xy_change[0]
def update(self):
if ((self.rect.left > 0) and (self.__dx > 0)) or ((self.rect.left < self.__screen.get_width()) and (self.__dx < 0)):
self.rect.left -= (self.__dx*5)
Any help is appreciated!
In init you have 3 underscores after the word init, so it is never called, there should be 2 either side of the word init (__init__())