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
-
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)
-
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
-
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 MAPBut this simple code
tile.color='#ff0000'
I'm so confused why it doesn't just change the texture, yet it changes the color correctly???
-
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. -
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
-
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.