How do I fix TypeError: __init__() missing 1 required positional argument: 'y' - python

I'm currently trying to set up hitboxes for my characters but I can't seem to get rid of this error.
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
self.x = x
self.y = y
pygame.sprite.Sprite.__init__(self)
self.image = IronMan
self.rect = self.image.get_rect()
self.rect.y = 475
self.direction = 1
self.hitbox = (self.x + 20, self.y + 11, 28, 60)
def draw(self, win):
self.hitbox = (self.x + 20, self.y + 11, 28, 60)
pygame.draw.rect(win, (255, 0, 0), self.hitbox, 2)
When the code is ran Im faced with
TypeError: __init__() missing 1 required positional argument: 'y'

Looks like you didn't provide sufficient parameters when you created an instance of the class. There are 2 options to fix it.
Provide sufficient parameters when creating instance.
Example:
Mark = Player() # Error
Cindy = Player(1) # Error
James = Player(1, 2) # Good!
Since you specified _init_ method to take 2 arguments, you must provide 2 arguments when calling it.
Simply set a default value for the arguments.
You can do this by using '=' sign.
Example:
def __init__(self, x=0, y=0):
#blabla
Now, _init_ method will automatically initialize the arguments to 0, if it's not provided manually.
Mark = Player() # Mark.x=0, Mark.y=0
Cindy = Player(1) # Cindy.x=1, Cindy.y=0
James = Player(1, 2) # James.x=1, James.y=2

Related

Inherited __init__() function not working as intended

I was working on a game using the pygame library on Python. I basically defined a Character class from which the Knight class and Enemy class would inherit functions. Since both children classes use the same initialize functions, I defined the __init__() function under the parent class. However, I don't fully understand how it works and I'm getting the following error:
TypeError: __init__() takes 1 positional argument but 3 were given
Here's my code:
class Character():
def __init__(self, img, hitbox, vel, pos_x, pos_y):
self.img = img
self.hitbox = hitbox
self.vel = vel
self.pos_x = pos_x
self.pos_y = pos_y
def draw(self):
if self.right:
pygame.transform.flip(self.img, True, False)
win.blit(self.img, (self.pos_x, self.pos_y))
class Knight(Character):
def __init__(self):
Character.__init__(self)
def move(self):
if self.right:
if self.x + self.vel < win_width:
self.x += self.vel
if self.left:
if self.x - self.vel > 0:
self.x -= self.vel
main_plr = Knight("img", (19, 20), 5, 30, 20)
For a quick fix: just remove the __init__ method from Knight.
The error is raised because you create a Knight object with 6
arguments (self, "img", (19, 20), 5, 30, 20) whereas the __init__ method accepts only one (self).
So if your Knight objects do not have any additional attributes
compared to Character objects, it will be just fine to remove the
__init__ method. Now if you want your knight to have weapons, for
example, you will have to do something like that:
class Knight(Character):
def __init__(self, img, hitbox, vel, pos_x, pos_y, weapon):
super().__init__(img, hitbox, vel, pos_x, pos_y)
self.weapon = weapon
k = Knight("img", (19, 20), 5, 30, 20, "sword")
[Edit]
Additionaly, as suggested by #Matiiss, you can use *args to avoid
repeating all arguments of Character.__init__ in Knight.__init__.
One advantage, besides conciseness, is that you do not have to modify
Knight if you add attributes to your Character objects.
class Knight(Character):
def __init__(self, *args, weapon):
super().__init__(*args)
self.weapon = weapon
k = Knight("img", (19, 20), 5, 30, 20, weapon="sword")
But now the drawback is that you have to specify the weapon with
weapon="the-weapon", since it is now a keyword argument (placed
after *args).
As the error you are seeing says, your Knight constructor does not accept those arguments; if you are going to use that kind of inherited method extension, the class and subclass methods need to have matching argument signatures. It's also best to use super() to refer to the superclass rather than naming it explicitly.
The simplest way of handling this is to use *args and **kwargs, to concisely pass arguments that aren't needed by the subclass method to the superclass method, ie
class Character():
def __init__(self, img, hitbox, vel, pos_x, pos_y):
self.img = img
self.hitbox = hitbox
self.vel = vel
self.pos_x = pos_x
self.pos_y = pos_y
class Knight(Character):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def move(self):
if self.right:
if self.x + self.vel < win_width:
self.x += self.vel
if self.left:
if self.x - self.vel > 0:
self.x -= self.vel

Getting a type Surface error with argument 1. How would I fix it?

I'm using Python 3.7.4 and Python 1.9.6. I have a class which is the main one for the subclass's. I'm experiencing an error: the line with the error --> window.blit(self.ship_img, (self.x, self.y)) TypeError: argument 1 must be pygame.Surface, not None.
Code:
class Ship:
def __init__(self, x, y, health=100):
self.x = x
self.y = y
self.health = health
self.ship_img = None
self.laser_img = None
self.lasers = []
self.cool_down_counter = 0
def draw(self, window):
window.blit(self.ship_img, (self.x, self.y))
def get_width(self):
return self.ship_img.get_width()
def get_height(self):
return self.ship_img.get_height()
The reason it has to be None because it has several images of the same class(meaning using the same variables) but with different coordinates and properties. It can't be a list, because then the .get_width() and .get_height() won't work. I'm using those to create barriers for the image(s).
I'm following along with the tutorial: https://www.youtube.com/watch?v=Q-__8Xw9KTM&ab_channel=TechWithTim. I'm at around 51:41 of the video. Thank you for the advice as always.
Just test that self.ship_img is not None, before drawing the object:
class Ship:
# [...]
def draw(self, window):
if self.ship_img != None:
window.blit(self.ship_img, (self.x, self.y))

