Home:ALL Converter>Sprite Kit NPC random movement in a platform game

Sprite Kit NPC random movement in a platform game

Ask Time:2014-12-23T19:00:34         Author:Krekin

Json Formatter

I've looked around Stack Overflow for a solution but have not found one to a problem I have with random NPC movement. Essentially, what I have coded up to now, is a simple 2D platformer game using Sprite Kit: there's a separate class for the NPC object. I initialize it in my GameScene (SKScene) no problem & so far it's behaving with the physicsWorld I have set up properly. Now I'm at the part where it simply needs to move randomly in any direction. I've set up the boundaries & have made it move with things like SKActions, utilizing things like CGPointMake, that would move the NPC randomly as needed, have it wait a little bit in that location & resume movement. BOOL's helped this process. However, I had difficulty getting the sprite to look left when moving left & looking right when moving right (looking up & down is not needed at all). So I found a way in a book by using Vector's. I set up a method in the NPC class which is used in the GameScene:

-(void)moveToward:(CGPoint)targetPosition
{
    CGPoint targetVector = CGPointNormalize(CGPointSubtract(targetPosition, self.position));
    targetVector = CGPointMultiplyScalar(targetVector, 150); //150 is interpreted as a speed: the larger the # the faster the NPC moves.
    self.physicsBody.velocity = CGVectorMake(targetVector.x, targetVector.y); //Velocity vector measured in meters per second.


    /*SPRITE DIRECTION*/
    [self faceCurrentDirection]; //Every time NPC begins to move, it will face the appropriate direction due to this method.
}

Now all of this works. But the issue at hand is calling this moveToward method appropriately in the update method. The 1st thing I tried was this:

-(void)update:(NSTimeInterval)currentTime
{
    /*Called before each frame is rendered*/

    if (!npcMoving)
    {
        SKAction *moving            = [SKAction runBlock:^{ npcMoving = YES }]; //THIS IS THE CULPRIT!
        SKAction *generate          = [SKAction runBlock:^{ [self generateRandomDestination]; }]; //Creates a random CGFloat X & CGFloat Y.
        SKAction *moveTowards       = [SKAction runBlock:^{ _newLocation = CGPointMake(fX, fY);
                                                            [_npc moveToward:_newLocation]; }]; //Moves NPC to that random location.
        SKAction *wait              = [SKAction waitForDuration:4.0 withRange:2.0]; //NPC will wait a little...
        [_npc runAction:[SKAction sequence:@[moving, generate, moveTowards, wait]] completion:^{ npcMoving = NO; }]; //...then repeat process.
    }
}

The vector method 'moveToward' requires 'update' method to be present for NPC movement to happen. I turn this off with 'npcMoving = YES' in the beginning in hopes that the NPC will move to targeted location & start the process again. This is not the case. If I remove SKAction with 'npcMoving = YES', the 'update' method calls upon the entire sequence of above SKActions every frame, which in turn doesn't move my NPC far. It simply has it change targeted location every frame, in turn creating an 'ADHD' NPC. Could someone please recommend what to do? I absolutely need to retain the vector movement for the directional properties & other future things but I am at a loss on how to properly implement this with the 'update' method.

Author:Krekin,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/27619008/sprite-kit-npc-random-movement-in-a-platform-game
yy