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.


    SpriteNode.texture issue

    Pythonista
    2
    6
    3587
    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.
    • Auer
      Auer last edited by

      I have what I believe to be a simple question..... how do i get the last line of code here to work.

      tile.texture=current_tile
      

      tile is a SpriteNode Object thing, and the current tile is just a png

      I'm attempting to edit a tilemap of SpriteNodes.... I'm quite clueless as all of my programming i learned in pygame.

      from scene import *
      import random
      import ui
      
      A = Action
      g1 ='g1.PNG'
      g2 ='g2.PNG'
      g3 = 'g3.PNG'
      g4='g4.PNG'
      g5='g5.PNG'
      tb='toolbar.PNG'
      
      
      all_tiles=[g1,g2,g3,g4,g5]
      tiles=[g1,g2,g1,g3,g4,g5,g2,g1]
      current_tile=g1
      
      mapsize=100
      
      themap=[[] for _ in range(mapsize)]
      
      class Arrow (SpriteNode):
      	def __init__(self, **kwargs):
      		SpriteNode.__init__(self, 'arrow.PNG', **kwargs) 
      			
      class MyScene (Scene):
      	def setup(self):	
      		self.unit=20
      		unit =self.unit
      		self.items=[]
      		self.points=0
      		#states of buttons
      		self.edit_mode=False
      		self.recenter_gravity=0,0,0
      
      
      		
      		self.background_color = '#000000'
      		sizex,sizey=self.size
      		self.ground = Node(parent=self)
      		
      		self.gen_map()
      		
      		#player
      		self.ship = SpriteNode('p1.PNG')
      		self.ship.size=(unit,unit)
      		self.ship.position = self.size / 2
      		self.add_child(self.ship)
      		
      		#__________BUTTONS&UI_____________
      		self.toolbar=SpriteNode('toolbar.PNG')
      		self.toolbar.size=(unit*16,unit*2)
      		self.toolbar.position=(unit*8,unit)
      		self.add_child(self.toolbar)
      		
      		self.edit_button=SpriteNode('emj:Wrench')
      		self.edit_button.size=(unit*2,unit*2)
      		self.edit_button.position=(unit,unit)
      		self.add_child(self.edit_button)
      		
      		self.re_center=SpriteNode('emj:Anger_Symbol')
      		self.re_center.size=(unit*2,unit*2)
      		self.re_center.position=(unit*3,unit)
      		
      		self.selected=SpriteNode(g1)
      		self.selected.size=(unit*2,unit*2)
      		self.selected.position=(unit*8,unit)
      		self.draws=SpriteNode('emj:Black_Nib')
      		self.draws.size=(unit*2,unit*2)
      		self.draws.position=(unit*6,unit)
      		
      		
      		self.tree = SpriteNode('leaves.PNG')
      		self.tree.size=(unit*3,unit*3)
      		#self.add_child(self.pb)
      		
      		#text on screen
      		self.score= LabelNode('0')
      		self.score.position=10,sizey-10
      		self.add_child(self.score)
      		
      		
      		
      		
      	def update_map(self):
      		sizex,sizey=self.size
      		self.ground.position.x
      		for _ in themap:
      			for tile in _:
      				
      				if tile.position.x+self.ground.position.x>=-self.unit and tile.position.y+self.ground.position.y>=-self.unit and tile.position.x+self.ground.position.x<= sizex +self.unit and tile.position.y+self.ground.position.y<= sizey+ self.unit:
      					tile.z_position=-1
      					self.ground.add_child(tile)
      				else:
      					tile.remove_from_parent()
      					
      	def gen_map(self):
      		sizex,sizey=self.size
      		unit=self.unit
      		#laggyyyy if multi press!!!
      		for _ in themap:
      			for tile in _:
      				tile.remove_from_parent
      				
      		#themap=[[] for _ in range(mapsize)]
      		#generate a random map
      		y=-unit/5
      		zpos=mapsize
      		ypos=0
      		for _ in range (mapsize):
      			
      			x=-unit
      			y+=unit*2
      			for _ in range (mapsize):
      				
      				x+=unit*2
      				tile = SpriteNode(random.choice(tiles), position=(x, y),)
      				tile.size=unit*2,unit*2
      				tile.z_position=zpos
      				themap[ypos].append(tile)
      			zpos-=1
      			ypos+=1
      			
      	def place_tree(self,xy):	
      		self.tree.position=xy-self.ground.position
      		self.tree.z_position=2
      		
      		self.ground.add_child(self.tree)
      		
      	def projectile(self,x,y):
      		ammo = Arrow(parent=self)
      		ammo.size=self.unit*2,self.unit*2
      		ammo.position = (self.ship.position)
      		#ammo.rotation=self.ship.rotation
      		actions = [A.move_to(x,y,1,6), A.remove()]
      		ammo.run_action(A.sequence(actions))
      		ammo.rotation=self.ship.rotation
      		self.items.append(ammo)
      		
      	def check_ammo_collisions(self):
      		sizex,sizey=self.size
      		for ammo in self.items:
      			if ammo.position in 	self.pb.frame:
      				self.items.remove(ammo)
      				ammo.remove_from_parent()
      				self.points+=1
      				self.pb.position=random.randint(0,sizex),random.randint(0,sizey)
      				
      	def update(self):
      		self.update_map()
      		self.check_ammo_collisions()
      		#self.score.text=str(self.points)
      		
      		#save old posotion
      		pos=self.ground.position
      		posx,posy=pos
      		
      		sizex,sizey=self.size
      		x, y, z = gravity()
      		#adjust for held angle of device
      		xx,yy,zz = self.recenter_gravity
      		x-=xx
      		y-=yy
      		z-=zz
      		
      		self.ground.position-=(x * 10, y * 10)
      		
      		#use old and new posotion for rotation
      		newpos=self.ground.position
      		newposx,newposy=newpos
      		deltax=posx-newposx
      		deltay=posy-newposy
      		self.ship.rotation = math.atan2(deltay,deltax)-4.7
      	
      	
      	def wrench(self,xy):
      		if xy in self.edit_button.bbox:
      			if self.edit_mode==True:
      				self.edit_mode=False
      				self.edit_button.color='red'
      				self.re_center.remove_from_parent()
      				self.draws.remove_from_parent()
      				self.selected.remove_from_parent()
      			elif self.edit_mode==False:
      				self.edit_mode=True	
      				self.edit_button.color='#00ff00'
      				self.add_child(self.re_center)
      				self.add_child(self.draws)
      				self.add_child(self.selected)
      				
      	def editmode(self,xy):	
      		if xy in self.re_center.bbox:
      			self.recenter_gravity=gravity()
      			
      		elif xy in self.draws.bbox:
      			pass
      			
      		elif xy in self.selected.bbox:
      			pass
      			
      	def playmode(self,xy):		
      		pass	
      			
      	def touch_began(self, touch):
      		xy =touch.location
      		if xy in self.toolbar.bbox:
      			self.wrench(xy)
      			if self.edit_mode==True:
      				self.editmode(xy)	
      			else:
      				self.playmode(xy)
      		else:
      			xy-=self.ground.position
      			#non toolbar interactions
      			if self.edit_mode==True:
      				for _ in themap:
      					for tile in _:
      						if xy in tile.bbox:
      							tile.texture=current_tile
      				
      			
      		
      
      run(MyScene(), PORTRAIT)
      JonB 1 Reply Last reply Reply Quote 0
      • JonB
        JonB @Auer last edited by

        @Auer

        SpriteNode.texture
        The Texture used to draw the sprite.

        You need to convert the string image names to scene.Textures. Best to do that up front, and keep a list of Textures around.

        all_tiles=[Texture(n) for n in [g1, g2, g3, g4, g5] ]
        etc
        
        1 Reply Last reply Reply Quote 0
        • Auer
          Auer last edited by

          So i made the change and it doesnt give me the texture error, but now something crazy is happening. The texture color is overriding the background color and surrounding tiles.

          tile.texture=current_tile
          

          Turns my PRE-EDIT GAME MAP into this.
          BROKEN TEXTURED MAP

          But this simple code

          tile.color='#ff0000'
          

          CHANGES THE COLOR JUST FINE

          I'm so confused why it doesn't just change the texture, yet it changes the color correctly???

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

            Can you post a gist containing your code? (Along with any other resources needed to run it?). From the pythonista file browser menu, you can tap edit, then select multiple files, then share button to share to gist. Or if just one file, you can do it from the wrench menu.

            Have you verified that themap is populated correctly?

            Supposedly, spritenode.color will tint a texture. Not sure, but you might need to set the UI.Image rendering mode to RENDERING_MODE_TEMPLATE, which allows tinting. see
            image docs, there is a method to create a copy with a different mode.

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

              The Gist
              I also commented all the images, really any images can be used tho since i specify size.... i think
              Thanks for the help!

              I assumed that since tile.color='#whatever' works perfectly it must not be 'themap' 's problem

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

                I couldnt reproduce your issue, but i was using your original code. Ill try with your gist.

                one issue is that SpriteNodes take up resources, and it is not a good idea to have 10000 of them in a scene. Your code ran at about 3fps for me.. though i think the images i was using were larger than 20x20, so all the rescaling might be hurting performance too.

                it seems to work well to render a single ground texture(which can be stored to a ui.Image, once), then just update bits as needed. This could be done prior to starting the scene, or even saved in a file for faster initial starting. It is not really necessary to try to do screen bounds checking, except maybe if you start getting into really huge maps, but in that case it makes more sense to divide the map into "zones", and you would only ever be showing the 9 adjacent zones to the current zone.

                https://gist.github.com/f55322ba716116cf7bf4cbc2e52a0b97
                Here is a version that operates at 60fps on my old ipad3 using this idea. themap was changed to an array of indexes, so you could still do things like collision checking with ground tiles of certain type. I render the entire map to an image/texture.

                edit mode has a second of lag or so, because it still has to draw the original map, then draw a new tile on top, then convert that to a texture again. Dividing the ground into a small number, say 10x10 of chunks each containing a single texture of 10x10 tiles probably would speed that up even more.

                i was lazy on the edit mode tile indexing, it works, but may be somewhat imprecise. probably need something like (xy.x+unit) // (2*unit) to match the center, not corner, of grid, but you maybe would want to draw the touch, and print the grid Coords to confirm.

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