Search code examples
objective-cscrollsprite-kittouchesbeganskaction

Objective-C SpriteKit: Stopping left tower only


So, I have a game where towers spawn on the right of the screen and move to the left, like they're scrolling. The towers are constantly going up-and-down, but I'd like to have it so when I touch the screen, the leftmost tower moving up-and-down will stop moving up-and-down (of course, still scrolling).

I haven't really had too much time to think about it, but I came up with a few good ideas. For one, I'm thinking that I'll just create a "touched" function, and call it when the touchesBegan() is called. I must do that for complicated reasons I won't explain. So far I came up with this code:

- (void)touched
{
    SKSpriteNode *lastSprite;
    for (SKSpriteNode *sprite in self.scene.children) {
        if (lastSprite && sprite) {
            if (sprite.position.x < lastSprite.position.x) {
                [sprite removeAllActions];
            }
        }

        lastSprite = sprite;
    }
}

But that doesn't seem to work. I commented out that code bit by bit and a problem occurs when using the fast-enumeration "for-in" statement. The towers will all scroll to the left, but they won't go up-and-down at all; even though this function never gets called anywhere!

So that's one thing I've tried. I've also tried using enumerateChildNodesWithName:usingBlock:, but that doesn't work because it needs to be an SKNode, while my towers are SKSpriteNodes. Plus, it's difficult for me to grab a hold of all the children in the scene that way. But I think using the towers' names will be helpful, right?

Please help me out! Some code snippets would be helpful, too!


EDIT:

I tried changing the touched() method to this:

- (void)touched
{
    NSArray *sceneNodes = self.scene.children;
    SKSpriteNode *lastNode = nil;
    for (SKSpriteNode *sprite in sceneNodes) {
        if (lastNode && sprite) {
            if (sprite.position.x < lastNode.position.x) {
                [sprite removeAllActions];
            }
        }
    }
}

The function worked in itself, and the towers continued to go up-and-down, but when I put it in the touchesBegan(), even when I don't touch, it stops going up-and-down just as before.


Solution

  • Here are the basic steps I suggest you follow:

    If you are subclassing (SKSpriteNode) your towers then create a BOOL property, something like BOOL movingUpDown, and set it to YES for any tower that has vertical movement.

    If you are not subclassing your towers, use the userData dictionary to create an entry which tells you if vertical movement is present.

    Next, add all tower objects into a mutable array. I personally prefer adding unique name to each object at the time of creation. Something like "node-0", "node-1" and so on. You can do this by having a counter and adding the value to each object's name.

    In the touchesBegan method you have your stop vertical movement code. If you are adding the tower objects sequentially, the first tower object should be the most left object.

    SKSpriteNode *myNode = [self.myArray firstObject];
    // set vertical movement to zero
    
    // remove the first object in the array
    [self.myArray removeObjectAtIndex:0];
    

    Your code is probably a bit different but you can use the above to get the gist of what you can do to make it work.