Class Help: "NameError: name 'self' is not defined" - python

I am attempting to create a Pawn class for a chess game, but I get the error "NameError: name 'self' is not defined" in the "can_move" function's first if statement, even though I define the colour as the input in the initialise function? Any ideas?
class Pawn(object):
def __init__(self, x, y, colour):
#store the pawns coords
self.x = x
self.y = y
#store the colour of the piece
self.colour = colour
#store if it moved yet or not
self.moved = False
self.print_value = self.colour+"P"
def can_move(newx, newy):
#func to check if piece can move along those coords
if self.colour == "W":
pieces = game_tracker.live_white
elif self.colour == "B":
pieces = game_tracker.live_black

Instance methods need self as first argument
def can_move(self, newx, newy):
Otherwise the method does not know which instance it is operating on

You need to add self as an argument, representing the current instance of the class. Also indent.
class Pawn(object):
def __init__(self, x, y, colour):
#store the pawns coords
self.x = x
self.y = y
#store the colour of the piece
self.colour = colour
#store if it moved yet or not
self.moved = False
self.print_value = self.colour+"P"
def can_move(self, newx, newy):
#func to check if piece can move along those coords
if self.colour == "W":
pieces = game_tracker.live_white
elif self.colour == "B":
pieces = game_tracker.live_black

Related

TypeError: __init__() takes X positional arguments but X+1 were given

class Game():
def __init__(self):
# here we want to make a player, and start making some attributes
self.player = character(50,50,100, (0,255,0), "Player")
self.enemy = character(55,200,200, (255,0,0), "Enemy")
self.alive = [self.player,self.enemy]
class character(): # this will be the class which can make any
def __init__(self,x,y,health,colour, name):
self.x = x
self.y = y
self.health = health
self.colour = colour
self.width = 90
self.height = 50
self.vel = 0.04
self.name = name
When I try to use or change the colour attribute (of the character) in my Game class, I get an
TypeError: __init__() takes 5 positional arguments but 6 were given
while defining the object player as here:
self.player = character(50,50,100, (0,255,0), "Player")
Why does Python tell me I gave it 6 arguments, when I only gave 5?
I don't know if this will solve the problem seeing as I cannot replicate the error either way but, Empty brackets are not needed on the class definitions.
class Game:
def __init__(self):
# here we want to make a player, and start making some attributes
self.player = character(50,50,100, (0,255,0), "Player")
self.enemy = character(55,200,200, (255,0,0), "Enemy")
self.alive = [self.player,self.enemy]
class character: # this will be the class which can make any
def __init__(self,x,y,health,colour, name):
self.x = x
self.y = y
self.health = health
self.colour = colour
self.width = 90
self.height = 50
self.vel = 0.04
self.name = name

Pygame relative coordinates between two objects , OOP

Let's say that i have a class containg the object coordinates in the __init__(self) part like this :
class myObject(object):
def __init__(self, name):
self.img = file1
self.x = random.randrange(0, 700)
self.y = random.randrange(0, 700)
...
Then, in another method, the x and y are being continuously changed :
def move(self):
surface.blit(self.img, (self.x, self.y))
self.x += 0.2
self.y += 1
...
Now , let's say that we have another class in which we have another object. But this object's coordinates are related to the coordinates of that first object :
class myRelativeObject(self):
def __init(self):
self.img = file2
self.x = myObject('instanceName').x + 20
self.y = myObject('instanceName').y + 30
def blit(self):
surface.blit(self.img, (self.x, self.y))
The problem now is that the myRelativeObject.x and myRelativeObject.y values are not being taken from the varibales myObject.x and myObject.y in the move() function.
Yet, they are taken from those in the __init__(self) that are randomly generated.
This makes the second object's coordinates being randomly regenerated every frame. Besides, i want them to be in relation with those in the move() function so that when the first object moves, the second one moves with it.
Let this be an instance of the first object:
myInstance = myObject('instanceName')
NOTE :
Keep in mind that the class methods except the init one, are running in a while loop.
Do not take the coordinates of the object, but make the referenced object an attribute itself:
class myRelativeObject(self):
def __init(self):
self.img = file2
self.refObject = myObject('instanceName')
self.relX = 20
self.relY = 30
def blit(self):
x = self.refObject.x + self.relX
y = self.refObject.y + self.relY
surface.blit(self.img, (x, y))

How do I make a variation of a pre-existing class?

