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.


    (How to) Spritesheet subtexture

    Pythonista
    spritesheet texture subtexture
    2
    7
    5963
    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.
    • Sketo
      Sketo last edited by

      I finally found out how to use the Texture.subtexture() to get a portion of a spritesheet on the scene. Now, after the initial setup of the subtexture, I'm having trouble figuring out how to change the position of the shown section to a new section after the initial setup.
      Do I have to create individual SpriteNodes for each section of the spritesheet? I'm hoping there is an easier way.
      Im hoping there is a way to update the coordinates in subtexture(Rect(?,?,?,?)) to show a new portion of the spritesheet.

      If anyone knows how to do this I would appreciate any help. Thank you!

      from scene import *
      
      
      class MyScene (Scene):
      	def setup(self):
      		self.background_color = 'black'
      		
      		self.sprite_sheet = SpriteNode()
      		
      		self.sprite_sheet.position = self.size / 2
      		self.sprite_sheet.scale = 2
      		
      		self.sprite_sheet.texture = Texture('plc:Gem_Orange').subtexture(Rect(0,0,.5,.5))
      		self.add_child(self.sprite_sheet)
      		
      	def touch_began(self, touch):
      		pass
      		
      		
      	def Update(self):
      		pass
      		
      		
      
      run(MyScene(), show_fps = True)```
      1 Reply Last reply Reply Quote 0
      • omz
        omz last edited by

        You basically have to create a separate Texture object for each portion of the sprite sheet. Don't worry about memory; textures generated by subtexture are very light-weight. They basically just store a reference to the actual texture (sprite sheet), and a couple of coordinates.

        Sketo 2 Replies Last reply Reply Quote 0
        • Sketo
          Sketo @omz last edited by

          @omz Thank you for your reply. I was hoping it would be easier, sense it is only a reference to a section of the sprite sheet. It seams as though you could just change the reference coordinates to show a different part without having to make a new object. But again thank you for clearing this up for me.

          1 Reply Last reply Reply Quote 0
          • Sketo
            Sketo @omz last edited by Sketo

            @omz Another question if you don't mind. Update should change from gem_texture[0], in setup, to gem_texture[3], in update(). Its not changing it... is this not possible or am I missing something?

            from scene import *
            
            gem_texture = [
            Texture('plc:Gem_Orange').subtexture(Rect(0,.5,.5,.5)),
            Texture('plc:Gem_Orange').subtexture(Rect(.5,.5,.5,.5)),
            Texture('plc:Gem_Orange').subtexture(Rect(0,0,.5,.5)),
            Texture('plc:Gem_Orange').subtexture(Rect(.5,0,.5,.5)),
            ]
            
            class MyScene (Scene):
            	def setup(self):
            		self.background_color = 'black'
            		self.gem = SpriteNode(gem_texture[0],
            		scale = 4,
            		position = self.size / 2,
            		parent = self)
            		
            	def touch_began(self, touch):
            		pass
            		
            	def update(self): #Fixed case correction
            		# Update should change from gem_texture[0], in setup, to gem_texture[3], in update(). Its not changing it... is this not possible or am I missing something?
            		self.gem.texture = gem_texture[3]```
            1 Reply Last reply Reply Quote 0
            • omz
              omz last edited by

              @Sketo The problem seems to be a typo. Your method is called Update (upper case), but it should be update (lower case).

              Sketo 1 Reply Last reply Reply Quote 0
              • Sketo
                Sketo @omz last edited by

                @omz WOW do I feel dumb. Thank you. I feel terrible for wasting your time for something so small but thank you again.

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

                  It took me a while to figure out how to use a spritesheet but I finally figured it out. I wanted to post a small example that shows how it works. If I had something like this at the beginning when I was looking then I would not have wasted so much time searching and trying to figure it out. As a beginner just starting to understand these ideas, I want to help those like me searching for hours trying to find an example that makes it easy to understand for beginners.
                  I hope this helps the next new comer.

                  The Rect(?,?,?,?) parameter describes the portion of the texture in unit coordinates, e.g. (0, 0, 0.5, 0.5) would create a texture from the bottom-left quarter of the original texture. (0,0) being the bottom left corner to half of the overall height (.5) of the texture and half of the overall width (.5) of the texture.

                  from scene import *
                  x,y,xs,ys = 0,0,1,1
                  # 🔼 Above sets up the initial subtexture(Rect(x,y,xs,ys)) on line 25 to show the full image until touch_began and touch_ended changes the coordinates of the subtexture to show whatever section you set in touch began.
                  
                  class MyScene (Scene):
                  	def setup(self):
                  		self.background_color = 'black'
                  		
                  		self.texture_name = SpriteNode(Texture('test:Mandrill'),
                  		scale = 2, 
                  		position = self.size / 2,
                  		parent = self)
                  		
                  	def touch_began(self, touch):
                  		global x,y,xs,ys #These variables must be referenced as global or they will not be recognized.
                  		
                  		x,y,xs,ys = 0,0,.5,1 #This changes the coordinates for update() on line 25 to show a portion of the texture.
                  	
                  	def touch_ended(self, touch):
                  		global x,y,xs,ys #These variables must be referenced as global or they will not be recognized.
                  		
                  		x,y,xs,ys = 0,0,1,1 #This changes the coordinates back to show the full image when you stop touching the screen.
                  		
                  	def update(self):
                  		self.texture_name.texture = Texture('test:Mandrill').subtexture(Rect(x,y,xs,ys))
                  		#This updates the Texture according to the cooridantes set by touch_began (line 17) and touch_ended (line 22).
                  		
                  
                  run(MyScene())```
                  
                  One of the things that was making it hard for me to understand was that after initially setting up the Texture, on line 9, I thought you could simply reference the subtexture() directly like this...
                  
                  self.texture_name.texture.subtexture = Rect(?,?,?,?) OR self.texture_name.subtexture = Rect(?,?,?,?)
                  
                  ... but this was not working and it racked my brain for a while. Then I tried this...
                  
                  self.texture_name.texture = Texture('test:Mandrill').subtexture(Rect(?,?,?,?))
                  
                  ... and found out that you must set, not just the subtexture, but the Texture and subtexture to the variable (self.texture_name.texture) before it's updated.
                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post
                  Powered by NodeBB Forums | Contributors