Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8581709
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 11, 20262026-06-11T21:07:05+00:00 2026-06-11T21:07:05+00:00

I have been battling with this for some time and my noob brain can’t

  • 0

I have been battling with this for some time and my noob brain can’t quite work it out. I have a standard tile map and currently use the following code to move my enemy sprite around the map

-(void) movePlayer:(ccTime)deltaTime {

    if (CGPointEqualToPoint(self.position, requestedPosition))
        return;


    float step = kPlayerSpeed * deltaTime;
    float dist = ccpDistance(self.position, requestedPosition);
    CGPoint vectorBetweenAB = ccpSub(self.position, requestedPosition);

    if (dist <= step) {
        self.position = requestedPosition;
        [self popPosition];
    } else {
        CGPoint normVectorBetweenAB = ccpNormalize(vectorBetweenAB);
        CGPoint movementVectorForThisFrame = ccpMult(normVectorBetweenAB, step);

        if (abs(vectorBetweenAB.x) > abs(vectorBetweenAB.y)) {
            if (vectorBetweenAB.x > 0) {
                [self runAnimation:walkLeft];
            } else {
                [self runAnimation:walkRight];
            }
        } else {
            if (vectorBetweenAB.y > 0) {
                [self runAnimation:walkDown];
            } else {
                [self runAnimation:walkUp];
            }
        }

        if (self.position.x > movementVectorForThisFrame.x) {
            movementVectorForThisFrame.x = -movementVectorForThisFrame.x;
        }
        if (self.position.y > movementVectorForThisFrame.y) {
            movementVectorForThisFrame.y = -movementVectorForThisFrame.y;
        }
        self.position = ccpAdd(self.position, movementVectorForThisFrame);
    }

}

