Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello β I'm @olemoritz on Twitter.
[SOLVED] Scene Update for all gameobjects help
-
Hello Everyone!
I have been using Pythonista and Eitorial for some time now and nytime i ad an issue i would usually find a solution, or path to one, here with yall. After all this time i cannot find an nswer anywhere.. the net is flooded with pygame but i only use iPad air2 and iPhone6s.
Heres what i got..
- i have a Core class that every other class inherits from. this has info such as
- Device info
- Global setting such as Scaling for Retina, screen resolution...
- Update, start and awake methods fore init order control. (update does nothing currently)
- and so on..
i need the update method to sync with game loop so all objects have the same timing. i know i can do the folowing...
from scene import * A = Action class GameObject(Node): def __init__(self, *args, **kwargs): #Node.__init__(self, *args, **kwargs) self.position = Point(10, 10) self.velocity = 30 def update(self, dt): self.position= (self.position[0] + self.velocity * dt, self.position[1] + self.velocity * dt,) class GameLoop (Scene): def setup(self): self.go = GameObject() self.add_child(self.go) def update(self): self.go.update(self.dt) . if __name__ == '__main__': run(GameLoop(), show_fps=False)
but i fel that doing so for all gameobjects is a bad idea lol..
example above is just that lol i think its silly but best Example i could come up with.
I thought of trying to make a metaclass that runs a loop but i'm not sure how that structure would work.
Any Help is VERY much appreciated!
P.S. Pythonista is a wonderful App and has help myself get through alot lately. please keep it going and keep up the outstanding work @omz!
- i have a Core class that every other class inherits from. this has info such as
-
There is nothing wrong with that approach. That is how many of the examples are written -- you keep a list of objects, and each run an update function.
Depending on what you are doing, you could also make use of Actions.
-
@JonB Thanks for the reply.
Im wanting to have the scene class implicitly include all instances of GameObject.
this game will be openworld and have MANY gameobjects and id hate to write hundreds of line statingobject_name.update(self.dt)
πi guess i could have a metaclass form a this list you say and then iterate that in update?
-
Just gave the metaclass direction and no success. i was able to easily control exec order for
awake()
andstart()
though the metaclass would always make a new scene loop fore each subclass.example
one of the attempts
class meta(type): @classmethod def awake(cls): return @classmethod def start(cls): return @classmethod def update(cls, dt): return @classmethod def __prepare__(metacls, name, bases, **kwds): class GameLoop (Scene): def setup(self): pass def update(self): metacls.update(self.dt) run(GameLoop()) return collections.OrderedDict() def __new__(cls, name, bases, namespace, **kwds): result = type.__new__(cls, name, bases, dict(namespace)) result.awake() ...some attr... result.start() return result class Core(metaclass=meta): def __init__(self): pass def update(self, dt): pass
I feel like there is a simple aproch to doing this but its just out of reach..
-
@stephen, sorry for being slow, but I do not yet quite get what you are trying to accomplish. Donβt the Nodes already support defining update methods that run in sync, without needing to be explicitly called?
-
@mikael well πΆ i actually have not tried let me run a quick test.
but to answer your question..
yes im wanting to have a single loop that EVERY GameObject that gets created inherits.
-
@mikael No Sir they do not automatically link. i even tried subclassing EffectsNode.
-
@stephen, can you please reiterate the design goal? Is it that you need to:
a) explicitly control the order every game object gets updated in
b) have global awake, stop methods affecting all objects
c) all objects to have access to the same core configurationWhat do you exactly mean by βneed to have all objects have the same timingβ?
-
I was saying you simply have something like this
def update(self): for node in self.children: if hasattr(node, 'update') and callable(node.update): node.update()
You could actually do something like this via a class decorator
def auto_update_children(cls): originalupdate = cls.__dict__.get('update') # Possibly None. def update(self): for node in self.children: if hasattr(node, 'update') and callable(node.update): node.update() #finally, if the class already had an update... call it. so you can define classes with an update method, it will update children, then call your specific code.. if callable(originalupdate): originalupdate(self) setattr(cls, 'update',update) return cls @auto_update_children class Game(Scene): def update(self): #do any specific game logic... children have all been update'd when this gets called check_collsitions() etc() #...
Likewise, you could then use said decorator on different "layers" that manage their own game state and children.
The other approach is that you don't have to literally call update on every object. You probably have classes of objects -- player, enemy, projectiles, powerups, whatever.
Keep those as lists inside your scene, and then loop through the lists.
The advantage of that is you can do things like check collisions of every enemy with player, or projectiles with player.def add_enemy(self): enemy = EnemyNode(....) # ... some code to add a random enemy... self.enemies.append(enemy) self.add_child(enemy) def add_projectile(self, initial_position, initial_velocity): projectile = Projectile(initial_position, initial_velocity) self.projectiles.append(projectile) self.add_child(projectile) def update(self): for enemy in self.enemies: enemy.update() player.update() for projectile in self.projectiles: projectile.update() if projectile.bbox.intersects(player.bbox): #kill player, ...
So, you don't have to have a separate named object for everything in your scene, you have categories of objects that get added so that they can start being updated.
-
I would be happy to π
ill draw out a mini-version.
class Core: def __init__(self, *args, **kwargs): self.awake() self.w, self.h=get_screen_size() self.screenScale=get_screen_scale() ...and so on... self.start() def awake(self): pass # exec before any attrs are set def start(self): pass # exec afer attrs but before returned def update(self): pass # needs to update from here for all gameobjects class GameObject(Core): def __init__(self, id=None *args, **kwargs): Core.__init__(self, *args, **kwargs) self.id=id class Actor(GameObject): def __init__(self, isHostile=False, speed=30, id=None, *args, **kwargs): GameObject.__init__(self, id=id, *args, **kwargs) self.isHostile=isHostile self.speed=speed self.position=(0,0) class Deer(Actor): def __init__(self, loot=[], isHostile=False, speed=50, id=100, *args, **kwargs): Actor.__init__(self, isHostile=isHostile, speed=speed, id=id, *args, **kwargs) self.loot_inventory=loot self.spawn_location=None self.health_points=None def awake(self): self.spawn_location=(456, 987) def start(self): self.health_points=100 def update(self): self.position=(...)
###In the example
- Core holds the initial
awake()
,start()
andupdate()
methodsawake()
is called before any base Attributes are set.start()
is called after all base attributes are set but before Instance is returnedupdate()
needs to provide loop for All Subclasses of Core.. so all GameObjects.
- now we work our way down to
Deer()
where we use the exec timing methods to set everything as needed.
I know i can just drop ref to every object in the Scene subclass but im trying to find a way to do this implicitly at
Core()
or before..ive tried A handfull of approches including metaclass and nothing seems to do this other than manually placing hundreds+objects in the
update()
of Scene subclass.I will be more than happy to give any information to help, been on this solo project for nearly a year now and im at a stand still till i get this resolved.
- Core holds the initial
-
Now thats what im talking bout!
i believe i shale give a combination of entity goups and Cls decorater..
Thank you!
i will be sure to post wether this solves my issue! -
Rereading your question ... I guess maybe I read more into your question than you originally wanted...
class GameLoop(Scene): def __init__(self): self.go_list = []; def add_gameobject(self, go): self.go_list.append(go) self.add_child(go) def remove_gameobject(self,go): #... remove from go_list and remove_child def setup(self): for i in range(40): self.add_gameobject( GameObject() ) def update(self): for go in self.go_list: go.update()
Doesn't something like this accomplish what you are after, without a lot of muss & fuss?
Now, I think you could accomplish various types of physics behaviours using decorators -- for instance, you could have a projectile decorator which simply takes current velocity and adjusts position. Then, you could have a affected_by_gravity decorator which adjusts velocity in each time step by g*dt in y. A bouncy decorator that looks for collisions and then inverts velocity, etc. Each decorator would have the form
def affected_by_gravity(cls): originalupdate = cls.__dict__.get('update) def update(self, dt): self.velocity[1] = self.parent.gravity * dt if callable(originalupdate): originalupdate(self,dt) setattr(cls,'update',update) return cls
then you could have
@affected_by_gravity @projectile_physics @bouncy class Ball(ShapeNode): def __init__(self): pass
-
i feel you first example hold the solution but i do know i will be looking into these decorators more. ive always went around them cuz thry feel uncomfortable. i normaly only programmed in .net on platforms like unity and unreal.
-
@JonB, agree on the first half of your post. Thanks for taking the time to make examples.
Regarding bullet physics and all that, would seem like recreating SpriteKit.
-
Thank you!! i REALLY appreciate the effort! ππ»ππ»
this community has always got me in the right direction. hopefully this rpg will be play-test ready in roughly 6-8 months (im doing everything alone art, story, coding... so bare with me lol) and as it moves along ill try to post updates and functional "builds" that way you all can throw some input in. when it is fully completed i plan to host it on app store but i will be providing copies for group of you that have been aiding me along the way with python. i never thought i would be able to do this level of coding on a mobile device. lol thank you again and again @omz amazing work on Pythonista!