Calling class functions through list - python

I was attempting to place certain class variables within a list. Each class has a method known as update and considering they each do the exact same thing I though it would be allot more convenient to simply place them in a list and call the method that way.
The method I am trying to call is known as update and this is the error that I get:
Traceback (most recent call last):
File "C:\Users\GoodPie\Desktop\New Game Dev\main.py", line 177, in <module>
initialize_game()
File "C:\Users\GoodPie\Desktop\New Game Dev\main.py", line 61, in initialize_game
start_menu(debugging, screen, clock, image_cache)
File "C:\Users\GoodPie\Desktop\New Game Dev\main.py", line 88, in __init__
self.init_start_screen()
File "C:\Users\GoodPie\Desktop\New Game Dev\main.py", line 115, in init_start_screen
self.update_group.append[New_Game_Button, Load_Game_Button, Quit_Game_Button, Settings_Button]
TypeError: 'builtin_function_or_method' object is not subscriptable
Here is the code I am trying to use
Entities.py:
class Quit_Game_Button(Entity):
def __init__(self, x, y, image_cache):
Entity.__init__(self)
self.image_cache = image_cache
self.image = function.get_image("images/Quit_Game.png", self.image_cache)
self.image.convert()
self.rect = Rect(x, y, 150, 30)
def update(self, mouse_position):
if self.rect.collidepoint(mouse_position):
self.image = function.get_image("images/Quit_Game_Hover.png", self.image_cache)
else:
self.image = function.get_image("images/Quit_Game.png", self.image_cache)
def check_click(self, clicked, mouse_position):
quit = False
if self.rect.collidepoint(mouse_position):
if clicked:
quit = True
return quit
class Settings_Button(Entity):
def __init__(self, x, y, image_cache):
Entity.__init__(self)
self.image_cache = image_cache
self.image = function.get_image("images/Settings_Button.png", self.image_cache)
self.image.convert()
self.rect = Rect(x, y, 50, 50)
def update(self, mouse_position):
if self.rect.collidepoint(mouse_position):
self.image = function.get_image("images/Settings_Button_Hover.png", self.image_cache)
else:
self.image = function.get_image("images/Settings_Button.png", self.image_cache)
main.py
self.update_group.append[New_Game_Button, Load_Game_Button, Quit_Game_Button, Settings_Button]
mouse_position = pygame.mouse.get_pos()
#Updating Entities on the screen
for entity in self.update_group:
entity.update(mouse_position)
Just so it's clear, the functions do exist. I was just wondering if I was going about calling methods the write way through a list/array? If not could someone please point me in the right direction? :)

You are trying to assign one to one(1) and two to two(), that results in a referenced before assignment error So change the class Names to something more suitable like One and Two
Also It is strictly recommended(for CapWords convention see pg4 here) to always start a python class name with a uppercase character
Corrected code would look like: (I've implemented the str method)
class One:
def __init__(self, x):
self.x = x
def update(self):
self.x += 1
def __str__(self):
return str(self.x)
class Two:
def __init__(self, x):
self.x = x
def update(self):
self.x += 1
def __str__(self):
return str(self.x)
def test():
one = One(1)
two = Two(2)
update_list = [one, two]
for i in update_list:
i.update()
print i
test()
Output:
2
3

This is a simple error.
self.update_group.append[New_Game_Button, Load_Game_Button, Quit_Game_Button, Settings_Button]
should be
self.update_group.extend([New_Game_Button, Load_Game_Button, Quit_Game_Button, Settings_Button])
You're trying to index append where you should call it. Second point is, that append takes only one parameter, so you should use extend.
But you're still operating on the classes, not instances of the classes.

The issue did not lie within the actual for loop for calling the update function within the class, it occurred through the appending off the class instances to the list. Therefore to solve this problem I tried:
self.update_group = [New_Game_Button, Load_Game_Button, Quit_Game_Button, Settings_Button]
and it worked perfectly. I don't know what the issue is with the appending to the array, but having a fixed list/array seems to work just fine for me. Credits to #Matthias for actually making me look at the method for adding the instances to the array.

Related

calling a parent class constructor from a subclass in python

I am trying to use subclasses of a python class to implement [more] specific behaviour for a [very simple] game.
Here's some classes used in the code declared at the beginning:
from enum import Enum
class direction(Enum):
LEFT = ','
RIGHT = '.'
class bomb:
def __init__(self,xval,yval):
self.x = xval
self.y = yval
self.fired = False
After these classes, here's the root class of the class that [seems to be] causing a problem:
class character:
# default constructor
def __init__(self,xval,yval):
self.x = xval
self.y = yval
self.alive = True
self.bomb = bomb(self.x,self.y)
def fire_bomb(self):
self.bomb.x = self.x
self.bomb.y = self.y
self.bomb.fired = True
and here's the subclass where the error appears subclass:
class baddie(character):
def __init__(self,xval,yval):
super().__init__(xval, yval)
self.currentDirection = direction().RIGHT
But when I try and create an array of baddies:
baddie_list = [baddie(1,1)], baddie(3,1), baddie(5,1), baddie(7,1), baddie(9,1), baddie(11,1)]
it's bombing out with the error:
Traceback (most recent call last):
File "pyinvaders.py", line 59, in <module>
baddie_list = [baddie(1,1)] #, baddie(3,1), baddie(5,1), baddie(7,1), baddie(9,1),
baddie(11,1)]
File "pyinvaders.py", line 42, in __init__
self.currentDirection = direction().RIGHT
TypeError: __call__() missing 1 required positional argument: 'value'
I'm not sure what I'm doing wrong here.
The error appears to occur when creating the array of baddie objects, which leads me to examine the constructor for the baddie.
Can anyone give some pointers on how I call the parent class constructor from the child class?
thanks heaps,
David
After all that, the error wasn't in the call to the parent constructor at all!
The error was on the line:
self.currentDirection = direction().RIGHT
which should be:
self.currentDirection = direction.RIGHT
That is, no brackets needed [smacks forehead with palm].
Thanks buran [especially]. You were spot on right - that's where the problem was!

