Andy Mills
Andy Mills

Reputation: 135

Can't modify objectAtIndex NSMutableArray of SKSpriteNodes

OK, so I'm having a problem directly modifying the contents of an NSMutableArray. Basically, I have an Array of SKSpriteNodes created in the initialisation function. I want to be able to modify a SKSpriteNode at a specified index depending on where the user touches the screen. I can get the correct index, and I can get the node, but I can't seem to get the properties of the node to change.

I've included the full code in here for clarity, but the issue is in the last function (touchesBegan).

What I want to do is be able to set the properties of the SKSpriteNode at the specified index. The debug messages are saying that *leftTile is being created properly and contains the correct data, but the changes don't take effect on the screen when I call the setHidden function.

#import "FLGameScene.h"

@implementation FLGameScene

/**
 * Convert Multidimensional Coordinates to Single Index
 *
 * @param int row                   Row index.
 * @param int col                   Column index.
 *
 * @return int
 */
- (int)multiToSingle:(int)row :(int)col
{
    return ((row * numTiles) + col);
}

/**
 * Determine the Iso Coordinates closest to the Real Position.
 *
 * @param CGPoint coords            Real coordinates.
 *
 * @return CGPoint
 */
- (CGPoint)xyToIso:(CGPoint)coords
{
    // Determine the Row and Column
    int x = (coords.x - offsetX) / tileSize;
    int y = (coords.y - offsetY) / tileSize;

    // Create the CGPoint
    return CGPointMake(x, y);
}

/**
 * Determine the Real Coordinates for a specified index.
 *
 * @param CGPoint coords            Iso coordinates.
 *
 * @return CGPoint
 */
- (CGPoint)isoToXY:(CGPoint)coords
{
    // Determine the X and Y Values
    float x = (coords.x * tileSize) + offsetX;
    float y = (coords.y * tileSize) + offsetY;

    // Create the CG Point
    return CGPointMake(x, y);
}

/**
 * Initialisation Function.
 *
 * @param CGSize size               Size of the Scene Area.
 *
 * @return *SKScene
 */
- (id)initWithSize:(CGSize)size
{
    // Call the Parent Constructor
    if (self = [super initWithSize:size])
    {
        // Log a Message
        if (debugMode) NSLog(@"Game Scene Created. Size: %f x %f", size.width, size.height);

        // Set the Background Colour
        [self setBackgroundColor:[UIColor colorWithRed:0.15f green:0.25f blue:1.0f alpha:1.0f]];

        // Set the Tile Size
        tileSize = 50.0f;

        // Set the Number of Tiles
        numTiles = 14;

        // Determine the Offset
        offsetX = (size.width / 2.0f) - ((numTiles / 2) * tileSize);
        offsetY = (size.height / 2.0f) - ((numTiles / 2) * tileSize);

        // Create the Lilypad Texture
        SKTexture *lilypadTex = [SKTexture textureWithImageNamed:@"lilypad"];

        // Create the Frog Texture
        SKTexture *frogTex = [SKTexture textureWithImageNamed:@"frog"];

        // Create the Tile Array
        _tileArray = [[NSMutableArray alloc] initWithCapacity:(numTiles * numTiles)];

        // Loop through and Create the Grid
        for (int col = 0; col < numTiles; col++)
        {
            for (int row = 0; row < numTiles; row++)
            {
                // Create a Random BOOL Value for the Frogs
                int containsFrog = (rand() % 2);

                // Log a Message
                if (debugMode) NSLog(@"Square %i, %i :: %i", row, col, containsFrog);

                // Calculate the X Position
                float posX = (col * tileSize) + offsetX;

                // Calculate the Y Position
                float posY = (row * tileSize) + offsetY;

                // Create the Sprite Node
                SKSpriteNode *tile = [[SKSpriteNode alloc] initWithTexture:lilypadTex];

                // Set the Tile Origin
                [tile setAnchorPoint:CGPointZero];

                // Add the Sprite User Data Dictionary
                [tile setUserData:[NSMutableDictionary dictionary]];

                // Set the Flag for Containing a Frog
                [tile.userData setValue:[NSNumber numberWithInt:containsFrog] forKey:@"containsFrog"];

                // Set the Tile Position
                [tile setPosition:CGPointMake(posX, posY)];

                // Set the Tile Size
                [tile setSize:CGSizeMake(50.0f, 50.0f)];

                // Add the Tile to the Board
                [self addChild:tile];

                // Add the Tile to the Array
                [_tileArray addObject:[tile copy]];
            }
        }

        for (SKSpriteNode *tile in _tileArray)
        {
            if ([[tile.userData valueForKey:@"containsFrog"] boolValue] == YES)
            {
                // Create a Frog Node
                SKSpriteNode *frog = [[SKSpriteNode alloc] initWithTexture:frogTex];
                [frog setAnchorPoint:CGPointZero];
                [frog setSize:CGSizeMake(tileSize, tileSize)];
                [frog setPosition:tile.position];

                // Add the Frog Node
                [self addChild:frog];
            }
        }
    }

    // Return the Instance
    return self;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // Get the Touches
    UITouch *touch = [touches anyObject];

    // Get the Touch Location
    CGPoint touchLocation = [touch locationInNode:self];

    // Determine the Tile X and Y
    CGPoint tileIndex = [self xyToIso:touchLocation];

    // Log a Debug Message
    if (debugMode) NSLog(@"Tile at %f, %f Tapped", tileIndex.x, tileIndex.y);

    // Search Available Tiles

    // Tile to the Left
    int leftTileIndex = [self multiToSingle:(int)tileIndex.x - 2 :(int)tileIndex.y];

    // Get the Tile Object
    SKSpriteNode *leftTile = [_tileArray objectAtIndex:leftTileIndex];

    if (debugMode) NSLog(@"Description: %@", [leftTile.userData description]);

    // Check for Frogs
    if ([[leftTile.userData objectForKey:@"containsFrog"] boolValue] == NO)
    {
        NSLog(@"Tile empty");
        [leftTile setHidden: YES];
    }
}

@end

Upvotes: 0

Views: 283

Answers (1)

CodeSmile
CodeSmile

Reputation: 64477

            // Add the Tile to the Board
            [self addChild:tile];

            // Add the Tile to the Array
            [_tileArray addObject:[tile copy]];

The sprite added to the scene graph is not the same as the one you add to the array because you create a copy of it. Don't copy and it'll work.

Even better: put all the tiles in an SKNode so you don't need the extra array, instead you can then refer to tiles via the children array.

Upvotes: 2

Related Questions