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.
Related
I am trying to make a Towerdefense Game
to check if the Enemy is in the hitcircle of the tower I want to use the function pygame.sprite.collide_mask to find out if they are touching.
This is the output:
AttributeError: 'pygame.mask.Mask' object has no attribute 'add_internal'
How can I make it work? Am I even remotely in the right direction of detecting the collision for the game?
I hope this code can work as much as it needs
import pygame
pygame.init()
class Tower(pygame.sprite.Sprite):
def __init__(self, window):
self.collision_circle =
pygame.image.load('assets/Towers&Projectiles/Collision_Circle/collision_circle.png')
self.tower_mask = pygame.mask.from_surface(self.collision_circle)
class Enemy(pygame.sprite.Sprite):
def __init__(self, window):
self.enemy_mask_image = pygame.image.load('Assets/Enemy/WALK_000.png')
self.enemy_mask = pygame.mask.from_surface(self.enemy_mask_image)
pygame.display.set_caption("Tower Defense")
width = 1200
height = 840
display_surface = pygame.display.set_mode((width, height))
my_enemy = Enemy(display_surface)
my_tower = Tower(display_surface)
while True:
enemy_sprite = pygame.sprite.GroupSingle(my_enemy.enemy_mask)
tower_sprite = pygame.sprite.GroupSingle(my_tower.tower_mask)
if pygame.sprite.spritecollide(enemy_sprite.sprite,tower_sprite,False,pygame.sprite.collide_mask()):
print("collision")
collide_mask use the .rect and .mask object of the Spirte. Therefore the name of the Mask attribute must be mask, but not tower_mask or enemy_mask.
In addition, the objects must have an attribute named rect, which is a pygame.Rect object with the position of the sprite.
Also the super calls a missing from your class constructors. e.g.:
class TowerCircle(pygame.sprite.Sprite):
def __init__(self, centerx, centery):
super().__init__()
self.image = pygame.image.load('assets/Towers&Projectiles/Collision_Circle/collision_circle.png')
self.mask = pygame.mask.from_surface(self.collision_circle)
self.rect = self.image.get_rect(center = (centerx, centery))
class Enemy(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.image.load('Assets/Enemy/WALK_000.png')
self.mask = pygame.mask.from_surface(self.enemy_mask_image)
self.rect = self.image.get_rect(topleft = (x, y))
See Pygame mask collision and Make a line as a sprite with its own collision in Pygame.
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
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.
I'm currently in the process of writing a larger program in python. It is a simple game, but I've got an Error. Can someone help me?
Error
Traceback (most recent call last):
File "C:/Users/kkuja/Desktop/game.py", line 36, in <module>
MainWindow.MainLoop()
File "C:/Users/kkuja/Desktop/game.py", line 17, in MainLoop
self.chicken_sprites.draw(self.screen)
File "C:\Users\kkuja\AppData\Local\Programs\Python\Python35\lib\site-packages\pygame\sprite.py", line 475, in draw
self.spritedict[spr] = surface_blit(spr.image, spr.rect)
AttributeError: 'Chicken' object has no attribute 'rect'
Code
import os, sys
import pygame
class Game:
def __init__(self, width=640, height=480):
pygame.init()
self.width = width
self.height = height
self.screen = pygame.display.set_mode([self.width, self.height])
def MainLoop(self):
self.ChickenLoad();
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
self.chicken_sprites.draw(self.screen)
pygame.display.flip()
def ChickenLoad(self):
self.chicken = Chicken()
self.chicken_sprites = pygame.sprite.Group(self.chicken)
class Chicken(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("chic.jpg")
if __name__ == "__main__":
MainWindow = Game()
MainWindow.MainLoop()
Thanks in advance!
In the function self.chicken_sprites.draw(self.screen) in your code chicken.rect is trying to be accessed, but you did not define it.
If you refer to the official documentation you can find this piece of code:
class Block(pygame.sprite.Sprite):
# Constructor. Pass in the color of the block,
# and its x and y position
def __init__(self, color, width, height):
# Call the parent class (Sprite) constructor
pygame.sprite.Sprite.__init__(self)
# Create an image of the block, and fill it with a color.
# This could also be an image loaded from the disk.
self.image = pygame.Surface([width, height])
self.image.fill(color)
# Fetch the rectangle object that has the dimensions of the image
# Update the position of this object by setting the values of rect.x and rect.y
self.rect = self.image.get_rect()
You do not set self.rect in your Chicken, it should look like this.
class Chicken(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("chic.jpg")
self.rect = self.image.get_rect(); #here rect is created