how to reference an attribute before it exists python - python

I'm writing a game in pygame, and I have a class that makes a heads up display with stats for each building when you click on it. the class variable current_hud starts as None, but when a building is clicked, its value becomes the building object so that when the draw function is called it only draws the hud of the selected building.
The problem is, I'm trying to create an instance of my "Text" class in the hud, but I'm getting the AttributeError: 'NoneType' object has no attribute 'name' because self.current_hud isn't an object yet, so self.current_hud.name isn't an attribute yet. How do I reference an attribute that doesn't exist yet? is waiting to instantiate the hud class until after the building is clicked on really the only option?
class Hud:
current_hud = None
def __init__(self,x,y):
self.x = x
self.y = y
self.name_text = Text(x,y,str(self.current_hud.name), (0,0,0), 36)
def draw(self):
if Hud.current_hud == self:
self.square = pygame.Rect((self.x,self.y),(440,400))
pygame.draw.rect(screen,(255,255,255),self.square)
self.name_text.x = self.x + 10
self.name_text.y = self.y + 20
sorry if this is convoluted, but it's a little difficult to explain. The full code is here if you want to run it and see how it all works: https://github.com/hailfire006/economy_game/blob/master/economy_game.py

You can take the name as an option to the Hud class and set it prior to instantiating the Text class.
class Hud:
current_hud = None
def __init__(self,x,y,name):
self.x = x
self.y = y
self.current_hud.name = name
self.name_text = Text(x,y,str(self.current_hud.name), (0,0,0), 36)
def draw(self):
if Hud.current_hud == self:
self.square = pygame.Rect((self.x,self.y),(440,400))
pygame.draw.rect(screen,(255,255,255),self.square)
self.name_text.x = self.x + 10
self.name_text.y = self.y + 20
In your full code example it looks like when you instantiate a building you have its name and can then pass that along to the Hud on instantiation.
class Building:
def __init__(self,posX,posY,color,name):
self.hud = Hud(0,0,name)

Related

Python set class variable after calling

I'm making a game using the pygame module and I have a player class:
class Player(pygame.sprite.Sprite):
def __init__(self, name, position, axsis, movment, idle, walk = None, jump = None):
pygame.sprite.Sprite.__init__(self)
self.name = name
self.idle = idle
self.walk = walk
self.jump = jump
self.image = self.idle[0]
self.movment = movment
self.left, self.right = axsis
self.pos = vec(position[0],position[1])
I am adding my characters using json data type and trying to add animations after calling the class but i can't do it
Sample code
class Game():
def __init__(self,json_file):
self.player_attribute = json_file
def character(self):
self.npc = []
for i in self.player_attribute:
self.npc.append(Player(i['name'],
i['position'],
i['axsis'],
i['movment']))
self.animation()
return self.npc
def add_animation(self):
for i in self.npc:
i.idle = "images\ghost.png"
def main_loop()
self.character
when i try this i get an error
self.image = self.idle[0]
TypeError: init() missing 1 required positional argument: 'idle'
how can i add the variables of the class after calling the class
It is not clear what the 'idle' parameter is supposed to represent in your code. However, the reason for the exception is that you are not passing any argument for 'idle' when constructing the Player object. You need something like:
self.npc.append(Player(i['name'],
i['position'],
i['axsis'],
i['movment'],
i['idle']))
You can either do that or alternatively you can pass a default argument to the Player constructor so that, when initializing you do not need to explicitly pass idle:
class Player(pygame.sprite.Sprite):
def __init__(self, name, position, axsis, movment, idle=[1], walk = None, jump = None):
You can modify its content at a later time, however I suggest you are careful what you instantiate that object attribute as, because it might come bite you back later (type error or value error).
If it were me, I would move this out of init, or not build the object until all values and their types are known (see Builder Design Pattern).
Hope this helped :) Cheers!

TypeError: argument 1 must be pygame.Surface, not type

I'm making a submarine game in python, but when I try to run it, the interpreter gives me very strange error:
"TypeError: argument 1 must be pygame.Surface, not type."
I tried to search the web for my answer, but it seems like this isn't very usual error. I also tried to find error by myself, but everything seemed fine to me. Here 's part of the code that I think error is in:
mina = pygame.image.load('mina.png')
class mina():
def __init__(self, x , y):
self.x = x
self.y = y
self.eksplozija = False
def naris(self):
screen.blit(mina, (self.x, self.y))
igralec = podmornica(150, 300, 10)
eksploziv = mina(700, 350)
metki = []
clock = pygame.time.Clock()
def grafika():
clock.tick(60)
screen.blit(ozadje, (0,0))
igralec.naris()
#line, that doesn't work:
eksploziv.naris()
for metek in metki:
metek.naris(screen)
pygame.display.flip()
The variable mina and the class mina have the same name. The class mina shadows the variable mina. You need to rename one or the other. I recommend to rename the calss mina to Mina, since Python classes use the CapWords convention (PEP 8 -- Style Guide for Python Code):
class mina():
class Mina():
eksploziv = mina(700, 350)
eksploziv = Mina(700, 350)

Python class parameters, where to define

