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.


    Where is the bug?... in .update(self.dt)

    Pythonista
    4
    10
    6110
    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.
    • david
      david last edited by ccc

      Hello everyone.

      I'm trying to adapt the card game shown below to the Pythonista 3, but I find a bug that I am unable to resolve. It appears in the "draw" function and the error is "init() missing 4 required positional arguments: r, g, b, a,...". Some clue?

      Best regards

      # Card Game
      #
      # In this game, you have to find matching pairs of cards.
      # This scene consists entirely of layers and demonstrates some
      # interesting animation techniques.
      
      from scene import *
      from random import shuffle
      from functools import partial
      import sound
      
      class Game(Scene):
      	def setup(self):
      		self.root_layer = Layer(self.bounds)
      		for effect in ['Click_1', 'Click_2', 'Coin_2', 'Coin_5']:
      			sound.load_effect(effect)
      			
      		self.deal()
      		
      	def draw(self):
      		background(0.0, 0.2, 0.3)
      		self.root_layer.update(self.dt)  ### bug???
      		self.root_layer.draw()
      		
      	def deal(self):
      		images = ['Rabbit_Face', 'Mouse_Face', 'Cat_Face',
      		'Dog_Face', 'Octopus', 'Bear_Face',
      		'Chicken', 'Cow_Face'] * 2
      		for image in images:
      			load_image(image)
      		shuffle(images)
      		self.root_layer.sublayers = []
      		self.cards = []
      		self.selected = []
      		card_size = 96 if self.size.w > 700 else 64
      		width = (card_size + 5) * 4
      		offset = Point((self.size.w - width)/2,
      		(self.size.h - width)/2)
      		for i in range(len(images)):
      			x, y = i % 4, i // 4
      			card = Layer(Rect(offset.x + x * (card_size + 5),
      			offset.y + y * (card_size + 5),
      			card_size, card_size))
      			card.card_image = images[i]
      			card.background = Color(0.9, 0.9, 0.9, 1)
      			card.stroke = Color(1, 1, 1, 1)
      			card.stroke_weight = 4.0
      			self.add_layer(card)
      			self.cards.append(card)
      		self.touch_disabled = False
      		
      	def touch_began(self, touch):
      		if self.touch_disabled or len(self.cards) == 0:
      			return
      		if len(self.selected) == 2:
      			self.discard_selection()
      			return
      		for card in self.cards:
      			if card in self.selected or len(self.selected) > 1:
      				continue
      			if touch.location in card.frame:
      				def reveal_card():
      					card.image = card.card_image
      					card.animate('scale_x', 1.0, 0.15,
      					completion=self.check_selection)
      				self.selected.append(card)
      				self.touch_disabled = True
      				card.animate('scale_x', 0.0, 0.15,
      				completion=reveal_card)
      				card.scale_y = 1.0
      				card.animate('scale_y', 0.9, 0.15, autoreverse=True)
      				sound.play_effect('Click_1')
      				break
      				
      	def discard_selection(self):
      		sound.play_effect('Click_2')
      		for card in self.selected:
      			def conceal(card):
      				card.image = None
      				card.animate('scale_x', 1.0, 0.15)
      			card.animate('scale_x', 0.0, 0.15,
      			completion=partial(conceal, card))
      			card.scale_y = 1.0
      			card.animate('scale_y', 0.9, 0.15, autoreverse=True)
      		self.selected = []
      		
      	def check_selection(self):
      		self.touch_disabled = False
      		if len(self.selected) == 2:
      			card_img1 = self.selected[0].card_image
      			card_img2 = self.selected[1].card_image
      			if card_img1 == card_img2:
      				sound.play_effect('Coin_5')
      				for c in self.selected:
      					c.animate('background', Color(0.5, 1, 0.5, 1))
      					self.cards.remove(c)
      					self.selected = []
      					if len(self.cards) == 0:
      						self.win()
      						
      	def new_game(self):
      		sound.play_effect('Coin_2')
      		self.deal()
      		self.root_layer.animate('scale_x', 1.0)
      		self.root_layer.animate('scale_y', 1.0)
      		
      	def win(self):
      		self.delay(0.5, partial(sound.play_effect, 'Powerup_2'))
      		font_size = 100 if self.size.w > 700 else 50
      		text_layer = TextLayer('Well Done!', 'Futura', font_size)
      		text_layer.frame.center(self.bounds.center())
      		overlay = Layer(self.bounds)
      		overlay.background = Color(0, 0, 0, 0)
      		overlay.add_layer(text_layer)
      		self.add_layer(overlay)
      		overlay.animate('background', Color(0.0, 0.2, 0.3, 0.7))
      		text_layer.animate('scale_x', 1.3, 0.3, autoreverse=True)
      		text_layer.animate('scale_y', 1.3, 0.3, autoreverse=True)
      		self.touch_disabled = True
      		self.root_layer.animate('scale_x', 0.0, delay=2.0,
      		curve=curve_ease_back_in)
      		self.root_layer.animate('scale_y', 0.0, delay=2.0,
      		curve=curve_ease_back_in,
      		completion=self.new_game)
      		
      run(Game())
      
      
      
      1 Reply Last reply Reply Quote 0
      • ccc
        ccc last edited by

        Older scene programs were based on the Classic Rendering Loop.

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

          There is a point too much in your code.

          self.root_layer.update(self.dt)_ ### bug???
          
          1 Reply Last reply Reply Quote 0
          • ccc
            ccc last edited by ccc

            After you match two tiles, the script will fail in the way that @david suggests.

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

              I did run your your code now. The reason why the script raises the exception is a namespace conflict in pythonistas scene namespace. If you follow the trace you will see that the exception is raised at scene_drawing.py line 253:

              ...
              ... isinstance(self.to_value, Color):
              253			value = Color()
              ...
              

              The Color type does not support a parameterless constructor anymore. There is nothing you can do because the file scene_drawing is read only (you could circumvent that but that does not seem to be a good idea). You would have to change value = Color() to something like value = Color(1, 1, 1, 1).

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

                This seems to be a bug in recordtype... or should I say an incompatibility with Python 3.

                In py3:

                		cls.__init__.im_func.func_defaults = init_defaults
                should be
                 		cls.__init__.__defaults__= init_defaults
                
                1 Reply Last reply Reply Quote 0
                • david
                  david last edited by

                  Hi all... Yes, the "problem" appears in the line "253 value = Color()" in scene_drawing.py

                  Following the line that says @ccc, I understand that I have to change the "classic rendering loop" by "Node/Action" ... any suggestions?

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

                    you could also just monkey patch Color:

                     _scene_types.Color.__init__.__defaults__=(0,0,0,0)
                    
                    1 Reply Last reply Reply Quote 0
                    • ccc
                      ccc last edited by ccc

                      Based on @JonB suggestion above, these lines fixed things...

                      try:      # Python 3
                          Color.__init__.__defaults__ = (0, 0, 0, 0)
                      except AttributeError:
                          pass  # Python 2
                      
                      1 Reply Last reply Reply Quote 0
                      • david
                        david last edited by

                        Nice. This work. Thank you!

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