im runing iPadOS 13.4 and i also cannot set the widget from settings. but i have no problem setting the widget using appex.set_widget_view()
.
i hope this helps you out until the bug is corrected!
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.
im runing iPadOS 13.4 and i also cannot set the widget from settings. but i have no problem setting the widget using appex.set_widget_view()
.
i hope this helps you out until the bug is corrected!
Here is a little game to help new develpoers to game design get started. there is a tutorial in exmples but its very minimal and doesnt give examples of diferent styles of writing. this currently is not a tutorial. and it is not flooded with comments so that its easier to follow the code. any questions are more than welcomeand i will add annotations as needed.
the game itssrlf is not perfect and does have bugs that pop up here and there. this is mainly due to using multiple styles at once creating small conflicts but the game does play and should be easy to expand nd add aditional components. i tried to leave it in a way that made it to whoever was using it could add functionality to help learn and understand game development. all images are builtin and script should run without any dependancies as long as its ran within Pythonista.
Enjoy
Stephen, Frey
@Karina @Drizzel here is a demo for action timing. i intended to have much more informative and visually attractive version and ill improve it in time but for noe you can see a visual difference between each interpolation.
note: this is formated for ipad only. future versions will have formatting for other devices. i appoligise.
from scene import *
class BaseSign(SpriteNode):
def __init__(self, texture=None, tag='Sign', *args, **kwargs):
super().__init__(texture=texture, *args, **kwargs)
self.anchor_point=(0.0, 1.0)
self.position = Point(10, get_screen_size()[1]-10)
self.z_position=1
self.color='#000000'
self.size=Size(get_screen_size()[0]-20, get_screen_size()[1]-20)
self.bg=SpriteNode(
texture=None,
color='#80cdff',
position=Point(3, -3),
anchor_point=(0.0, 1.0),
size=Size(get_screen_size()[0]-26, get_screen_size()[1]-26),
parent=self)
self.sign=LabelNode(
'',
position=Point(1, 15),
z_position=3,
font=('Ubuntu Mono', 18),
parent=self.bg,
color='#000000',
anchor_point=(0.0, 1.0))
class MyScene (Scene):
def setup(self):
self.dur=5
self.moveToPos=(73, 245)
self.sign=BaseSign(parent=self, position=self.size/2)
self.sign.sign.text=self.Text()
for x in range(16):
b=SpriteNode(Texture('pzl:BallGray'),
size=Size(16, 16),
color='#00f90b',
position=Point(73, (get_screen_size()[1]-132) - 36.15*x),
z_position=9,
parent=self)
b.run_action(
Action.repeat(
Action.sequence(
Action.call(self.UpdateTime, 0.1),
Action.wait(0.5),
Action.move_to(self.moveToPos[1], b.position[1], 2, x),
Action.move_to(self.moveToPos[0], b.position[1], 2, x)),-1))
def UpdateTime(self, node, progress):
if self.speed is 1:
self.speed=0.5
else:
self.speed=1
self.sign.sign.text=self.Text()
def Text(self):
return f'''
╔════════════════════════╗
║ BUILT_IN_CONSTANT ║
╠════╦════════╦══════════╣
║ 2s ║ 2 part ║ 1x speed ║
╠════╩════════╩══════════╣
║TIMING_LINEAR ║
╟═╡ ╞═╢
║TIMING_EASE_IN_2 ║
╟═╡ ╞═╢
║TIMING_EASE_IN_2 ║
╟═╡ ╞═╢
║TIMING_EASE_OUT ║
╟═╡ ╞═╢
║TIMING_EASE_OUT_2 ║
╟═╡ ╞═╢
║TIMING_EASE_IN_OUT ║
╟═╡ ╞═╢
║TIMING_SINODIAL ║
╟═╡ ╞═╢
║TIMING_ELASTIC_OUT ║
╟═╡ ╞═╢
║TIMING_ELASTIC_IN ║
╟═╡ ╞═╢
║TIMING_ELASTIC_IN_OUT ║
╟═╡ ╞═╢
║TIMING_BOUNCE_OUT ║
╟═╡ ╞═╢
║TIMING_BOUNCE_IN ║
╟═╡ ╞═╢
║TIMING_BOUNCE_IN_OUT ║
╟═╡ ╞═╢
║TIMING_EASE_BACK_IN ║
╟═╡ ╞═╢
║TIMING_EASE_BACK_OUT ║
╟═╡ ╞═╢
║TIMING_EASE_BACK_IN_OUT ║
╟═╡ ╞═╢
╚════════════════════════╝'''
if __name__ == '__main__':
run(MyScene(), show_fps=True)
@rownn i annotated with comments.
class MyTextView(ui.TextView):
def __init__(self, *args, **kwargs):
self.delegate = self
def begin_editing(self):
# forces keyboard to present
pass
def end_editing(self):
# forces keyboard to close
pass
def replace_range(self, range, text):
pass
### start of delegate methods ###
def TextView_should_begin_editing(self, textview):
# resize and reposition for keyboard
return True
def TextView_did_begin_editing(self, textview):
# keyboard presented
pass
def TextView_did_end_editing(self, textview):
pass
def TextView_should_return(self, textview):
# resize and reposition for no keyboard
textfield.end_editing()
# keyboard not presented
return True
def TextView_should_change(self, textview, range, replacement):
return True
def TextView_did_change(self, textview):
pass
heres is example of using brush like objects with scrolling nd random (not too random) spacing. if you have ny questions please ask!
@Drizzel thank you, i alwys try to help out tht way i get to learn kong the wy aswell 😎🤓🤓
from scene import *
import sound
import random
import math
A = Action
def w(): return get_screen_size()[0]
def h(): return get_screen_size()[1]
def MaxBrushSize(): return 10-2
def BaseBlock(parent):
return SpriteNode(Texture('plf:Tile_BoxItem_boxed'),
size=Size(64, 64), parent=parent,
anchor_point=(0.0, 0.0))
def Block(parent):
return SpriteNode(Texture('plf:Tile_BoxCrate_double'),
size=Size(64, 64), parent=parent,
anchor_point=(0.0, 0.0))
def Stone(parent, x):
return SpriteNode(Texture('plf:Tile_BrickGrey'),
size=Size(64, 64), parent=parent,
anchor_point=(0.0, 0.0), position=Point(x*64, 0))
class TopBrush(Node):
def __init__(self, brushSize, *args, **kwargs):
self.base=BaseBlock(self)
self.size=Size(64, 64)
self.position=Point(w()+(self.size.w), h()-self.size.h)
self.brushSize=brushSize
self.blocks=list([self.base, ])
for x in range(1, self.brushSize):
b=Block(self)
b.position=(self.base.position[0], self.base.position[1] - x*b.size[1])
self.blocks.append(b)
class BottomBrush(Node):
def __init__(self, brushSize, *args, **kwargs):
self.base=BaseBlock(self)
self.size=Size(64, 64)
self.position=Point(w()+(self.size.w), 0)
self.brushSize=brushSize
self.blocks=list([self.base, ])
for x in range(1, self.brushSize):
b=Block(self)
b.position=(self.base.position[0], self.base.position[1] + x*b.size[1])
self.blocks.append(b)
class MyScene (Scene):
def setup(self):
self.background=SpriteNode(Texture('plf:BG_Colored_grass'),
size=Size(w(), h()), position=self.size/2, parent=self)
self.preset=[(1, 7),(2, 6),(3, 5),(4, 4),(5, 3),(6, 2),(7, 1)]
self.i=0.0
self.brushSpawnTimer=3.0
self.brushes=list([])
self.scrollSpeed=40
for x in range(int((w()*128)/64)):
self.brushes.append(Stone(self, x))
def Add_Brush(self, choice):
if self.i > self.brushSpawnTimer:
bb=BottomBrush(choice[0])
tb=TopBrush(choice[1])
self.add_child(bb)
self.add_child(tb)
self.brushes.append(bb)
self.brushes.append(tb)
self.i=0.0
self.brushSpawnTimer = random.randrange(3, 6)
else:
sb=Stone(self, (w()+128)/64)
self.brushes.append(sb)
def Remove_Brush(self, brush):
self.brushes.remove(brush)
brush.remove_from_parent()
self.Add_Brush(random.choice(self.preset))
def did_change_size(self):
pass
def Scroll(self, brush):
x=brush.position[0]-self.scrollSpeed*self.dt
y=brush.position[1]
return Point(x, y)
def update(self):
self.i += self.dt
for brush in self.brushes:
if brush.position[0] <= -64:
self.Remove_Brush(brush)
brush.position = self.Scroll(brush)
def touch_began(self, touch):
pass
def touch_moved(self, touch):
pass
def touch_ended(self, touch):
pass
if __name__ == '__main__':
run(MyScene(), show_fps=False)
.txt
files.⏎
button to send user back to menu without having to reload Script.Scripts ↴
Scripts.txt
. on the first available empty line and paste unicode.:
script name:ABCDEFG...
Emoji and Symbold ↴
💪 ⟾ Emoji.txt
and ♳✯✟ ⟾ Misc.txt
place eachPremade Smilies ↴
Faces.txt
place each face on a single line.For seamless Use, change Script file name to Special Characters.py
and
place inside Examples/Keyboard/
replacing original script. This way will use
new Version instead without the need to Setup inside Pythonista settings.
.txt
filesfile name
inside Options.txt
—STEPHEN FREY
Included are two files for offline Resource for Unicode. Files are to large to open inside Pythonists and Editorial.
Attribution goes to OMZ, devloper of Pythonista
for providing IDE as well as the tools and original script for this Module!
Files located at github
pythonista Docs
def layout(self):
# This will be called when a view is resized. You should typically set the
# frames of the view's subviews here, if your layout requirements cannot
# be fulfilled with the standard auto-resizing (flex) attribute.
pass
often used to signal when screen orientation has changed.
also in scene
Module
def did_change_size(self):
pass
After many hours of thought and going over my cose a few times i fiund that since
I already released the Game Example Space Escape, its nearly pointless to do
a tutorial series on the same project.. That said i will be closing this one here
and i will create a new one.
Python RPG will cover at more aspects of game development.
and much more..
This new series will be done in sections due to the amount of code and testing we will
need. i will provide sprite sheets to help follow along, though i do encourage using your
own assets to help motivate yourself to push on. game development can get pretty stressfull
and even make you feel like its too hard. but keep pushing along and ALWAYS ask a question
if you have one!
Keep note that i will be writing this on my own and do have a life outside Python, at least i
like to think i do... so there might be gaps in time between sections and chapters. 🤓
@jackattack said:
Also the only bit I didn’t really understand was when you set up the button class you used init, but then you did spritenode.init what is this for?
when you subclass an object that has __init__
paramiters you must either call the Parent class __init__
as i did here or you can use super()
. if you do not call the parent's __init__
then the new object will not inherit the dirived.
@jackattack said:
I’ve learnt so much reading your code, love the way you’ve done so many things, spent ages going through it all. Could you give me any insight into the order you went about writing it?
I usually start with utility classes. in my Example game this would be stuff like Screen()
and EventManager()
, then visual testing. at this point i woud start my ButtonNode()
and Animations()
.. now i create my Player()
, GUI()
and o on. the order on the script itself doesnt matter with Object Orientated Programing (OOP) just remember the Interpreter exec the scripts top down. so in order to Dirive from from Class A it must exist before Class B.
@jackattack said:
Wow this works perfectly thank you so much, I’m going to take some time to study it and try to learn how to recreate it with some other effects. Thanks for taking the time out 😌
Not a problem at all! 🥂💯 i enjoy helping others if you have any equestions please dont hesitate!;
this ones an easy one 😁
for scene
module, Point
is a class that doesnt overide __call__
mqgic method. the position
attribute for a Node is a Point
object. so when you wrote:
new_snake.position(random.randint(0,1024), 768)
your calling on position lime it was a function.
what you shouldmofmdone is set the attribute instead of calling it.
new_snake.position = Point(random.randint(0,1024), 768)
here we are calling he __init__
methodm instead of the __call__
to create a new Point
object.
@Louise said:
self.run_action(Action.wait(1))
i do believe that wait cannot be called by itself. you must call a functional action also. but you can do a few things. you cqn use Action.call(func)
and leave it empty, or yu can use call and inside the called function/methos yiu can run the logic needed to end p,ayer tuen or start NPC turn.
alternatively instead of using run_action
you can use time.sleep(1.0)
though you might need to run this call on the main thread..
If your also using the ui
module there is ui.delay(func, seconds)
you wont need to import ui
because its aleady imported within scene
and accessible through your from scene import *
my favorite, but unnecessary, is creating a timer Node subclass and when you need a timer instantiate an instance of it seting duration and reduce time by Delta Time. when finished call a function set at creation.
i hope this helps. let us know if you need any further help buddy!
Here is a snippet from the Space Escape Demo I posted to help with this sort of thing. It's got a lot going on but it shows a good amount of Animation functionality.
def ForceField(self, speed, repeat=-1, t=TIMING_ELASTIC_IN_OUT):
def color_to(node, progress):
node.color='#09dfff' if random.random() < 0.5 else '#0016ff'
fade=[]
scale=[]
rotate=[]
for x in range(100):
val=random.random()
if val < 0.5:
val = 0.5
mod=random.random()
fade.append(a.fade_to(val-0.4, speed, t))
fade.append(a.call(color_to, 0.1))
if val < 0.6:
val = 0.8
rotate.append(a.rotate_by(val*5, speed, t))
scale.append(a.scale_y_to(val, speed, t))
scale.append(a.scale_x_to(val, speed, t))
self.node.run_action(
a.repeat(
a.group(
a.sequence(fade),
a.sequence(scale),
a.sequence(rotate)),
repeat))
@OkieWolf said:
def button3_tapped(sender):
sidea = float(v['textfield3'].text)I
sideb = float(v['textfield4'].text)
sidec = float(v['textfield5'].text)
if sidea is not None and sideb is not None
sidec = sidea + sideb
v['label1'].text = 'sidec = ' + str(sidec)
def button3_tapped(sender):
sidea = float(v['textfield3'].text)I # <= remove "I" typo
sideb = float(v['textfield4'].text)
sidec = float(v['textfield5'].text)
# checking if not None
if sidea and sideb: # <= you forgot your ":" statment closing
sidec = sidea + sideb
v['label1'].text = f'sidec = {sidec}' # changed to fstring
Also remember to use code format on posts 😀 thnk you!
```
import ui
import objc_util
def adaptivePresentationStyleForPresentationController_(_self, _cmd,
controller):
#### force the popover presentation style to stay as-is
return -1 # UIModalPresentationNone
def popoverDelegateCompletion(delegate):
if delegate._popview is not None and delegate._bgcolor is not None:
delegate._popview.background_color = delegate._bgcolor
if delegate._completion is not None:
delegate._completion()
delegate._popview = None
delegate._presented_block = None
def popoverPresentationControllerDidDismissPopover_(_self, _cmd, controller):
import objc_util
delegate = objc_util.ObjCInstance(_self)
popoverDelegateCompletion(delegate)
PopoverPresentationDelegate = objc_util.create_objc_class(
"PopoverPresentationDelegate",
methods=[adaptivePresentationStyleForPresentationController_,
popoverPresentationControllerDidDismissPopover_],
protocols=["UIPopoverPresentationControllerDelegate"])
def popover(sourceview, popview, presented=None, dismissed=None):
"""Create and display a popover modal view containing the given
content view, with a little arrow pointing at the given source view.
'presented' is called when the popover is first presented.
'dismissed' will be called when the popover is dismissed."""
def _closer(vc, delegate):
#### return a function object which will dismiss the popover
#### and restore the popview bg color, as well as call
#### any completion function
def _f():
vc.dismissViewControllerAnimated_completion_(True,None)
popoverDelegateCompletion(delegate)
return _f
#### find the view controller which is presenting the source view
#### this is what the popover arrow will point at
sourcevc = sourceview.objc_instance._findNearestViewController()
#### create a new modal view controller and set its presentation
#### style to the popover style, and size it to the content
UIViewController = objc_util.ObjCClass("UIViewController")
vc = UIViewController.new().autorelease()
vc.modalPresentationStyle = 7 # UIModalPresentationPopover
vc.preferredContentSize = objc_util.CGSize(popview.width, popview.height)
#### As of iOS 13+ popover presentation bounds include the little arrow
#### as part of the content area.
#### Since our popup content is designed to be displayed only in the
#### rectangular portion of the popover view, we constrain it to
#### the "safe area", which excludes the arrow.
safeView = objc_util.UIView.new().autorelease()
safeView.addSubview_(popview.objc_instance)
safeView.backgroundColor = objc_util.UIColor.clearColor()
vc.view = safeView
popview.objc_instance.translatesAutoresizingMaskIntoConstraints = False
guide = safeView.safeAreaLayoutGuide()
anchor = popview.objc_instance.leadingAnchor()
anchor.constraintEqualToAnchor_(guide.leadingAnchor()).active = True
anchor = popview.objc_instance.trailingAnchor()
anchor.constraintEqualToAnchor_(guide.trailingAnchor()).active = True
anchor = popview.objc_instance.topAnchor()
anchor.constraintEqualToAnchor_(guide.topAnchor()).active = True
anchor = popview.objc_instance.bottomAnchor()
anchor.constraintEqualToAnchor_(guide.bottomAnchor()).active = True
#### retrieve the popover presentation controller for the new modal
#### view controller, bail if that fails for some reason
popover = vc.popoverPresentationController()
if popover is None: return None
#### create and assign the popover presentation delegate
delegate = PopoverPresentationDelegate.new().autorelease()
delegate._completion = dismissed
delegate._popview = popview
delegate._bgcolor = None
popover.delegate = delegate
#### if the popview has a translucent background, make the
#### presenting view translucent instead, and the popview transparent,
#### save the original color to restore on dismissal.
color = popview.background_color
if color[3] < 1.0:
popview.background_color = "clear"
delegate._bgcolor = color
popover.backgroundColor = objc_util.UIColor.colorWithRed_green_blue_alpha_(*color)
popover.sourceView = sourceview.objc_instance
popover.sourceRect = objc_util.CGRect(objc_util.CGPoint(0,0),objc_util.CGSize(
sourceview.width, sourceview.height))
#### if a presentation function is provided, it is converted to an
#### objective-c block to be called when the popover is displayed
objc_f = None
if presented is not None:
objc_f = objc_util.ObjCBlock(presented, None, [objc_util.c_void_p])
delegate._presented_block = objc_f
#### present the view controller containing the popover content
#### via the popover presentation controller, using the
#### popover delegate we created, and return the close
#### function to allow caller to close the popover from code
sourcevc.presentViewController_animated_completion_(vc, True, objc_f)
return _closer(vc, delegate)
def showPopover(sender):
popview = ui.View()
popview.width = 200
popview.height = 100
popview.add_subview(ui.Label(text="Hello popover!", flex="WH"))
popover(sender, popview)
v = ui.View()
v.width = 300
v.height = 300
b = ui.Button()
b.title = "Show Popover"
b.action = showPopover
b.frame = (0,0,100,40)
b.center = v.center
v.add_subview(b)
v.present("sheet")
Here u go!
console.set_idle_timer_disabled(flag):
Disable or enable the idle timer (which puts the device to sleep after a certain period of inactivity).
console.is_in_background():
Return True if the app is currently running in the background, False otherwise.
im not familier with turtle
but i assume with the code you provided this is expected.. after addingba coupe lines and removing the assuming unneeded call to update and getting the current screen instead of making a new one i got it o draw.
import turtle
wn = turtle.getscreen()
wn.title("pong by zach")
wn.bgcolor("black")
wn.setup(width=800,height=600)
wn.tracer(0)
t=turtle.Turtle()
t.color('#23ff00')
live=1
while live:
t.forward(10)
if t.position()[0] > 150:
live=0
@Bumbo-Cactoni im not 100% on understanding exactly what you are going for so ive just beenthrowin stuff together to help ya out. ive been running under the assumption of a text editor lol thats why i included the undo funtionality, and currently playing around with a custom file picker.
as for your workaroud, @mikael was correct about history update. but you only needed to remove the history_view stuff you can keep the undo-redo stuff if you like. and i would suggest not storing history in a file unless yourvwanting to keep a log of changes. i say this because history is just the ontainer holding the diferent states of your text for undo-redo. and changes often and you wouldnt want to open and close a file lot to keep it updated.
The reason im doing this tutorial in episodes instead of all at once is so it can evolve over time so to help the community as best it can. that said we have our first contribution! after the fact of losing standard functionality of classes with python by not using Instances i ran a few tests and found that we can return the built in functionality while maintaining only a single instance by creating a Singleton. Attribution for this Episode goes to @mikael for helping improve quality
main focus this Episode will be converting our
EventManager
into a singleton."The singleton pattern is a design pattern that restricts the instantiation of a class to one object."
we add the magic Dunder method__new__
so we can set our classmethod_instance
so we can maintain the singleton status by returningcls._instance
ifcls._instance
is notNone
to__init__
.
class EventManager:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, *arg, **kwargs):
self.main=None
self.hud=None
self.game_state=None
def start(self, main, hud):
self.main=main
self.hud=hud
self.game_state=GameState.MAIN_MENU
self.main.view.hidden=True
self.hud.add_subview(MainMenu())
def update(self, dt):
pass
def touch_began(self, touch):
pass
def touch_moved(self, touch):
pass
def touch_ended(self, touch):
pass
In
Main
we grab a refernce toEventManager
fromHUD
class Main(Scene):
def setup(self):
self.event_manager=self.view.superview.event_manager
def did_change_size(self):
pass
def update(self):
self.event_manager.update(self.dt)
def touch_began(self, touch):
self.event_manager.touch_began(touch)
def touch_moved(self, touch):
self.event_manager.touch_moved(touch)
def touch_ended(self, touch):
self.event_manager.touch_ended(touch)
Inside HUD lets ceate our initial instance of
EventManager
since this is our Top Level Object. then after setting ourSceneView
we call start forHUD.event_manager.start
whichmain
andhud
insideHUD.event_manager
and set our game state andin turn present our main menu.
class HUD(ui.View):
def __init__(self, *args, **kwargs):
self.background_color='#66492a'
self.event_manager=EventManager()
# Game Window
self.main = SceneView(
scene=Main(), frame=(5, 5, Screen.x-10, Screen.y-10),
anti_alias=True, frame_interval=1,
shows_fps=True, background_color='#2c00ff')
self.add_subview(self.main)
self.event_manager.start(self.main.scene, self)
We will call it here for this one and it wont feel like we did anything but in the long run this Episode will help our project 10-fold.