How to get a SpriteNode to change image / colour on screen-touching another Sprite?
So, as the title states, I would like to find out how I am able to amend an existing sprite to a new colour/image, when I touch another Sprite on the iPad screen.
Specifically - this is part of the Connect-4 script I am trying to create. The way I have chosen to do the 'how to choose ones move' is comprised of an area with left and right arrows, and in between these arrows is the button that says 'make move'. So, as one presses the left or right arrows, another sprite moves one column at a time to the respective column in the space above the board where the player wishes to make the move. Once the player is happy with the column to move, they press the separate 'make move' sprite.
This then calls the code that fills the next empty space on the board for that column, and also calls a 'check if winning line' function.
However. what I also wish to do is once the 'make move' sprite has been pressed, the colour of the sprite in the space above the board changes to match the colour of the next player to go. I believe I have the logic sorted for this, but I can't for the life of me figure out how to change the sprites colour.
In the def setup(self) function I have defined the sprite as this;
# this will show current player above row selected self.player = SpriteNode(self.turn_colour) self.player.position = (player_x, player_y) self.player.scale = 1.8 self.add_child(self.player)
and then in the def touch_began(self, touch) function, I have this;
if self.turn == 0: self.turn_colour = ('emj:Red_Circle') else: self.turn_colour = ('emj:Blue_Circle') self.player = SpriteNode(self.turn_colour) # left button pressed, so insert code to move disc to left here # right button pressed so insert code to move disc to right here
But unfortunately, this does not seem to amend the self.player sprite at all. Could someone advise please;
1 - if this is possible, and if so
2 - what is the correct syntax I should use, and
3 - which Pythonista game function I should place the code to do that
Any help greatly appreciated. More than happy to elaborate if needed. Many thanks.
@themusicman, I would suggest that your game would be easier to implement using plain ui Views instead of the scene module. For example, you can implement direct touch handlers on Views.
@themusicman, but to answer your question, if I understand correctly, you are just changing the value of the self.player valiable to a new SpriteNode, which is not added to the scene at all.
Instead, change the texture of the existing SpriteNode:
self.player.texture = Texture('emj:something')
Or you can set the color attribute to tint the texture with different colors.
I managed to write some alternate (but yes, very ugly) code to do this. Just not too sure where the best place is to locate it,.
for fill_board in range(COLUMN_COUNT): for rows2 in range(ROW_COUNT): if self.board[rows2][fill_board] != 0: if self.board[rows2][fill_board] == 1: self.fill_circle = SpriteNode('emj:Red_Circle') else: self.fill_circle = SpriteNode('emj:Blue_Circle') # self.fill_circle = SpriteNode(self.turn_colour) self.fill_circle.scale = 1.8 self.fill_circle.position = ( (fill_board * (768 - 68) / COLUMN_COUNT) + 80, (rows2 * (768 - 68) / COLUMN_COUNT) + 68) self.add_child(self.fill_circle)
It works when this code is inserted in the
function, though it is a very poor 'brute force' method of checking an array and filling a Sprite on the screen depending on the content of the item in the array.
When I inserted this code into the
def touch_began(self, touch):
function, I have a few placement issues so need to do some further investigation as to the best location to place that code.
I really do need to write a more efficient way of doing this... maybe by just inserting one piece on the board per turn instead of filling every space with its corresponding array item!
That's noobies to coding for you, eh haha
Okay so I learnt that you can get the frame of a SpriteNode. Say that your sprite is moving in random directions like an AI finding paths. Now take the frame of the SpriteNode:
def setup(self): trap = SpriteNode('sprite', position=self.size/2) AI = SpriteNode('sprite', position=self.size/3 trap_location = trap.frame self.add_child(AI) self.add_child(trap)
Now in the update function, check if the location of the AI is in the location of the trap:
def update(self): if (self.AI.frame.x and self.AI.frame.y) in trap_location: # Do the rest of your code here.
Another option is to create a totally new Sprite. Presumably for connect 4 you would have a Sprite for red and one for black, and you could just hide one when you show the other.
Absolutely loving the help and support from experts on here, thanks so much guys and gals.
@Splefix - that's an awesome idea, thanks for the suggestion.
@JonB - yep, this is exactly what I ended up doing, Jon. Once I had my head around the logic and syntax, even this old chap managed to code this section in a few mins.
Still a few things to iron out in the code, but all in all, for my first real attempt at a slightly longer Python script than Print("Hello World:), I am pretty pleased with myself.
Connect4 coded in Pythonista and running (albeit with a few glitches) on my iPad. Who'd have thunk it!! haha