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.
[SPACE ESCAPE]-Game example to help with Game dev
-
@Karina said:
def setup(cls, *args): cls.main=args[0] cls.hud=args[1]
@stephen Here the args is a dict or you access like that first and sec arg?
*
is a wildcard list and**
is a wildcard key/val dict.you can use any name you want but he standard is
*args
and**kwargs
here im assuming there is a list index 0 and 1. a better way would of jusr using none
None
parmeters. -
@Karina i forgot to add that it doesnt have to be
args
you can almost use anything. for example:def func(*abc): for x in abc: print(id(x))
and somewhere call func passing objects as arguments
-
@mikeal im working on a singleton solution for EventManager and found a few different implementations. One didnt work lol but i wanted to see if you had any inglton suggestions
-
-
@stephen I read about *args **kwargs things, but they didn't say what it is, like list or dict. Now you wrote couple words about, not article, and I got what is itπ
I'm reading now your buttons, and you use there ui, but didn't import it. You can access ui through scene?
Also they not so explain in docs what the sender param is -
@stephen When I launch this it gives to areas of grey and black colors, but it should be blueπ€ Or not?
-
@stephen, Internet is indeed full of these.
Here is a very basic singleton implementation:
class EventManager: _instance = None def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance # For demonstration only @property def address(self): return id(self) assert EventManager().address == EventManager().address
You might need to be concerned about threads, in which case you would need a lock:
from threading import Lock class EventManager: _instance = None _lock = Lock() def __new__(cls): with cls._lock: if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance
If you think of creating millions of these, a little optimization minimizes the cost of acquiring the lock:
class EventManager: _instance = None _lock = Lock() def __new__(cls): if cls._instance is None: with cls._lock: if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance
Of course, you would also need to be aware of any threads you have when updating the event manager values.
-
-
@Karina said:
@stephen I read about *args **kwargs things, but they didn't say what it is, like list or dict. Now you wrote couple words about, not article, and I got what is itπ
im glad i was able to help with
*
and**
.
@Karina said:
I'm reading now your buttons, and you use there ui, but didn't import it. You can access ui through scene?
The
scene
modulewas built off of the
ui` module. both, if im correct, were created for Pythonista specifically. if you go into yourPython Modules
=>Standard Library (3.6)
=>site-packages
=>scene.py
you will see at the top:
#import 'pythonista' #coding: utf-8 from _scene2 import * import _scene2 from scene_drawing import * import math from numbers import Number from io import BytesIO import ui
_scene2
is the core modulescene_drawing
is aditional functionality- then
math
,numbers.Number
,io.BytesIO
are standard - and the
ui
module
when we used
from scene import *
this means everything π so we dont need to importscene_drawing
,math
,numbers.Number
,io.BytesIO
orui
.scene
does this for us.If you want you can still do your own import but it will still be the same instance a that was imported inside
scene
so theres really no need.@Karina said:
Also they not so explain in docs what the sender param is
wow im suprised the docs didnt cover this one.. but its really simple and ill show you an example i made of a
ButtonNode
i made to use withscene
that hould be very close to howui
uses it.When you create a
ui.Button
and set theaction
property and then Tap the button there are a few things that happends..first it changes to the
pressed
state that changes the image to visually how you di tap it. then it calls the function/method that you setaction
to and passesself
as the only argument.class ui.Button(ui.view): ... def _action(self): # some cool stuff self.action(self) # more cool stuff ...
this is why your Custome action needs
sender
now inside your custome action you can use sender to accesd the button you pressed
def button_tapped(sender): sender.superview.background_color = "blue"
this changes the color of the view that contains your button. π
here is the example for a button in scene..
import scene class EventHandler: children=[] event_loop=None @classmethod def add_child(cls, node): cls.children.append(node) if cls.event_loop == None: cls.event_loop = node.scene @classmethod def count(cls): return len(cls.children) @classmethod def touch_began(cls, touch): for child in cls.children: if cls.event_loop.point_from_scene(touch.location) in child.frame: child.Button_Tapped() class ButtonNode(scene.ShapeNode): def __init__(self, action, name=f'ButtonNode', bg_color='#d4d2ca', accessoryColor='#e80000', icon=None, accessory='emj:Exclamation_Mark_2', anchor_point=(0.5, 0.5), font_family='Helvetica', font_size=16, parent=None, position=(0, 0), size=(120, 45), corner_radius=8, border_size=20, borderColor='#000000', text='', text_color='#000000', tint='white', enabled=True, *args, **kwargs): self.x, self.y = position self.w, self.h = size super().__init__( path=scene.ui.Path.rounded_rect( self.x, self.y, self.w, self.h, corner_radius), fill_color=bg_color, stroke_color=borderColor, shadow=None, parent=parent, *args, **kwargs) EventHandler.add_child(self) self.icon=self._init_textures(icon) self.accessory=self._init_textures(accessory) self.border_size=border_size self.name=name + ' ' + str(EventHandler.count()) self.enabled=enabled self.text=text if text != '' else self.name self.tint=tint self.text_color=text_color self.borderColor=borderColor self.corner_radius=corner_radius self.showAccesory=False self.accessoryColor=accessoryColor self.parentNode=parent self.position=position self.size=size self.button_action=action self.anchor_point=anchor_point self.font_family=font_family self.font_size=font_size self.components=dict({ 'accessory':None, 'icon':None, 'label':None, 'width':None, 'height':None}) self._setup(self.icon, self.accessory, self.components) def _init_textures(self, img): if type(img) == str or type(img) == scene.ui.Image: return scene.Texture(img) else: return None def _setup(self, i, a, c): if a != None: c['accessory']=scene.SpriteNode( texture=a, size=(self.size[1]/4, self.size[1]/5*1.5), position=scene.Point(-self.size[0]/2+7, self.size[1]/2-10), parent=self, z_position=4, color=self.accessoryColor) if i != None: c['icon']=scene.SpriteNode( texture=i, size=scene.Size(self.size[1]/2, self.size[1]/2), position=scene.Point(self.w/2 - self.size[1]/3 , 0), parent=self, z_position=9) if self.text: c['label']=scene.LabelNode( text=self.text, font=(self.font_family, self.font_size), position=scene.Point(0 , 0), anchor_point=(0.5, 0.5), color=self.text_color, parent=self, z_position=10) def Button_Tapped(self): if self.components['accessory'].alpha > 0: self.components['accessory'].alpha = 0 if self.enabled: self.button_action(self) #--------------------------------------------------------------------------- def my_button_action(sender): print(f'{sender.name}: {sender.text}..') class main(scene.Scene): def setup(self): self.background_color='#f2f2f2' self.my_button_up=ButtonNode( text='', parent=self, position=scene.Point(self.size[0]/2, self.size[1]/2+100), action=my_button_action) self.my_button_right=ButtonNode( text='right', parent=self, position=scene.Point(self.size[0]/2+100, self.size[1]/2), action=my_button_action) self.my_button_down=ButtonNode( text='down', parent=self, position=scene.Point(self.size[0]/2, self.size[1]/2-100), action=my_button_action) self.my_button_left=ButtonNode( text='left', parent=self, position=scene.Point(self.size[0]/2-100, self.size[1]/2), action=my_button_action) def touch_began(self, touch): EventHandler.touch_began(touch) scene.run(main())
-
@Karina said:
@stephen When I launch this it gives to areas of grey and black colors, but it should be blueπ€ Or not?
im assuming your doing Episode 2 of the tutorial. if so your project should look like this at he end
if you are talking about the tutorial we should post questions on the respective thread so anyone in the future can see Q and A wihout having to hunt it down π
-
@mikael said:
@stephen, Internet is indeed full of these.
Here is a very basic singleton implementation:
class EventManager: _instance = None def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance # For demonstration only @property def address(self): return id(self) assert EventManager().address == EventManager().address
You might need to be concerned about threads, in which case you would need a lock:
from threading import Lock class EventManager: _instance = None _lock = Lock() def __new__(cls): with cls._lock: if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance
If you think of creating millions of these, a little optimization minimizes the cost of acquiring the lock:
class EventManager: _instance = None _lock = Lock() def __new__(cls): if cls._instance is None: with cls._lock: if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance
Of course, you would also need to be aware of any threads you have when updating the event manager values.
π€¦π»ββοΈ i wasnt calling
super().__new__(cls)
thank you! one more question, im not too familier withthreading
just yet with python.. isnt each Animation orAction
asynchronous and if so since im considering threading here should i make EventManager async aswell? or would the constant calls toupdate
create conflict?the size of this game wont matter too much but my next walkthrough game will be the RPG and the scale of that one will be much greater, limited to resource allocation from IOS. and i want to use the library created from this one on that to help others create thier personal
cookbook
orlibrary
-
@stephen cool designπ
And this is not thread of the tutorial? -
@stephen how did you learn scene and ui? Cause to me docs is not enough
-
@Karina said:
@stephen cool designπ
And this is not thread of the tutorial?this thread for the Example Game π. though it is the Topic the code and questions wont be quite the same. thats why im doing the Tutorial in small chunks. that way there is a thread for each and they wont get flooded with conversation from all over the place. everything should stay based on each "Episode". people in the future, or even right now, that are doing the tutorial may never see the questions you have asked and the answer to even one of your questions could of helped many people. but they cant if they are in the wrong Thread.. and thats a shame because you usually have really good questions!
Links to Tutorial:
At the top of each there is a link to the the Files for each.
-
For myself it was about 4 months of trial and error crash course. and every now and then i would find somthing on this forum (ill note that it was tough to find helpfull threads at the time because it was flooded with spam and general conversation Threads.. thanks to @ccc and a couple others they spent the time to filter the forums for everyone. so thats not an issue anymore βΊοΈ) and somtimes a thread on StackOverflow or GeeksForGeeks.. tdamdouni has a great repository of scripts that helped me alot and still do aswell.
That is why im doing this tutorial and why i made th Example.. To try and help th community Continue to grow and hopfully get some cool games along the way π..
-
@stephen I tried to do like an arrow here
class ButtonNode(SpriteNode): def __init__(self, img, action=None, text=None, parent=None, *args, **kwargs): super().__init__(self, img, *args, **kwargs)
But he tells me that in super().init should be 2 numbers. I don't understand what he means at allπ€·ββοΈ
-
@Karina said:
@stephen I tried to do like an arrow here
class ButtonNode(SpriteNode): def __init__(self, img, action=None, text=None, parent=None, *args, **kwargs): super().__init__(self, img, *args, **kwargs)
But he tells me that in super().init should be 2 numbers. I don't understand what he means at allπ€·ββοΈ
when used in a classbdeffenition, in this case
__init__
, super will gather the needed data from the current environment that it needs to define the instance. so here you dont pass self and super forSpriteNode
is expecting a string fortexture
(string is a sequence of characters) and not self. this automatic defining is why super is used. its called Cooperative Inheritance. as long as there is a super call in all base classes it allows for multiple inheritance without having to bother with explicitly defining who the parent or base class is. for example it would be more practical to made a button a ShapeNode that way you can add a border to the button without adding another sprite in the background by usingpath
. now if we had putsuper().__init__(*args, **kwargs)
and insured the correct args are passed we would just need to change the base class fomButtonNode(SpriteNode):
toButtonNode(ShapeNode):
and super would handle the rest. ππ -
@stephen So here better to put ShapeNode instead of SpriteNode?
-
-
@stephen Yes, I know, I copied it to my pythonista when you showed it. But there a lot of things, don't know from where to begin it. I just used to write more linear, so it's difficult for me to understand. But it goes slowly