Python function not defined

I have been making a python 3d game in ursina. So far so good but for one error:
File "C:\Users\my name\AppData\Local\Programs\Python\Python39\lib\site-packages\ursina\main.py", line 117, in _update
__main__.update()
File "c:\Users\my name\Desktop\game456.py", line 14, in update
release()
NameError: name 'release' is not defined```
I dont understand this error. I have seen others run code like this too. This code is inspired by another person making a game in ursina so i copied a little bit of code myself. i tried googling an answer but it's just about a variable not being defined,etc. View code below.
from ursina import*
from ursina.prefabs.first_person_controller import FirstPersonController
gamebyme = Ursina()
def update():
if held_keys["left mouse"]:
shoot()
else:
release()
class Voxel(Button):
def __init__(self, position = (0,0,0)):
super().__init__(
parent = scene,
position = position,
model = 'map',
origin_y = 0.5,
texture = texture,
color = color.color(0,0,random.uniform(0.9,1)),
scale = 0.1)
class Gun(Entity):
def __init__(self):
super().__init__(
parent=camera.ui,
model='ak_47',
position=Vec2(0.8,-0.1),
color=color.gray,
scale=0.3)
def shoot(self):
self.rotation=Vec3(0,0,10)
def release(self):
self.rotation=None
def reload(self):
self.rotation=Vec3(0,0,0)
plr = FirstPersonController()
gun = Gun()
vxl = Voxel()
gamebyme.run()
In this function
def update():
if held_keys["left mouse"]:
shoot()
else:
release()
you should specify the Gun type object you want to call the functions from, eg:
def update(gun):
if held_keys["left mouse"]:
gun.shoot()
else:
gun.release()

Why "NameError: name 'draw_Objects' is not defined" occurs

I am making a small game using pygame.
I have defined a function called draw_Objects() but Name Error occurs as if I didn't define the function. What should I do?
The code is part of the module
I have tried to change the draw_Objects() function but I couldn't solve it.
import pygame
from const import *
class item(pygame.sprite.Sprite):
def __init__(self,game):
super().__init__()
self.game=game
#self.screen=screen
self.width=WIDTH
self.height=HEIGHT
#potion 사진 불러옴
self.image=pygame.image.load("tile/red-potion.png")
self.rect = self.image.get_rect()
self.red_potion=pygame.image.load("tile/red-potion.png")
self.blue_potion=pygame.image.load("tile/blue-potion.png")
self.mask=pygame.mask.from_surface(self.image)
self.rect = self.image.get_rect()
redItem=[50,530,300,50,850,100,600,280,800,400]
def __call__(self):
print (" ")
def item_display(self,screen):
#아이템 화면에 표시
screen.blit(self.red_potion,(50,530)) #red1
screen.blit(self.blue_potion,(30,530))
screen.blit(self.blue_potion,(30,460))
screen.blit(self.red_potion,(300,50)) #red2
screen.blit(self.blue_potion,(400,150))
screen.blit(self.image,(850,100)) #red3
screen.blit(self.red_potion,(600,280)) #red4
screen.blit(self.red_potion,(800,400)) #red5
screen.blit(self.blue_potion,(600,370))
def draw_Objects(myList=[]):
for i in myList:
x=myList[i]
y=myList[i+1]
screen.blit(self.red_potion,(x,y))
i+=1
def item_eat(self,screen):
item__=item(self)
#red2 item
self.rect.x=300
self.rect.y=50
#item과 player 충돌 검사
hits_item=pygame.sprite.spritecollide(self,self.game.player_group,False,pygame.sprite.collide_mask)
if hits_item :
screen.blit(self.red_potion,(50,530)) #red1
screen.blit(self.blue_potion,(30,530))
screen.blit(self.blue_potion,(30,460))
screen.blit(self.blue_potion,(400,150))
screen.blit(self.red_potion,(850,100)) #red3
screen.blit(self.red_potion,(600,280)) #red4
screen.blit(self.red_potion,(800,400)) #red5
screen.blit(self.blue_potion,(600,370))
else:
#item__.item_display(self.screen)
draw_Objects(redItem)
this line
draw_Objects(redItem)
is looking for a global function named draw_Objects which does not exist. you need to call
self.draw_Objects(redItem)
However, you would also need to include self as a parameter in the function definition like so
def draw_Objects(self, myList=[]):
draw_Objects is not a global function, it is an attribute of the class and can be called with self.
def item_eat(self,screen):
item__=item(self)
#red2 item
self.rect.x=300
self.rect.y=50
#item과 player 충돌 검사
hits_item=pygame.sprite.spritecollide(self,self.game.player_group,False,pygame.sprite.collide_mask)
if hits_item :
screen.blit(self.red_potion,(50,530)) #red1
screen.blit(self.blue_potion,(30,530))
screen.blit(self.blue_potion,(30,460))
screen.blit(self.blue_potion,(400,150))
screen.blit(self.red_potion,(850,100)) #red3
screen.blit(self.red_potion,(600,280)) #red4
screen.blit(self.red_potion,(800,400)) #red5
screen.blit(self.blue_potion,(600,370))
else:
#item__.item_display(self.screen)
self.draw_Objects(redItem) # Change this line to reference draw_Objects
It's rather simple.
def draw_Objects(self):
myList=[]
for i in myList:
x=myList[i]
y=myList[i+1]
screen.blit(self.red_potion,(x,y))
i+=1
Then call it like:
self.draw_Objects()

What is a 'rect style object' and how do I implement it into my code?

I am trying to learn python by making a space game where you travel around the map fighting enemies(drones) that are randomly placed around the map. So far I have been successful in moving the playable spaceship around the map(with rotation), firing lasers, and blitting drones around the map(The drones follow the spaceship around). Though I don't entirely understand classes, I seem to have been able to pull it off so far.
Now, I want to input enemy hp with Laser/Drone collision. I gave the Drone class self.rect = self.image.get_rect() and called an instance of it in the Laser1 class using self.c = pygame.Rect.colliderect(drone.rect) but it just gives me this:
Traceback (most recent call last):
File "space.py", line 85, in <module>
blist.append(Laser1 (beamx, beamy))
File "space.py", line 79, in __init__
self.c = pygame.Rect.colliderect(drone.rect)
TypeError: Argument must be rect style object
I have searched a lot online for a way to fix this but I don't understand it much and nothing seems to work for me. Any help would be greatly appreciated!
Here is my code:
class Drone:
def __init__(self, dronex, droney):
self.x = dronex
self.y = droney
self.hp = dronehp
self.image = pygame.image.load("Androne.png").convert_alpha()
self.rect = self.image.get_rect()
dlist = []
for i in range(10):
dronex = random.randint(0, 7700)
droney = random.randint(0, 4520)
dronehp = 3
dlist.append(Drone (dronex, droney))
drone = Drone(dronex, droney) #-----------instance i think...
class Roid:
def __init__(self, roidx, roidy):
self.x = roidx
self.y = roidy
self.type = random.randint(0, 2)
rlist = []
for i in range(811):
roidx = random.randint(-1000, 9104)
roidy = random.randint(-800, 7200)
rlist.append(Roid (roidx, roidy))
class Laser1:
def __init__(self, beamx, beamy):
self.x = beamx
self.y = beamy
self.laser1 = pygame.image.load("laser1.png").convert_alpha()
self.rect = self.laser1.get_rect()
self.c = pygame.Rect.colliderect(drone.rect) #---line 79...
blist = []
for i in range(2):
beamx = batx
beamy = baty
blist.append(Laser1 (beamx, beamy)) #---line 85...
class Laser2:
def __init__(self, beamx2, beamy2):
self.x2 = beamx2
self.y2 = beamy2
self.laser1 = pygame.image.load("laser1.png").convert_alpha()
self.rect = self.laser1.get_rect()
self.c = pygame.Rect.colliderect(drone.rect)
b2list = []
for i in range(2):
beamx2 = batx
beamy2 = baty
b2list.append(Laser2 (beamx2, beamy2))
Also, this is my first question to ask on here. If there is anything I can do to make this question better do tell. I will except any and all feedback!
To answer the title: A rect style object is a pygame.Rect, a tuple or a list with 4 elements. So you can usually pass a 4-tuple or list to methods that expect a pygame.Rect as well.
As Paul Cornelius mentioned, the exception is raised because you use the colliderect method of the pygame.Rect class, but should instead use the colliderect of the self.rect instance.
self.c = self.rect.colliderect(drone.rect)
You can actually use pygame.Rect.colliderect directly and pass the two rects that you want to check, but that's unusual and would be a bit confusing for everyone else.
# `self.rect` is passed as the `self` argument.
self.c = pygame.Rect.colliderect(self.rect, drone.rect)
Paul Cornelius is in the right direction. Since you're learning python I'll explain briefly. The colliderect method is implemented in C:
static PyObject*
rect_colliderect (PyObject* oself, PyObject* args)
{
PyRectObject* self = (PyRectObject*)oself;
GAME_Rect *argrect, temp;
if (!(argrect = GameRect_FromObject (args, &temp)))
return RAISE (PyExc_TypeError, "Argument must be rect style object");
return PyInt_FromLong (DoRectsIntersect (&self->r, argrect));
}
Since you called it through the class definition and not an instance, drone.rect was assigned to oself by the python wrapper to this method, and args was probably assigned some equivalent of NULL. Hence the error message you saw (and not a 'missing required positional argument' as one would expect).
Don't have any experience with Pygame, but with a little searching it seems the problem you are having is a result of passing an improper argument to your pygame.Rect.colliderect() on line 79. The object you are passing the pygame.Rect.colliderect() method is not being read as a Rectangle object. Try printing the object drone.rect data and object type to see where the problem might be.

Pygame, inheritance issue

I am either new nor experience in python and i find myself in a fat problem that even after many hours in Google and Bing i can find the answer for. My problem starts with this code:
class Rectangulo(object):
def __init__ (self, x, y, color, largo, alto, cambio_x, cambio_y):
self.alto = alto
self.largo = largo
self.color = color
self.cambio_x = cambio_x
self.cambio_y = cambio_y
self.x = x
self.y = y
def dibujar(self):
pygame.draw.rect(pantalla, self.color, (self.x, self.y, self.alto, self.largo))
def mover(self):
self.x += self.cambio_x
self.y += self.cambio_y
class Elipse(Rectangulo):
def __init__(self):
Rectangulo.__init__(self)
def dibujar (self):
pygame.draw.ellipse(pantalla, Rectangulo.color,(Rectangulo.x, Rectangulo.y, Rectangulo.alto, Rectangulo.largo))
THis is the most important piece of code right now. I have find the problem laid in Elipse and have tried many ways to make the inheritance to work, but the console continue showing this message.
Traceback (most recent call last):
File "/home/josh/Escritorio/Codigo python/Jueguito.py", line 63, in <module>
miEl = Elipse(x,y,VERDE,alto,largo,cam_x,cam_y)
TypeError: __init__() takes 1 positional argument but 8 were given
Everytime i tried to call the class function dibujar() with this code:
for item in range(10):
x = random.randrange(685)
y = random.randrange(485)
alto = random.randrange(20, 71)
largo = random.randrange(20, 71)
cam_x = random.randrange(1, 2)
cam_y = random.randrange(-3, 3)
miObjeto = Rectangulo(x,y,VERDE,alto,largo,cam_x,cam_y)
miLista.append(miObjeto)
miEl = Elipse(x,y,VERDE,alto,largo,cam_x,cam_y)
miEl variable used to have their own for loop but i thought in this way would be less confusing for me. I still can't figure out what is happening. I fear i need some help.
Your Eclipse instance is failing to initialise, because when it calls the initialise of its base class Rectangulo, that class takes 7 parameters (x, y color, ... etc) and you aren't providing any.
So you have a number of options, but the two most common approaches would be:
Pass the same 7 params into Eclipse's __init__ method, and then pass those same params into the call to Rectangulo.__init__(self, ...)
Decide on the params to be used for the Rectangulo within the Elipse e.g. Rectangulo.__init__(self, 1, 2, "red", ...).
Generally speaking you will probably want the first option. e.g.
class Elipse(Rectangulo):
def __init__(self, x, y, color, largo, alto, cambio_x, cambio_y):
Rectangulo.__init__(self, x, y, color, largo, alto, cambio_x, cambio_y)
If your Elipse class needs no additional parameters of its own, then you can simplify the above a little by doing this:
class Elipse(Rectangulo):
def __init__(self, *args, **kwargs):
Rectangulo.__init__(self, *args, **kwargs)
This will basically pass any and all arguments given to the instantiation of Elipse through to the Elipse.__init__ call.

Categories