class Camera(object):
def __init__(self, win, x=0.0, y=0.0, rot=0.0, zoom=1.0):
self.win = win
self.x = x
self.y = y
self.rot = rot
self.zoom = zoom
cam = Camera(Window,1,1,1,1)
vs
class Camera(object):
def __init__(self, win, x, y, rot, zoom):
self.win = win
self.x = x
self.y = y
self.rot = rot
self.zoom = zoom
cam = Camera(Window,1,1,1,1)
So does the first block of code just make the class static where it can only be made and not adjusted with parameters? If so, what's the usefulness of this?
The first block of code just sets default values for those variables. When the class is initialised if they are passed to the class, then they will be set. Otherwise the class variables will contain the default values.
In the second block of code, by not setting a default value you are making those parameters required for the class.
See this question for a better explanation: Why do we use __init__ in python classes?
The difference between the first one and second one is: the first one has default values while the other one dosen't. For example with the first one
cam = Camera(Window) wouldn't give you an error (x=0.0, y=0.0, rot=0.0 and zoom=1.0 have a default assigned value).
But the second code block would give you an error if you were to create new instance of the class like this cam = Camera(Windows). Wich is ultimately the difference between your first code block and your second one.
Cheers!

Issue with passing attributes between classes in python

Ive made these classes below and I'm trying to have a tile in the game present a text based on an attribute in another class. I keep getting this error.
File "C:\Users\xxxxxxxx\PycharmProjects\Game.idea\Girls.py", line 20, in not_interested
return (self.interest < 10)
AttributeError: 'GirlTile' object has no attribute 'interest'
class Girls():
def __init__(self):
self.girlnames = ["Lucy", "Cindy", "April", "Allison", "Heather", "Andrea", "Brittany", "Jessica", "Lane", "Lauren", "Sabrina","Chelsea","Amber"]
self.name = random.choice(self.girlnames)
self.height = random.randrange(60, 72)
self.age = random.randrange(18, 25)
self.number = self.new_number()
self.interest = 0
def not_interested(self):
return (self.interest < 10)
from Girls import Girls
class GirlTile(MapTile):
def __init__(self,x,y):
self.enemy = Girls()
super().__init__(x, y)
def intro_text(self):
self.stance = Girls.not_interested(self)
if self.stance:
print("Hey whats up")
It looks like not_interested is an instance-level method, but you are trying to call it with a class (Girls). And the call is sort of "working" because you are passing the GirlTile instance in the call -- hence the error that the GirlTile has no interest attribute (because it does not).
Maybe you intended this instead?
def intro_text(self):
# Use an actual Girl instance to call not_interested().
self.stance = self.enemy.not_interested()
...

collision detection error:AttributeError: type object 'Ship_laser' has no attribute 'sprites'

I am trying to write a game using a model, but i get the error:
"File "C:\Python27\lib\site-packages\pygame\sprite.py", line 1514, in spritecollide
for s in group.sprites():AttributeError: type object 'Ship_laser' has no attribute 'sprites'"
when running the script.If i dont call my collision function the script runs, so in that function is the mistake,but i dont understand where's the mistake.Here is the code of the function:
def collisions():
for enemy_ship in classes.Enemy_ship.List:
enemy_laser = pygame.sprite.spritecollide(enemy_ship, classes.Ship_laser, True)
if len(enemy_laser) > 0:
for hit in enemy_laser:
enemy_ship.health -= 25
for laser in classes.Ship_laser.List:
if pygame.sprite.spritecollide(laser, enemy_ship, True):
laser.destroy()
If it's needed i am posting the the Ship_laser class from my classes.py file
class Ship_laser(pygame.sprite.Sprite):
allsprites = pygame.sprite.Group()
def __init__(self, x, y, image_string):
pygame.sprite.Sprite.__init__(self)
Ship_laser.allsprites.add(self)
self.image = pygame.image.load(image_string)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.velx, self.vely = 0, 0
#staticmethod
def laser_movement(SCREENWIDTH, SCREENHEIGHT):
for laser in Ship_laser.List:
laser.rect.x += laser.velx
laser.rect.y += laser.vely
def destroy(self):
Ship_laser.List.remove(self)
del self
Considering that the Laser.ship class it's inheriting the pygame.sprite.Sprite class i dont understand the error.This is my first game.Please help
I can't say I am an expert with pygame, nor do I fully understand how you have built your classes. When I hear ship laser, I think of a single instance that belongs to a ship, yet in your class you define "allsprites" which is mutable type defined to a class instance (shared by all members of the class).
But given this, allsprites will be the same mutable object shared among ever ship_laser, almost like the yellowpages of your class. When you call pygame.sprite.spritecollide (based on pygame docs) it is looking for the sprite.Group and hence, you should pass it the group lookup (the yellowpages aka allsprites) rather than the reference to the class. That should sort your issues. So, here is your code change:
enemy_laser = pygame.sprite.spritecollide(enemy_ship, classes.Ship_laser, True)
to
enemy_laser = pygame.sprite.spritecollide(enemy_ship, classes.Ship_laser.allsprites, True)

Categories

Resources