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))
Related
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
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
This is the relevant part of the code that I am having issues with. The player.x and player.y are getting "AttributeError: type object 'player' has no attribute 'x'" errors in the debug console. I have a seperate class called "player" and I want to get its x and y coordinate while it is moving around so that the enemy can move toward it. This is the player class beginning part that is also relevant:
class player(object):
def __init__(self, x, y, sprintMultiplier, fps):
self.x = x
self.y = y
self.vel = 1/fps * 150
class enemy(object):
def __init__(self, fps, difficulty):
pass
def draw(self, window):
self.moveTowardsPlayer()
window.blit(self.downStanding, (self.x, self.y))
def moveTowardsPlayer(self):
dx, dy = self.x - player.x, self.y - player.y
dist = math.hypot(dx, dy)
dx, dy = dx/dist, dy/dist
self.x += dx * self.vel
self.y += dy * self.vel
Based on the code provided, it looks like you're mixing up a class with an object (instance) of that class.
player here is a class, of which you could create objects. The player class itself has no class attributes (i.e., variables that are shared by all members of the class); it only has instance attributes (variables unique to individual instances of the class). So the expected use is that you create one or more instances (maybe global to your program) and operate on those.
Thus, I think what you need is threefold:
To create a player object like so: the_player = player(starting_x, starting_y, multiplier, starting_fps)
Add a parameter for that player to your enemy's initializer, like so:
class enemy(object):
def __init__(self, player_to_track, fps, difficulty):
self.player_to_track = player_to_track
Pass the_player to the enemy object you create.
(For what it's worth, many people adhere to a convention of making class names capitalized, and instances lowercase. This helps make it the distinction obvious when reading the code—you get something like my_player = Player( . . . ), and if you ever write Player.foo, it helps call out that you're talking about a class attribute, not a member variable.)
Error in your code
You are declaring the x and y variables of the class player as private instance variables whereas in the enemy class you are accessing those x and y values as global variables.
So the work around the problem is.
You either declare the x and y values as global variables as below
and access those x and y variables as global ones in the constructor
as given below.
class player(object):
x = 0
y = 0
def __init__(self, x, y, sprintMultiplier, fps):
player.x = x
player.y = y
self.vel = 1/fps * 150
or Pass a player instance to the method moveTowardsPlayer() within the
enemy class if you don't want to keep the x and y variables (of player
class) as global/class variables. Code is given below.
def moveTowardsPlayer(self, player1):
dx, dy = self.x - player1.x, self.y - player1.y
dist = math.hypot(dx, dy)
dx, dy = dx/dist, dy/dist
self.x += dx * self.vel
self.y += dy * self.vel
I want to use the self variables in one class and use them in another class which already has its own self variables how to do I do this. Some code here to help.
class A():
self.health = 5
class B(): # This class already has a self function
for sprite in all_sprites:
if pygame.sprite.collide_circle(self, sprite):
self.collide = True
self.health -= 0.1
You're misunderstanding. self is only an internal reference. Within the class, you refer to self. Otherwise, you refer to the sprite object directly as such,
class A():
self.health = 5
class B(): # This class already has a self function
for sprite in all_sprites:
if pygame.sprite.collide_circle(self, sprite):
sprite.collide = True
sprite.health -= 0.1
The following code may help to explain how to use self in a class. Notice on line 45 that self is passed to the collide method of the sprite class. Inside of a class, you can pass self (which represents the current instance you are working with) to any other instance method or function if desired.
import math
import random
def main():
b = B(5, 5, 2)
print('Health =', b.health)
b.collide_sprites()
print('Health =', b.health)
class Sprite:
def __init__(self, x, y, radius):
self.x = x
self.y = y
self.radius = radius
def collide(self, other):
middle_distance = math.hypot(self.x - other.x, self.y - other.y)
edge_margin = self.radius + other.radius
return middle_distance < edge_margin
class A(Sprite):
def __init__(self, x, y, radius):
super().__init__(x, y, radius)
self.health = 5
class B(A):
def __init__(self, x, y, radius):
super().__init__(x, y, radius)
self.all_sprites = [A(
random.randrange(10),
random.randrange(10),
random.randint(1, 4)
) for _ in range(50)]
self.collide = False
def collide_sprites(self):
for sprite in self.all_sprites:
if sprite.collide(self):
self.collide = True
self.health -= 0.1
if __name__ == '__main__':
main()
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