omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    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.


    Flappy bird

    Pythonista
    4
    81
    25217
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • stephen
      stephen @Karina last edited by stephen

      @Karina

      Outstanding work so far! im very impressed on how fast you are grasping this.

      first ill answer your questions ๐Ÿค“


      what the difference between w() and self.size.w?

      In my example w() is recieving the width size of the screen directly. self.size.w is reference to the current Node's width. Yes when used inside your Subclass of scene.Scene this will be the same value. but this is only becasue you are initiating its View by using the module level run() function. (run always launches in fullscreen). but in the future you may notwant fullscreen and this means you would use a custom ui.View class then add a SceneView to it. now if you use the w() function you will get screen width as expected but now your self.size.w will return a different value referencing the SceneView's frame (frame โ‡จ Tuple(x, y, width, height)) you can also retrieve this uing MySceneView.frame[2]. in our case i didnt needto use the w() function but we practice how we wantto playon game day. ๐Ÿ˜Ž good habets produce great programs.


      MaxBrushSize just returns 8??

      yes i know the return 10-2 seems useless. but maybe down the road you want to create, lets say, powerups. one might be the gaps get larger bfor n seconds. since we already have this in out code all we need to do is make a quick change.. this would be the replacement โฅฅ

      	def MaxBrushSize(mod):
      		return 10 - mod
      

      then somwhere in your code you you add somthis similar to this

      	...
      	def StartGapPowerUp(self, value ):
      		self.maxBrushSize = MaxBrushSize(value)
      		time.sleep(10) #waits 10 seconds
      		self.maxBrushSize = MaxBrushSize(default)
      	...
      

      ive been playthingwith game development for many years in multiple languges so i have built some habits that i dont notic i do anymore lol.



      next post will be some notes nd pointers of you latest code posted and ill put a script showing my previous answeres in action! stay tuned ๐Ÿค“๐Ÿค“

      1 Reply Last reply Reply Quote 0
      • Karina
        Karina last edited by Karina

        1. self.point=Point(w() + self.position.w, h() - self.size.h)
        If w() and self.size.w are the same here, then we got 2*self.position.w? And why instead of sec arg don't just right 0??

        2. When I tried to use sleep(), my screen just got black and I couldn't close it. And also was a problem and it all hang and didn't move. I did smth and fixed it, don't know how๐Ÿ˜…. But why theese things can happen?

        I have hundred of questions on each couple lines)

        stephen 2 Replies Last reply Reply Quote 0
        • stephen
          stephen @Karina last edited by stephen

          @Karina

          '''
          I realized i didnt fully implemate Brushes and that might have been confusing.
          so ill post a new script using actual brushes. 
          
          and as a bonus for showing you actually want to learn and not just copy/paste 
          ill add some extra functionality for your 'cookbook'. 
          
          
          i do apologise about the amount on notations lol there beingbalot of comments
          doesnt mean its a bd script. most is advice. i did change a few things mostly
          for your convenience and to smooth out animation.
          
          but first here is some notes on hat you have provided thus far..
          '''
          from scene import *
          import random
          import time
          
          
          A = Action()
          
          '''
          i added these so you only have one place to change sizes instead of
          bouncing around
          	sw โ‡’ screen width
          	sh โ‡’ screen height
          	bw โ‡’ block width
          	bh โ‡’ block height
          	so โ‡’ screen orientation
          	lw โ‡’ level view port width
          	lh โ‡’ level view port height
          '''
          
          
          def sw(): return get_screen_size()[0]
          def sh(): return get_screen_size()[1]
          def bw(): return 64
          def bh(): return 96
          def so(): return 1 if sw() < sh() else 2
          def lw(): return 1024 if so() is 2 else 768
          def lh(): return 1024 if so() is 1 else 768
          
          
          
          def Ground(parent):
              return SpriteNode('plf:Ground_Grass', parent=parent, size=Size(bw(), bh()))
             
          
          
          def ColumnBlock(parent):
              return SpriteNode('plc:Brown_Block', parent=parent, size=Size(bw(), bh()))
          
          '''
          not sure what happened here but as you 
          probably know if called wil throw exceptions. 
          im assuming this is why you dont actually use it.
          
            self.position = (self.size.w)
          
          first a regular Node object hase no size property.
          BUT it has a bbox wich is a scene.Rect with a width value. 
          even with that said a poisition property much recieve a 
          2 Tuple (x, y) preferably a Point object but not neccesary.
          	i.e:
          		self.position = Point(x, y)
          let me know if your having a problem here it seem as your
          trying to use self to refer to your Scene class. and you can.
          but not through self. if your not sure how self work i can tell
           u jut say
          '''
          class BottomBrush(Node):
              def __init__(self):
                  self.ground = GroundBlock(self)
                  self.position = (self.size.w)
                 
              
          class Game(Scene):
              def setup(self):
                  self.background_color = '#99d7ff'
                  #to track when 5 seconds passed and need to add a new column
                  self.time_passed = 0
                  #add the first column so you don't have to wait for it 5 seconds
                  self.columns = []
                  self.add_column()
                  x = 0
                  ground = Node(parent=self)
                  
                  #building the upper and lower ground
                  '''
                  	Generally a while loop is not a very big deal but in this
                  	case its not a great idea.
                  	i say this because what if for some unknown reason
                  	self.size.w is somthing crazy like 2389488754589433357. 
                  	๐Ÿค“๐Ÿ˜… unlikely i know but just for fun...
                  	now your game is hung up seeming like it is frozen to end user.
                  	now a for loop, at least i feel, is much safer in this. matter.
                  	but to be honest.. a premade pillar object would be best use. ill 
                  	show this in next post. 
                  '''
                  while x < lw()+bw():
                      lower_tile = SpriteNode('plf:Ground_Grass', 
                      	position=Point(x, 0), size=Size(bw(), bw()), anchor_point=(0.5, 0.0))
                      higher_tile = SpriteNode('plf:Ground_GrassCenter', 
                      	position=Point(x, lh()), size=Size(bw(), bw()))
                      x += bw()
                      ground.add_child(lower_tile)
                      ground.add_child(higher_tile)
                      
                  self.speed = 1 # Node.speed is defaulted to 1.0
                  '''
                  changed z_position to keep to and bottom over blocks
              	'''
                  ground.z_position = 999
              def update(self):
                  self.time_passed += self.dt
                  '''
                  good job with >= hen comparing floats in this manner never use ==
                  
                  sence your calling self.column_moves() every frame we can manually
                  move our blocks. (see method comment)
                  # note: changing "5" to eithere a random int or an instance property
                  	will  alow a more dynamin level generation.
                  '''
                  if self.time_passed >= 5:
                      self.add_column()
                      self.time_passed = 0
                  self.column_moves()
                      
                      
              def add_column(self):
              	
                  lower = random.randint(1, 360) // bw()
                  higher = 9 - int(lower)
                  #building the lower part
                  y = 35
                  '''
                  here you can get rid of the variable "lower"
                  this should reduse memory use. for this game it
                  doesnt matter but in future it could make a diference. 
                  use this instead..
                  
                		  for i in range(random.randint(0, 360) // 64):
                  	
                  this insures the memory is released after forloop.
                  
                  also i would suggest moving 
                  		block.anchor_point = (0.5, 0)
          			        		and
          			    block.position = (self.size.w, y)
                  to your ColumnBlock function like this
                  	
          	        def ColumnBlock(parent, x, y):
          	    		return SpriteNode('plc:Brown_Block',
          						    		anchor_point=(0.5, 0),
          						    		position=Point(x, y),
          						    		parent=parent)
          						    		
          		then in your for loop make your "i" var useful and get rid of "y"
          		
          			for i in range(lower):
          	            self.columns.append(ColumnBlock(self, self.size.w, i*64))
          	            
          		now we dont add a new block to memory then copy to list.  we
          		just add one to list and memory at same time.
                  
                       anchor_point is values 0 to 1 
                       0 being botom left a 1 being top/right
                       (1, 1) would be top right
                       (0.5, 0.5) would be center.
                       changed block.size.h to 1.0
                  '''
                  for i in range(1, lower+1):
                      block = ColumnBlock(parent=self)
                      block.anchor_point = (0.5, 0.5)
                      block.size= Size(bw(), bh())
                      block.position = (lw(), bh()/3+i*bw())
                      
                      block.z_position = -i
                      self.columns.append(block)
                      y += bw()
                  #building the higher part
                  y = lh()
                  for i in range(1, higher+1):
                      block = ColumnBlock(parent=self)
                      block.anchor_point = (0.5, 0.5)
                      block.position = (lw(), (lh()-i*bh()/2))
                      block.z_position = i
                      self.columns.append(block)
                      y -= bh()
                      
              '''
              great work on this part only sugestion would be to set your interp timing.
              probably TIMING_SINODIAL  in this case cuz its mich smoother than linear.
              and this will go where you have "30/self.speed". and this oddly doesnt thow
              an excption and id avoid "0" for duration. 0.1 seems fast enough. or even 
              0.01 if needed. so somthing like ths.
              
              		A.move_by(-self.size.w, 0.1, TIMING_SINODIAL)
              		
              you also dont need remove. this is meant o remove objects not Actions.
              sinve you pass none or () its does nothing.
              
              one more thing the "self.speed is used to modify Action speed. but its 
              automatically implemented. to if you want a 2x animation speed just set
              self.speed = 2  and everything else is done for you."
              
              you also should useba Node object to group the sprites this way theres
              no need for the for loop. you just move the parent and child nodes will
              follow.
              i changed the folowing method so that it stops the "jerking"bwhen it 
              moves. they now move smoothly
              
              ::from update comment::
              with that all said, lets be nice to our cpu and instead of runing an Action 
              proccess lets just do some simple math. im not changing thisone but i would 
              write the following:
              	#note: i wouldnt do this for every block i would group the colums (โ—•_โ—•) 
          		#note: velocity would be set inside startup/__init__ and can be used
          		#      with powerups โ˜บ๏ธ
              	for i in self.columns:
                      i.position = Point(
                      	i.position[0] - self.velocity*self.dt, i.position[1])
              	
              '''
              
              def column_moves(self):
                  actions = [A.move_by(-self.size.w/2, 1, TIMING_SINODIAL)]
                  for i in self.columns:
                      i.run_action(A.sequence(actions))
                          
                      
          '''
          dont forget you can set some properties when calling the  "run()" function
          
          scene.run()
          ## you know this one lol ##
          	โ‘ด scene
          ## alloud orientations. 
          -	FROM DOC: Important: The orientation 
          -	parameter has no effect on iPads starting with iOS 10 because
          -	it is technically not possible to lock the orientation in an app
          -	that supports split-screen multitasking. ##
          	โ‘ต orientation=DEFAULT_ORIENTATION 
          ## frame rate controle
          	FROM DOC: By default, the sceneโ€™s update() method is called 60
          	times per second. Set the frame_interval parameter to 2 for 
          	30fps, 3 for 20, etc. ## 
          	โ‘ถ frame_interval=1
          ## this game wont need but here you go
          	FROM DOC: Set this to True to enable 4x multisampling. This has
          	a (sometimes significant) performance cost, and is disabled by
          	default. ##
          	โ‘ท anti_alias=False
          ## explains itself. i tent do make my own so i can control the 
          	color and position. ##
          	โ‘ธ show_fps=False
          ## you shouldnt need this for this game if kept simple
          	โ‘น multi_touch=True
          	)
          '''
          run(Game())
          
          # now to write that version two example for u. and again great work!
          
          
          1 Reply Last reply Reply Quote 0
          • stephen
            stephen @Karina last edited by stephen

            @Karina said:

            1. self.point=Point(w() + self.position.w, h() - self.size.h)
            If w() and self.size.w are the same here, then we got 2*self.position.w? And why instead of sec arg don't just right 0??

            2. When I tried to use sleep(), my screen just got black and I couldn't close it. And also was a problem and it all hang and didn't move. I did smth and fixed it, don't know how๐Ÿ˜…. But why theese things can happen?

            I have hundred of questions on each couple lines)

            1.

            self.point=Point(w() + self.position.w, h() - self.size.h) If w() and self.size.w are the same here, then we got 2self.position.w? And why instead of sec arg don't just right 0??*

            self.position.w should be self.position.x
            translated self.point=Point(w() + self.position.w, h() - self.size.h) means
            Node's Position is a Point Object with x coordinate at screen width plus node's position x and y coordinate at screen height minus nodes hieght.

            or in other words

            x = screen_width + self.position.x
            y = screen_hieght - self.size.hieght
            self.position = Point(x, y)

            2.

            When I tried to use sleep(), my screen just got black and I couldn't close it. And also was a problem and it all hang and didn't move. I did smth and fixed it, don't know how๐Ÿ˜…. But why theese things can happen?

            this was my fault lol i forgot you need to att a decorator from ui module

               @ui.in_background
                def add_column(self):
                    time.sleep(5)
            

            this will run sleep on a different thread than your scene

            1 Reply Last reply Reply Quote 0
            • stephen
              stephen last edited by stephen

              @Karina

              never too many questions

              1 Reply Last reply Reply Quote 0
              • stephen
                stephen last edited by

                @Karina now im off to write the game in the way i would. so you can compare. in no way is MY way the best or even the most correct. but it is the way i learned to implement different objects and functionality over the years.

                1 Reply Last reply Reply Quote 0
                • stephen
                  stephen last edited by stephen

                  @Karina just an update ive been a bit busy but i might have my project ready in the next 20 hours or so. it wont have a lot of comments but ill put a few. but im trying to use only descriptive naming so it should not beva problem.hope to see what you learned from this project ๐Ÿค“๐Ÿค“๐Ÿค“

                  1 Reply Last reply Reply Quote 0
                  • Karina
                    Karina last edited by

                    @stephen said:

                    self.point=Point(w() + self.position.w, h() - self.size.h) <

                    Ah, I forgot that we're inside Node, not Scene

                    i understand what lw() does, but what is lower port width? And lw() is the returns the width, if add bw(), we should get beyond the screen?

                    self.size.w is somthing crazy like 2389488754589433357

                    I went to check the self.size.w, and it is 1024. What do you it is smth like that๐Ÿ‘†? And why in that case for is better than while?

                    stephen 1 Reply Last reply Reply Quote 0
                    • stephen
                      stephen @Karina last edited by

                      @karina said:

                      @stephen said:

                      self.point=Point(w() + self.position.w, h() - self.size.h)
                      Ah, I forgot that we're inside Node, not Scene

                      i understand what lw() does, but what is lower port width? And lw() is the returns the width, if add bw(), we should get beyond the screen?

                      Response:

                          sw โ‡’ screen width
                          bw โ‡’ block width
                          lw โ‡’ level view port width
                      

                      top part and lower part , at least in this case, are the same size width. so both top and bottom parts get their size width from our bw() Block Width.
                      Yes we do want to add AT LEAST block width past screen width.
                      Video Games are Feuled by immersion. You wand the End User to feel that our Level already exists.. so they must not see the objects pop into our level. so we do this just outside the view port. same for removinghe objects. we wait till they are at least Block Width negative position if block.w < -block.w: del block.
                      Also in our position checks we want to compare < for removing blocks and > for adding blocks and not <= and >=. by doing this we get a 1 point buffer insuring our create and delete actions are not visible bo End User.


                      @karina said:

                      @stephen said:

                      self.size.w is somthing crazy like 2389488754589433357

                      I went to check the self.size.w, and it is 1024. What do you it is smth like that๐Ÿ‘†? And why in that case for is better than while?

                      Response:

                      โ€œ ๐Ÿค“๐Ÿ˜… unlikely i know but just for fun... โ€

                      the value 2389488754589433357 this game is simple so this shouldnt happen. you coud see similar if you had bad execution order while using large open world type game environment...

                      since python has a GIL Global Interpreter Lock both the for and the whie loops are "blocking" and both can be used to achive hat you want.. The only prolem i can see making the for loop better choice here is that a while loop has the possibility of being infinit if somthing doesnt go right where the for loop has a predefined end point. insuring the game will not freeze forever do to your code withen.



                      did i cover what you were confused for these? im not sure i completey understook your questions. ๐Ÿ™ƒ

                      1 Reply Last reply Reply Quote 0
                      • Karina
                        Karina last edited by Karina

                        I thought of grouping the blocks but don't know how to do it.

                        It's quite difficult to me to formulate them now cause I don't have anything to write on and can't buy it๐Ÿ˜ฟ But:

                        I don't know what the timing_sinodial, timing_ease in and others mean. I tried to play with them in examples but didn't see the difference, also anti-alias and its 4x multisampling
                        And the Brushes, so didn't implement it and MaxSizeBrush, but maybe I will when do the jumps

                        1 Reply Last reply Reply Quote 0
                        • stephen
                          stephen last edited by stephen

                          @Karina ill whip up a quick example that will show the diferences and ill Annotate as much as i can ๐Ÿ™ƒ hang tight

                          what do you mean you have nothing to write on?

                          1 Reply Last reply Reply Quote 0
                          • Karina
                            Karina last edited by

                            @stephen a notebook or smth and I wouldn't have to look what was in the beginning and had important things in front of me

                            stephen 1 Reply Last reply Reply Quote 0
                            • stephen
                              stephen @Karina last edited by

                              @Karina said:

                              @stephen a notebook or smth and I wouldn't have to look what was in the beginning and had important things in front of me

                              what are you using currently? and im sorry im taking so long to get back but i read overball the comments and im not sure i covered all the questions before. do you still not understand how the following works?

                              • w()
                                -update(self)
                                -self.dt
                                -self
                                -self.size.w
                                -lw()

                              my final example full game will include all these and more but i dont want you to throw a full script at you unless you can comprehend a good amount. most of what has been covered has been mostly linear and the full script ill feel like a spider web lol but ill annotate as much as i can.

                              1 Reply Last reply Reply Quote 0
                              • Karina
                                Karina last edited by

                                w()
                                -update(self)
                                -self.dt
                                -self
                                -self.size.w
                                -lw()

                                This yes, here it looks quite easy.
                                I'm trying to write for now like I can, though it's not the best way and I get annoying bugs sometimes
                                What it means that it all was linear?

                                the full script ill feel like a spider web lol but ill annotate as much as i can.

                                Wow I'm scared

                                1 Reply Last reply Reply Quote 0
                                • Karina
                                  Karina last edited by Karina

                                  @stephen You said @in_background makes smth run on a dif thread. I'm not into the ui for now, but what is the dif thread?

                                  stephen 2 Replies Last reply Reply Quote 0
                                  • stephen
                                    stephen @Karina last edited by

                                    @Karina what i mean by linear is the scripts are writen in a step by step manner. and then the rest is all focused inside the loop body. just a way i refer to simple writing techniques. where alternatively i tend write in a manner that jumps around. multiple inheritence, conroller types, delegates.. and so on.

                                    @karina said:

                                    @stephen You said @in_background makes smth run on a dif thread. I'm not into the ui for now, but what is the dif thread?

                                    ui.in_background() decorator executes the following process in the main thread instead of on your current event loop's. whenever you call module level run() function from scene or class method View.Present()from ui you create a new event loop separate from Interpreters main thread. Python uses GIL (Global Interpreter Lock) that only alows one thread. you can still use multiprocessing though. for info on that check out Asynchronous programming. the reason for GIL is objC memory managment is not considered "Thread Safe".

                                    Docs said:

                                    ui.in_background(fn):

                                    Call a function on the main interpreter thread. This is useful to perform long-running tasks from an action or delegate callback without blocking the UI. It can also be used for functions that donโ€™t support being called from the main UI thread (e.g. console.alert()).

                                    as far as you not using the ui module... you have been this whole time.. lol scene uses ui quite heavely. and you dont need to import ui separatly. by using from scene import * ui is also included. from your game just call ui. and then whatever you want from there. when you run your scene game it actually prepares the ui stuff for you and then presents a SceneView if you setup a custom View class in your game script you can create a scene.SceneView and set its SceneView.scene property to your Game Object. then instead of using run(MyScene()) you present the View which places your game in its own frame on your screen making it easy to add ui objects as your gui for ur game.

                                    1 Reply Last reply Reply Quote 0
                                    • stephen
                                      stephen @Karina last edited by

                                      @Karina and im almost finished with the Animation/Actions demo. should be posted later this evening.

                                      currently 5pm my time

                                      1 Reply Last reply Reply Quote 0
                                      • Karina
                                        Karina last edited by

                                        @Karina and im almost finished with the Animation/Actions demo. should be posted later this evening.
                                        currently 5pm my time

                                        ๐Ÿ‘

                                        1 Reply Last reply Reply Quote 0
                                        • Karina
                                          Karina last edited by ccc

                                          def touch_began(self, touch):
                                          		sound.play_effect('arcade:Jump_4')
                                          		self.player.texture = player_textures[3]
                                          		jumping = [A.move_by(0, 100, 0.2), A.wait(1), A.move_by(0, -100, 0.1)]
                                          		self.player.run_action(A.sequence(jumping)
                                          

                                          I tried to make him jump but it doesn't work. I know there should be a more clever way to do that but I have no idea

                                          1 Reply Last reply Reply Quote 0
                                          • Drizzel
                                            Drizzel last edited by

                                            @Karina I havenโ€™t used Actions much, I prefer animating nodes myself. But theoretically, from reading the docs, your code should work (assuming your indentation is correct and your actual code doesnโ€™t miss the closed bracket at the end)

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            Powered by NodeBB Forums | Contributors