user732887
user732887

Reputation: 11

Python - Instance Variable Access

I am currently making a game. I have 2 classes and I want one to access the others instance variables. I'm not sure how to do this or if it is possible.

Both Classes at some point inherits to the class gameEngine
gameEngine <- Game
gameEngine <- SuperSprite <- Character <- Enemy
gameEngine <- SuperSprite <- Character <- Player

My Game class creates an instance variable of an object self.player = Player(self) and I want to be able to use that in my Enemy class so it can do self.player.x. So I can make AI in the enemy class so it’s aware of my player. Any suggestions for how to do this, my logic might be wrong so any help would be grateful. If I need to post my code or anything please tell me.

That or I have been trying to pass an object to a function. So bob can get enemyAI in the game class. But I get an error 'Enemy' object is not callable. Yet it passes it and does the function prints out information then dies. BUT if I move self.enemyAi(self.bob) into the clicked condition it works fine.

if self.enemyWeakBtn.clicked:
    print "spawning enemey"
    self.bob = Enemy(self)

    self.enemies.append(self.bob)
    self.enemyGroup = self.makeSpriteGroup(self.enemies)
    self.addGroup(self.enemyGroup)
    self.enemyActive = True            

elif self.enemyActive:
    print self.bob
    self.enemyAi(self.bob)
    print " active"

Upvotes: 1

Views: 1448

Answers (2)

Pwnna
Pwnna

Reputation: 9538

If i understand you correctly, You want to have the Enermy instances get access to of the Player instance

There are 2 ways to accomplish it. I'm using the second method atm in my programs and plans to add the first method.

First way involves getting the class to have an instance, and calling a class method allows one to get that instance.

class Game:
    instance = False

    def __init__(self):
        if self.__class__.instance:
            raise RunTimeError("Game has already been initialized.") # RunTimeError might be a bad choice, but you get the point
        self.__class__.instance = self

    @classmethod
    def getInstance(cls):
        return cls.instance

##>>> g = Game()
##>>> g
##<__main__.Game instance at 0x02A429E0>
##>>> del g
##>>> Game.getInstance()
##<__main__.Game instance at 0x02A429E0>
##>>> 
## Here you can have, in your enermy class, g = Game.getInstance(). And g.player will be able to access the player instance, and its properties

Second way to do it is what I've been working with. It involves having the Game class regulating EVERYTHING in the game. Meaning: Everything is a variable under game. Also, every single game variable (for example, a player) will have an attribute named game that reference back to the game instance.

Example:

class Player:
    def __init__(self, game):
        self.game = game
        print self.game.enermy

class Game:
    def __init__(self):
        self.enermy = "Pretend I have an enermy object here"
        self.player = Player(self)


##>>> g = Game()
##Pretend I have an enermy object here
##>>> g.player.game.enermy
##'Pretend I have an enermy object here'
##>>> 
## Iin your enermy class, self.game.player will be able to access the player instance, and its properties

Some might object with having the second way, I, too, see the problem with an extra step. Maybe someone can shed some light on the comparison between the 2.

A combination method could be which is what I'm hoping to move to, however this raises some issue with which one you need to place first in the file, or else you might get Player not defined or Game not defined. Though I think it can be solved with separating the 2 classes into different files.

class Player:
    def __init__(self):
        self.game = Game.getInstance()

class Game:
    instance = False

    def __init__(self):
        if self.__class__.instance:
            raise RunTimeError("Game has already been initialized.") # RunTimeError might be a bad choice, but you get the point
        self.__class__.instance = self

    @classmethod
    def getInstance(cls):
        return cls.instance

Upvotes: 1

R&#233;troX
R&#233;troX

Reputation: 2096

The error is likely the lack of a constructor for the Enemy class. By running:

self.bob = Enemy(self)

It looks for the function __init__(self, arg1) in the Enemy class. If it is not provided, Python will be unable to treat Enemy as a "callable," meaning that it cannot be used like a function, or in this case, used to call a constructor with one argument.

Upvotes: 0

Related Questions