movePlayer: is called by the classes updateWithDeltaTime: method. the ivar requestedPosition is set in the updateWithDeltaTime method as well, it basically gets the next point out of a queue to move to. These points can be anywhere on the map, so if they are in a diagonal direction from the enemy the enemy sprite will move directly to that point. But how do I change the above code to restrict the movement to vertical and horizontal movement only so that the enemies movement ‘staircases’ its way along a diagonal path, taking the manhattan distance (I think its called). As shown by my crude drawing below… S being the start point F being the finish and the numbers being each intermediate point along its path to create a staircase type diagonal movement. Finally I intend to be able to toggle this behaviour on and off, so that I can choose whether or not I want the enemy to move free around the map or be restricted to this horizontal / vertical movement only.

 | | | | | | | | | |
 | | | | | | | | | |
 | |F| | | | | | | |
 | |5|4| | | | | | |
 | | |3|2| | | | | |
 | | | |1|S| | | | |
 | | | | | | | | | |
 | | | | | | | | | |
 | | | | | | | | | |
 | | | | | | | | | |
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-11T21:07:06+00:00Added an answer on June 11, 2026 at 9:07 pm

    So the current solution I have found is as follows…

    -(void)pathfind {
        //Get a reference to the tile map
        CCTMXTiledMap *tileMap = (CCTMXTiledMap *)[[[[CCDirector sharedDirector] runningScene] getChildByTag:kStartLayer] getChildByTag:kMapNode];
        NSAssert(tileMap != nil, @"No Tile map");
    
        //Convert self.position to tile coordinates and set to both vars. stepTileCoord so that we can add a tile in direction of travel.
        CGPoint selfTileCoord = [tileMap tileCoordFromLocation:self.position];
        CGPoint stepTileCoord = [tileMap tileCoordFromLocation:self.position];
    
        //Init this var to keep track of the last tile worked out so the next one can be worked out from it. We start at self.position.
        CGPoint lastTileCoord = selfTileCoord;
    
        //For loop, iterates over each orginal position in the requestedPositionQueue.
        for (int i=0; i < [requestedPositionQueue count]; i++) {
    
            //Get the current original path tile coordinate.
            CGPoint requestedTileCoord = [[requestedPositionQueue objectAtIndex:i] CGPointValue];
            NSMutableArray *tempPoints = [NSMutableArray array];
    
            //While loop interates until it has worked out every intermediate step to the original path tile.
            while (!CGPointEqualToPoint(requestedTileCoord, stepTileCoord)) {
    
                //FIXME: what happens if path takes us back over the orignal start point?
                if (CGPointEqualToPoint(selfTileCoord, requestedTileCoord)) {
                    //Not sure if this will cause an issue.
                    break;
                }
    
                CGPoint vectorToDest = ccpSub(lastTileCoord, requestedTileCoord);
    
                if (abs(vectorToDest.x) > abs(vectorToDest.y)) {
                    if (vectorToDest.x > 0) {
                        stepTileCoord.x -= 1;
                    } else {
                        stepTileCoord.x += 1;
                    }
                } else {
                    if (vectorToDest.y > 0) {
                        stepTileCoord.y -= 1;
                    } else {
                        stepTileCoord.y += 1;
    
                    }
                }
    
                //If the tile worked out is the requestedTileCoord then break, no need to add it to tempPoints as it will already be in the requestedPosition Queue.
                if (CGPointEqualToPoint(requestedTileCoord, stepTileCoord)) {
                    break;
    //                CCLOG(@"%@", [requestedPositionQueue description]);
                } else {
                    //Save this tile to tempPoints arrway. And save it to lastTileCoord.
                    [tempPoints addObject:[NSValue valueWithCGPoint:stepTileCoord]];
                    lastTileCoord = stepTileCoord;
    //                CCLOG(@"\n{%f, %f}", lastTileCoord.x, lastTileCoord.y);
                }
            }
            //As we have now got an array, tempPoints, with all the intermediate step points to current point out of requestedPositionQueue we shall add all objects in tempPoints to requestedPositionQueue. NSIndexSet will ensure its added at the correct location in array.
            NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(i, [tempPoints count])];
            [requestedPositionQueue insertObjects:tempPoints atIndexes:indexes];
    //        CCLOG(@"%@", [requestedPositionQueue description]);
            //i is updated so the next point pulled out of the array isn't one of the worked out intermediate steps.
            i += [tempPoints count];
        }
    }
    

    So to begin with, I have the path of tile coordinates for the character saved in an ivar array for example…

    requestedPositionQueue = [NSMutableArray arrayWithObjects:
                                          [NSValue valueWithCGPoint:CGPointMake(7, 18)],
                                          [NSValue valueWithCGPoint:CGPointMake(11, 18)],
                                          [NSValue valueWithCGPoint:CGPointMake(7, 22)],
                                          [NSValue valueWithCGPoint:CGPointMake(7, 18)],
                                          [NSValue valueWithCGPoint:CGPointMake(11, 22)],
                                          nil];
    

    So as you can see this has some points which would require so form of diagonal movement. I then call the pathfind method and this iterates over the requestedPositionQueue and adds all the intermediate tile coordinates ensuring it always picks a tile either vertically or horizontally but never diagonally next to the current tile until it completes the entire path.

    Then in the update: method I iterate over the requestedPositionArray, taking the next tile coordinate from it, convert it to a pixel position then assign that to my requestedPosition ivar and then run the movePlayer: method (code in the original post).

    I have put comments in the pathfind method for my own benefit and thus may not be that comprehensive but they may help your understanding of my thinking.

    Finally this is the best I have come up with which allows me to ensure I can either move my character to a pixel position without restrictions or if I want move them there but confine them to only moving vertically or horizontally via tile centres. So if you can see a way to refine and optimise this code please do, or any constructive criticism will always be appreciated.

    EDIT: The FIXME: in there highlights a potential bug that I haven’t had time to look at yet. I will repost once I have investigated and fixed if required.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

So I have been battling with this for some time and I need your
I have been battling this for some time and I need some guidance. I'm
I have a challenging problem I've been battling for some time now. The Problem:
I've been battling with this for some time and seem to be getting nowhere.
I have been battling with this code for quite a while and just don't
I have been battling with this for a while (even used some Ant-based workarounds),
I have been battling this for a long time now. My understanding of Autorelease
So I have been trying and battling with this for a few hours now.
I've been battling with this issue for a couple of days now. I have
Have been trying to figure this problem out for a while now and was

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.