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.
ui.Switch and Scene
-
Hi All,
Would love some help on this one! I've got the bare bones of a game I'm building here but I've hit a stumbling block.
What I have is a ui.View with a ui.Switch attached at the top to control flicking between two scenes embedded scenes ("MyScene" and "MyScene2"). I can get the switch to flick between the two scenes but what I can't do is get the "clear_game" function to run within each Scene. Essentially what I want is either; A) ability to run the "clear_game" function from within each scene when the ui.Switch value changes or, B) ability to completely restart each scene when the ui.Switch value is changed.
Code is below. I'm not sure if this is troublesome because I'm trying to call a function within a Scene from a different module i.e. ui.Switch? Or am I just having a 'mare, so to speak?
from scene import * from ui import * import canvas X,Y = ui.get_screen_size() W,H = (X-40)/3,(X-40)/3 Left = 20 Mid = int(Left+W) Right = int(Mid+W) Base = 150 Centre = int(Base+H) Top = int(Centre+H) Locations = [(Left,Top),(Mid,Top),(Right,Top),(Left,Centre),(Mid,Centre),(Right,Centre),(Left,Base),(Mid,Base),(Right,Base)] def Switch_Flicked(self): if switch.value==True: V.remove_subview(SV) V.add_subview(SV2) MyScene2.clear_game else: V.remove_subview(SV2) V.add_subview(SV) MyScene.clear_game class MyView(ui.View): def __init__(self, *args, **kwargs): ui.View.__init__(self, *args, **kwargs) class Squares(ShapeNode): def __init__(self, *args, **kwargs): ShapeNode.__init__(self, path=ui.Path.rect(0,0,W,H), stroke_color='#000000', anchor_point=(0,0), fill_color='#ffffff', **kwargs) class MyScene(Scene): def setup(self): self.background_color = '#4dc870' self.shape_list = [] for location in Locations: self.square = Squares(parent=self, position=location) self.square.line_width = 2 self.shape_list.append(self.square) def touch_began(self, touch): for shape in self.shape_list: if 0 < touch.location[0]-shape.position[0] < W and 0 < touch.location[1]-shape.position[1] < H: shape.color = '#065fa2' def clear_game(self): for shape in self.shape_list: shape.color = '#ffffff' class MyScene2(Scene): def setup(self): self.background_color = '#c84d93' self.shape_list = [] for location in Locations: self.square = Squares(parent=self, position=location) self.square.line_width = 2 self.shape_list.append(self.square) def touch_began(self, touch): for shape in self.shape_list: if 0 < touch.location[0]-shape.position[0] < W and 0 < touch.location[1]-shape.position[1] < H: shape.color = '#e5cc35' def clear_game(self): for shape in self.shape_list: shape.color = '#ffffff' switch = ui.Switch(action=Switch_Flicked, x=0, y=0) V = MyView(background_color='#ffffff') V.add_subview(switch) SV = SceneView(frame=(0,50,X,Y-100)) SV2 = SceneView(frame=(0,50,X,Y-100)) SV.scene = MyScene() SV2.scene = MyScene2() V.add_subview(SV) V.present()
-
In Switch_Flicked() you are missing parens after MyScene2.clear_game. If you make that MyScene2.clear_game() (add the parens to make the call) what happens?
I would rewrite as:
def Switch_Flicked(): old, new = SV, SV2 if switch.value else SV2, SV V.remove_subview(old) V.add_subview(new) MyScene2.clear_game()
-
Ah yes, I was missing the parentheses as I was playing around with it a bit. After correcting to MyScene2.clear_game() I get the error:
TypeError: clear_game() missing 1 required positional argument: 'self'
And when I run clear_game(self) I get the error:
ui.Switch object has no attribute "shape_list"
Obviously I was to be calling the shape_list attribute from the MyScene/MyScene2 object but am having trouble doing so.
-
Remove self from Switch_Flicked(). That is a pure function and is not a method of any class.
-
You are also calling clear_game as a method of the class and not the instance. Change e.g.
MyScene2.clear_game()
toSV2.scene.clear_game()
.In general, reserve uppercase for classes only, to avoid confusion.
-
And while we are at it, I would recommend having just one MyScene class, as they look functionally identical. Pass the varying bits like colors as arguments to
__init__
and store them inself
for use in other functions.If differing functionality is needed in the future, consider subclassing to add the diverging methods.
-
Thanks @mikael that's greatly appreciated. Problem solved!