I am currently creating a game where each enemy has a specific AI. Each enemy is given an AI and statistic changes(health, damage, etc.). However, I also need to assign these enemies to an NPC slot before the game's main loop is run. The problem comes in because I need to identify the x-value and y-value of the enemy so the game knows where to place them. If I keep the x- and y-values as a parameter in the AI class, I have to repeatedly redefine them when I put them in an NPC slot(my slots are labelled 'NPC1', 'NPC2', and so on).
class PeonGrounded(object):
def __init__(self, x, y, width, height, vel, aggrorange, health=20.0, kb=10, jumplength=10.0, jumpheight=2.0,
jumpmomentum=0.25):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = vel
self.direction = 'R'
self.standing = True
self.health = health
self.canMove = True
self.jumplength = jumplength
self.isJump = False
self.canJump = True
self.kb = kb
self.jumpheight = jumpheight
self.jumpmomentum = jumpmomentum
self.neg = 1
self.aggrorange = aggrorange
self.aggroed = False
I now want to be able to define some parameters(everything but x, y, width, height) but leave others blank for defining later.

How do I access a variable in a class that was defined before in another class?

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

Python: Classes that "talk" to each other

I'm a college student. I'm in my second comp sci class and we haven't got much past simply making classes and functions within them so I haven't really been able to make much use of the complicated jargon I've found on the internet.
I'm making a roach infestation sim, and I need to be able to have a "roach" class be able to detect where a "food" class is in a window. My teacher told me that my best shot might be to make another mastermind-like class that is a middle man between the two, but I don't really know how that would work. Can anyone help me out? I'm using Python through Calico. Here's what I have of the roach class (EDIT: guess I should show the main() etc too):
class Roach:
def __init__(self, win, placex, placey):
self.timer = 320 + (10 *(int(10 *random.random())))
self.speed = 0.2
self.heading = 360
self.win = win
self.x = placex
self.y = placey
self.body = self.makeBody()
self.body.draw(self.win)
def __str__(self):
t = "Roach at ("+str(self.x)+","+str(self.y)+")"
return t
def makeBody(self):
body = Rectangle((-5,-5),(5,5))
body.setFill(Color('Brown'))
body.moveTo(self.x,self.y)
return body
def move(self, win):
self.x = self.x + self.speed *sin(self.heading)
self.y = self.y + self.speed *cos(self.heading)
self.body.moveTo(self.x,self.y)
self.avoid(win)
def avoid(self, win):
Border = False
if self.x >= win.getWidth():
self.setHeading(random.randrange(91, 269))
self.x = win.getWidth() - 1
Border = True
elif self.x <= 0:
self.setHeading(random.randrange(271, 449))
self.x = 1
Border = True
elif self.y >= win.getHeight():
self.setHeading(random.randrange(1, 179))
self.y = win.getHeight() - 1
Border = True
elif self.y <= 0:
self.setHeading(random.randrange(181, 359))
self.y = 1
Border = True
return Border
#Getters
def getSpeed(self):
return self.speed
def getHeading(self):
return self.heading
def getX(self):
return self.x
def getY(self):
return self.y
#Setters
def setSpeed(self, speed):
self.speed = speed
def setHeading(self, heading):
self.heading = heading
self.body.rotateTo(self.heading)
def setX(self, x):
self.x = x
def setY(self, y):
self.y = y
def main():
win = Window(400, 400)
win.setBackground(Color("White"))
Rpop = []
Wpop = []
i = 320
menu(win, Rpop, Wpop)
while getKeyPressed() != 'Escape':
for roach in Rpop:
if roach.avoid(win) == True:
roach.avoid(win)
elif i % roach.timer == 0:
roach.setHeading(360*random.random())
roach.move(win)
if getKeyPressed() == 'm':
menu(win, Rpop, Wpop)
i = i + 1
def menu(win, Rpop, Wpop):
while getKeyPressed() != 's':
if getKeyPressed() == 'r':
Rpop.append(Roach(win,getMouseNow()[0],getMouseNow()[1]))
if getKeyPressed() == 'w':
point1 = getMouse()
dot1 = Circle((point1[0],point1[1]), 3)
dot1.draw(win)
point2 = getMouse()
dot2 = Circle((point2[0],point2[1]), 3)
dot2.draw(win)
Wpop.append(Wall(win, point1[0], point1[1], point2[0], point2[1]))
return
main()
Sorry for the lack of comments and likely juvenile programming. Thank you so much.
Here's a sort of rough outline of how you might use an additional "Master" class to allow two other classes to communicate as is alluded to in the OP:
class Master():
...
def is_food_there(self, coords):
for food_instance in self.food_instances:
if coords == food_instance.coords:
return True
class Food():
def __init__(self, master_instance):
self.coords = ###some coordinates or whatever
master_instance.food_instances.append(self) ### register this food with master
class Roach():
def __init__(self, master_instance):
self.master_instance = master_instance
...
def move(self, newlocation):
if( self.master_instance.is_food_there(newlocation) ): ### check with master for food coords
###do something
The idea is that the we have a Master class which is essentially a container for a list of Food instances, and Roach class knows which Master instance it belongs to, so it can access that master's "is_food_there" function which in turn looks through the Food instances that belong to it. The Master class is "the man in the middle" in this example.

Categories

Resources