A variable which suppose to be pygame.Surface appears like a string

I just added a function to my code which should display an image from a directory. It requires an argument which specifies which window it displays it in. When I try to pass it in I receive the following error:
Traceback (most recent call last):
File "Pygame.py", line 122, in <module>
Player.load()
File "Pygame.py", line 74, in load
screen.blit(self.path, (self.x, self.y))
TypeError: argument 1 must be pygame.Surface, not str
My code:
import pygame
#init the pygame and create a screen
pygame.init()
screen = pygame.display.set_mode((1080,720))
done = False
#colours
blue = (0,0,255)
red = (255,0,0)
green = (0,255,0)
black = (0,0,0)
white = (255,255,255)
yellow = (255,255,0)
#path to the background
bg_path = "Racing.png"
#path to the car image
car_path = "car.png"
#starts the game clock
clock = pygame.time.Clock()
#opening bg image
background_image = pygame.image.load(bg_path).convert()
#class for all of the objects on the screen
class shape():
def __init__(self, place, x, y):
self.place = place
self.x = x
self.y = y
class rectangle(shape):
def __init__(self, place, colour, x, y, length, width):
super().__init__(place,x, y)
self.colour = colour
self.length = length
self.width = width
def draw(self):
pygame.draw.rect(screen, self.colour, pygame.Rect(self.x, self.y,
self.length, self.width))
def move_up(self):
self.y = self.y - 10
def move_down(self):
self.y = self.y + 10
def move_right(self):
self.x = self.x + 10
def move_left(self):
self.x = self.x - 10
class player(shape):
def __init__(self, place, x, y, length, width, path):
super().__init__(place,x, y)
self.length = length
self.width = width
self.path = path
def load(self):
screen.blit(self.path, (self.x, self.y))
Rectangle = rectangle(screen, yellow, 540, 660, 60, 60)
Player = player(screen, 540, 600, 60, 60, car_path)
Player.load()
This isn't all of the code but the rest isn't related to the problem (I think). Please tell me if more code is needed.
car_path is set as a string here
car_path = "car.png"
But blit() requires a pygame.Surface object for the first argument which pygame.image.load would give you, i.e.
car_path = pygame.image.load("car.png")
instead.

Ways to reach variables from one class to another class?

I'm trying to create a basic game, but I'm fairly new to the python programming scene. I've come across a problem where with two classes (a player and enemy class), I want to access class variables like health from the player and enemy, and vice versa. What are some ways of doing this?
Here's the code to better emphasize what I'm asking:
class Player(object):
def __init__(self, image):
self.x = 100
self.y = 240
self.health = 30
self.defense = 25
self.image = image
self.black = (0, 0, 0)
self.draw()
def draw(self):
screen.blit(self.image, (self.x, self.y))
line = pygame.draw.rect(screen, self.black, (80, 300, 100, 5))
def attack(self):
pass
class Enemy(object):
def __init__(self, image):
self.x = 480
self.y = 240
self.health = 20
self.defense = 15
self.image = image
self.black = (0, 0, 0)
self.draw()
def draw(self):
screen.blit(self.image, (self.x, self.y))
line = pygame.draw.rect(screen, self.black, (460, 300, 100, 5))
def attack(self):
pass
Basically, I don't understand how I can take something like the "self.health" from one class, and easily access it from the other class. I've tried some methods of using return methods etc., but I'm curious if there are any simple ways to do this. Help is appreciated!
This code creates a class, and in the special __init__ method, it assigns values to various member variables.
class Player(object):
def __init__(self, image):
self.x = 100
self.y = 240
self.health = 30
self.defense = 25
self.image = image
self.black = (0, 0, 0)
self.draw()
These member variables are also called properties in Python. If you have a reference to a Player instance (an instance of the Player class):
p = Player()
You can access the properties all you like:
print(p.health)
Perhaps you need some kind of "main loop" or controller class that has access to players and enemies and can set their properties accordingly:
class MainLoop(object):
def __init__(self):
self.player_1 = Player()
self.enemy_1 = Enemy()
def run(self):
if fight(): # fight() is some function of your game
self.player_1.health -= 10
self.enemy_1.health -= 20

Using pygame.Surface.blit inside class

I can call my class only one time.
My code is:
class fish:
def __init__(self, x, y, image, speed):
self.x = x
self.y = y
self.image = image
self.speed = speed
def be(self):
screen.blit(self.image, (self.x, self.y))
self.x -= self.speed
if boot.x+36 > self.x and boot.x < self.x+5:
if boot.y+34 > self.y and boot.y < self.y+5:
boot.live -= 1
boot.x = 100
boot.y = 460
fishes = []
fishes.append(fish(900, 300, fish_1, 1))
And when I call 'fish' object inside or outside the game loop(fishes.append(fish(900, 300, fish_1, 1))
I got Error:
TypeError: 'fish' object is not callable
My first guess is that you have a fish variable somewhere down in your code. Rename the class to Fish as well as the constructor call to Fish(900, 300, fish_1, 1) and it should be fine.

Categories