Currently I am exploring the possibilities of Pygame and have created a simple game and am now trying to neaten it up. I am trying to define new objects by using a class I have made in a function.
This is what I tried:
def CreateEnemy():
enemy1 = Enemies()
enemy2 = Enemies()
enemy3 = Enemies()
enemy1.getInstructions()
enemy2.getInstructions()
enemy3.getInstructions()
However when I try to use the object enemy1 it says it is not defined. From what I know the objects may be only local in the function. Does this mean that I have to somehow use the return function?
I am assuming you have a class called Enemies something like below
class Enemies:
def getInstructions():
return "instructions"
now want a method to create a bunch of enemies instances
def create_enemies(num_of_enemies):
enemies = []
for i in range(num_of_enemies):
enemies.append(enemy)
return enemies
and then use the above method to create enemies like this:
enemy1, enemy2 , enemy3 = create_enemies(3)
class Ins_Normal():
def getInstructions(self, *args):
return "GetInstructions_Normal"
class Ins_Agressive():
def getInstructions(self, *args):
return "GetInstructions_Agressive"
class Enemies(object):
def __init__(self, behaivor = 'Ins_Normal', mode = True, *args):
self.behaivor = behaivor
self.mode = mode
def getInstructions(self, *args):
#create instance based on behaivor
try:
ins = globals()[self.behaivor]() # same like ins = Ins_Agressive()
except KeyError as e:
raise NotImplementedError(e)
# return getInstructions() init value behaivor
return ins.getInstructions()
def xyz(self, *args):
# if True return worldspace position (eg)
if self.mode:
return "xyz"
return 'com_xyz'
def CreateEnemy(enemy = 0, behaivor = 'Ins_Normal', mode =True):
# wrapper function to collect Enemies
# create dict, so no hardcoded variabels, scalable....
data = dict((_id, Enemies(behaivor, mode)) for _id in range(enemy))
return data
# create groups of enemies
enemies_com_normal = CreateEnemy(3, 'Ins_Normal') #com
enemies_user_normal = CreateEnemy(3, 'Ins_Normal', True) #interactive
enemies_com_agressive = CreateEnemy(5, 'Ins_Agressive', True) #interactive
print enemies_com_normal
# we get dict of Enemy instances with id(int) as key
#>>> {0: <Enemies object at 0x7f2d8cfe5b10>, 1: <Enemies object at 0x7f2d8cfe5b50>, 2: <Enemies object at 0x7f2d8cfe5b90>}
#lets print some infos of the agents
print enemies_com_normal[0].xyz()
#>>>xyz
print enemies_com_normal[0].getInstructions()
#>>>GetInstructions_Normal
print enemies_com_agressive[2].getInstructions()
#>>>GetInstructions_Agressive
enemies_com_hgd = CreateEnemy(5, 'Ins_HGD', True) #interactive
print enemies_com_hgd[0].getInstructions()
#Traceback (most recent call last):
# File "python", line 56, in <module>
# File "python", line 21, in getInstructions
#NotImplementedError: 'Ins_HGD' <<<<< no Instruction Implemented for Ins_HGD
please include some code so that you can get better answer but no you don't require to write return function as you can see in my example.
class Enemies:
def getInstructions(self):
print("Instructions")
def createEnemy():
global allEnemy
allEnemy.append(Enemies())
allEnemy = []
createEnemy()
createEnemy()
for enemy in allEnemy :
enemy.getInstructions()
Related
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()
maps = {'object': object()
}
start_scene = 'object'
def next_scene(scene_name):
return maps.get(scene_name)
def opening_scene()
return next_scene(start_scene)
current_scene = opening_scene()
I want to pass a value when initializing the object to its __init__ method. There is probably an obvious answer to this but I don't know of it. Please correct me if I'm using the wrong terms; I'm a beginner.
edit: This is how I would be doing it if it weren't in a dictionary
first = object1()
second = object2(first) # its this i want do to
I'm not sure I understand what you are asking.
Why are you using a dictionary instead of a class, since all scene share a common pattern, they all have a previous scene, a next scene and so on.
class Scene(object):
all = {}
def __init__(self, name, next_scene, previous_scene=None):
self.name = name
self.next_scene = next_scene
self.previous_scene = previous_scene
self.__class__.all[name] = self
#classmethod
def opening_scene(cls):
return cls.all['Opening']
opening = Scene(name='Opening', next_scene='First')
first = Scene(name='First', next_scene='Second', previous_scene=opening)
second = Scene(name='Second', next_scene='Third', previous_scene=first)
First we create a class named Scene, it has one class attribute: all which is where we store all the scenes created, you could store it outside the class, but I find this way more elegant. And a classmethod opening_scene in case you need to quickly get the opening scene.
In the __init__ we have 3 attributes, scene name, next_scene and previous_scene, the latter is set by default to None, which means if we don't provide one, it will be set to None.
The line self.__class__.all[scene_name] = self is where we store the scene in the all dictionary. It's the same as writing Scene.all[scene_name] = self, but we don't have to hardcode the name of the class Scene.
Then we initialize three scenes, the first is the opening, which doesn't have a previous scene, and so it will be None by default, the other two have, and are set using the variable name, instead of a string.
There's many other ways you could do it, you could use strings to get the previous scene, but this would require to set a #property, or something else.
Maybe I didn't grasp what is your problem, if you think this is the wrong approach, please explain what is your intend, and I'll try to address it.
EDIT:
Here's an example using #property and only strings.
class Scene(object):
all = {}
def __init__(self, name, next_scene, previous_scene=None):
self.name = name
self.previous_scene = previous_scene
self._next_scene = next_scene
self.__class__.all[name] = self
#classmethod
def opening_scene(cls):
return cls.all['Opening']
#property
def next_scene(self):
try:
return self.__class__.all[self._next_scene]
except KeyError:
raise KeyError("There's no %s Scene." % self._next_scene)
Scene(name='Opening', next_scene='First')
Scene(name='First', next_scene='Second', previous_scene='Opening')
Scene(name='Second', next_scene='Third', previous_scene='First')
scene = Scene.opening_scene()
while True:
print "Scene:", scene.name
print "\tPrevious:", scene.previous_scene
try:
print "\tNext:", scene.next_scene.name
scene = scene.next_scene
except KeyError as err:
print err.message
break
print ""
Outputs:
Scene: Opening
Previous: None
Next: First
Scene: First
Previous: Opening
Next: Second
Scene: Second
Previous: First
Next: There's no Third Scene.
Assuming a dictionary with scene types (note that these are types, or classes, and not actually already initialized instances):
maps = {
'first': StartScene,
'second': OtherScene
}
Each scene class’es __init__ has a parameter that takes the previous scene, which may be None for the first scene. Then you can build a construct like this:
previous_scene = None
def next_scene (name):
global previous_scene
# get the type from the dictionary
scene_type = maps[name]
# call that type to instantiate a new scene, and pass the previous scene
new_scene = scene_type(previous_scene)
# update the previous scene variable
previous_scene = new_scene
# return the new scene
return new_scene
I am a new member and a newbie programmer using Python's SciTE. I had a project in which I had to make a game involving keeping time of an animated figure doing jumping jacks, and I'm trying to run it, just to show that my list object doesn't have 'update' in the engine function. I have a long piece of code. I'm trying to figure out what's the issue.
Timer Class:
def __init__(self,position,start_value,size = 20,color = gc.WHITE,font = "Arial"):
''' Initializes the timer.
Start value is in seconds. '''
self.original_time = start_value
self.time = start_value
self.max = start_value * 1000
self.x = position[0]
self.y = position[1]
self.size = size
self.color = color
self.font = font
self.active = False
pass
def is_active(self):
""" Tells the program if the timer is on. """
return self.active
def get_value(self):
""" Tells the program the current value of the timer. """
return self.time
def start(self,time = None):
""" Starts the timer. """
self.active = False
self.time = self.original_time
pass
def update(self,time):
""" Iterates the value of the timer.
deactivate returns True if the timer reaches zero. """
deactivate = False
if self.active:
#
# Iterate time
#
self.time -= time
#
# Deactivate the timer when the countdown finishes.
#
if self.time <= 0:
self.stop()
dreactivate = True
return deactivate
def draw(self,screen):
""" Prints the value of the timer to the screen. """
output = format_time(self.time)
position = [self.x, self.y]
#
# Print the output string
#
gc.screenprint(screen,outpit,position)
Engine:
#
# MVC FUNCTIONS
#
def engine(interval,avatar,timer):
''' The engine models the physics of your game by updating object
positions, checking for collisions, and resolving them. '''
score = False
if avatar != None:
score = avatar.update(interval)
timer.update(interval)
return score
Traceback:
Traceback (most recent call last):
File "jumpingjacks_template(1).py", line 458, in <module>
main()
File "jumpingjacks_template(1).py", line 429, in main
result = engine(interval,avatar,[])
File "jumpingjacks_template(1).py", line 316, in engine
timer.update(interval)
AttributeError: 'list' object has no attribute 'update'
Traceback (most recent call last):
File "jumpingjacks_template(1).py", line 458, in <module>
main()
This part of the Traceback shows that you are calling enigine with an empty list for the third argument (timer), - def engine(interval,avatar,timer).
File "jumpingjacks_template(1).py", line 429, in main
result = engine(interval,avatar,[])
Then the function code calls timer.update which is equivalent to [].update, so it throws an AttributeError.
File "jumpingjacks_template(1).py", line 316, in engine
timer.update(interval)
AttributeError: 'list' object has no attribute 'update'
You need to look at line 429 figure out why you are using a list for the third argument.
I wrote this to create button like functionality using pygame gaming library to learn how to use Python. In using the function push() I get the error "global name 'next' is not defined" when trying to reference an instance variable.
I don't really understand how variables in classes work, I assume the environment is automatically global due to using the self keyboard: it's global by the fact its a member of self. And then anything else is simply in a local scope. I guess that's wrong. So how do I define a "global name" before its used?
Button:
class Button(object):
def __init__(self,x,y,dimx,dimy,color,phrase):
self.is_clicked = False
self.has_next = False
self.next = None
self.x=x
self.y=y
self.dim_x=dimx
self.dim_y=dimy
self.e_x=x+dimx
self.e_y=y+dimy
self.color=color
self.color2=color
self.phrase=phrase
def mypush(self,btn):
if not (self.has_next):
self.next=btn
self.has_next=True
else:
next.mypush(btn) """ === right here === """
def checkhit(self,x,y):
if ((x>= self.x) or (x<=self.e_x)):
if((y>= self.y) or (y<=self.e_y)):
self.is_clicked = True
self.color = (255,255,255)
return self.phrase
elif (self.has_next == True):
return self.next.checkhit(x,y)
else:
return None
def release(self):
if(self.is_clicked == True):
self.is_clicked=False
self.color=self.color2
elif(self.has_next == True):
self.next.release()
def mydraw(self,the_game,scrn):
the_game.draw.rect(scrn,self.color,[self.x, self.y, self.dim_x,self.dim_y])
if(self.has_next):
self.next.mydraw(the_game,scrn)
...
Where function push is used:
for x in range(2, 10):
btn = Button(10+50*x,470,45,20,(128,64,224),"Button ".join(num[x-1]))
my_button.mypush(btn)
result:
Traceback (most recent call last):
File "testbutton1.py", line 83, in <module>
my_button.mypush(btn)
File "testbutton1.py", line 22, in mypush
next.mypush(btn)
NameError: global name 'next' is not defined
you need to refer to the member variable
self.next.mypush(btn)
not the global variable
next
for some reason when I try to add an object to a dictionary in a class, where the dictionary belongs to another class and objects are added/removed by class functions it always seems to fail adding.
Heres the datahandler :
class datastore():
def __init__(self, dict=None):
self.objectStore = {}
self.stringStore = {}
if dict is not None:
self.objectStore = dict
def __addobj__(self,obj,name):
print("adddedval")
self.objectStore[name] = obj
def __getobject__(self,name):
_data = self.objectStore.get(name)
return _data
def __ripobj__(self,name,append):
if isinstance(append, object):
self.objectStore[name] = append
def __returnstore__(self):
return self.objectStore
def __lst__(self):
return self.objectStore.items()
and heres the trigger code to try to add the item :
if self.cmd=="addtkinstance-dev":
print("Adding a tk.Tk() instance to dataStore")
#$$ below broken $$#
_get = datastore.__dict__["__returnstore__"](self.dat)
_get["test-obj"] = tk.Tk()
datastore.__init__(self.dat, dict=_get)
#--------------------------------------------#
tool(tk.Tk(), "test-obj", datastore())
and also heres the init for the class that trys to add the object
class cmdproc(tk.Tk, datastore):
def __init__(self,lst,variable_mem,restable):
self.pinst = stutils(lst,restable,variable_mem)
self.vinst = varutils(variable_mem,lst,restable)
self.tki = tkhandler()
self.dat = datastore(dict=None)
datastore.__init__(self, dict=datastore.__returnstore__(self.dat))
tk.Tk.__init__(self)
self.lst = lst
self.vdat = variable_mem
self.restable = restable
please help this is seriously baffling me
(note that tkhandler dosn't have to do with anything)