How to make a sprite follow a trail?

945 Views Asked by At

I'm making a game where the player draws a line and then a sprite should follow and run on it. I have a mutable array and also a draw method which works well. but I'm having trouble figuring out a way to move the sprite. I have tried different approaches but I can't get the iterator to work.

It's supposed to work by iterating through the array. which is populated with CGPoint locations previously stored. I try to move the sprite in ccTouchedEnded but it highlights [toucharray objectAtIndex:0] and says

passing 'id' to parameter of incompatible type 'CGPoint (aka 'struct CGPoint')

-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event  { 
    //remove objects each time the player makes a new path
    [toucharray removeAllObjects];
}

-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event  {    
    UITouch *touch = [ touches anyObject];
    CGPoint new_location = [touch locationInView: [touch view]];
    new_location = [[CCDirector sharedDirector] convertToGL:new_location];

    CGPoint oldTouchLocation = [touch previousLocationInView:touch.view];
    oldTouchLocation = [[CCDirector sharedDirector] convertToGL:oldTouchLocation];
    oldTouchLocation = [self convertToNodeSpace:oldTouchLocation];

    // add touches to the touch array 
   [toucharray addObject:NSStringFromCGPoint(new_location)];
    [toucharray addObject:NSStringFromCGPoint(oldTouchLocation)];

}

-(void)draw
{
    glEnable(GL_LINE_SMOOTH);

    for(int i = 0; i < [toucharray count]; i+=2)
    {
        CGPoint start = CGPointFromString([toucharray objectAtIndex:i]);
        CGPoint end = CGPointFromString([toucharray objectAtIndex:i+1]);
        ccDrawLine(start, end);
    }
}

-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{

  // here is the line I can't get to work to move the sprite

 _sprite.position = ccpAdd(ccpMult([toucharray objectAtIndex:0], progress),         ccpMult([toucharray objectAtIndex:0+1], 1-progress));

}
2

There are 2 best solutions below

2
On

Record the positions of the path in an array or a list and iterate through that to move your sprite along the trail. I did this in a game I made to create a particle trail behind the player. I used a size 20 array and iterated through that on an interval, updating the array at the iterator's position with the location of my character and then moving the particle effect to the location stored in the array at the position of the iterator plus 1.

You'll need to seed the array with the starting location so that you don't have null values and you'll need a special case for when you're at the end of the array because you don't want to read from an out of bounds location, instead have your code read from the 0 position.

0
On

I did this before, by (what you have so far) creating an array Mine was with multiple sprites on screen, so I also had 1 definition "Touched sprite"

  • ontouchstart empty array and add first point (start point) + set TouchedSprite to the Sprite that was closest to the start point)
  • ontouchmove add point to array
  • ontouchend (run the array on the sprite by actions (get back to that later)

A few problems is what I got, (1) I could only control 1 sprite at a time and (2) the drawn line had way too many points.

Solution to number 1:

Create a subclass Object of a sprite and create your sprites like that. Within that object create an array (make it accessible with @property and @synthesize) which will allow you to place the drawn path points in. Also create a public method called "runPathAction".

So onTouchStart you clean the Array and set the selected spriteObject. OnTouchMove add the items, OntouchEnd set the array of the selected spriteObject to the local array and then run the "runPathAction" method. (You could have passed it to the method, but I like doing it this way, just in case I want to access the array)

Solution to number 2:

I found that drawing the line creates WAY to many points. So, I created a boolean operator called "CanDraw" and a schedule with a time interval of 0.1 (you can play around with it) to a method which sets canDraw to YES. and then in the onTouchMove you check for canDraw == YES, add the point and set canDraw=NO;

This way you will have an interval of 0.1 seconds to add the points. Don't forget to remove the schedule onTouchEnd!

Now how to run the actions:

You will want a steady speed, so you will need to set a speed variable. Walk through the array of points and calculate the distance between each point to create a total distance. (PS Don't forget that the first pint is from CurrentLocation to Point0 in the array).

When you have the total distance you can figure out how much delay time you should set in your actions per step. (if you don't do this, you don't know the delay time and if you fix that you get weird movement).

Create a method, and check the "count" of the array. If count = 0 return; (finished! do cleanup or whatever), otherwise run an actionsequence, which at the end calls itself. (the check for count will handle the "break".

Grab 1 item of the array CGPoint p = (objectAtIndex:0); and remove that item from the array (removeAtIndex:0).

Run the action with the delay time and there you go!