2

With reference to this programming game I am currently building.

Important: Scroll down to see [Edit]

Some of the methods that a user can call in my game will be methods that will do a Translate Transform to the Robot (just a Canvas basically).

From the move method, I know the heading (angle) at which the Robot will be facing at the time, and I also know the length of pixels that the Robot wants to move.

Now, the problem I am facing is how to translate the canvas (in a timer) to move at its current facing angle?

alt text http://img8.imageshack.us/img8/3606/robottranslatemovementfu3.jpg

There must be some Maths that I am missing here, but I just can't figure out what to work out in each Timer tick.

Here is the method that is invoked, that contains the timer that will tick every 5 milliseconds, animate the movement:

public void Ahead(int pix)
    {
        eventQueue.Enqueue((TimerDelegate)delegate(DispatcherTimer dt)
        {
            /* Available Variables:
            Translate_Body.X <= Current Robot Location on X-axis
            Translate_Body.Y <= Current Robot Location on Y-axis
            Bot.Body <= The Canvas that needs to be translated (moved)

            To translate the robot, I just basically do this:
                Translate_Body.X++; or Translate_Body.YY++; to increment, or -- to decrement ofcourse

            Now I need to figure out the logic on when to increment (or decrement, according to the angle I suppose) the Y and X
            */

            IsActionRunning = true;
            dt.Tick += new EventHandler(delegate(object sender, EventArgs e)
            {
                lock (threadLocker)
                {
                     //The logic needs to happen in here, with each timer tick.
                     //so with each timer tick, the robot is moved on pixel according to its angle.
                     //Then I need to make a condition that will indicate that the robot has arrived at its destination, and thus stop the timer.
                }
            });    
            dt.Start();
        });
    }

[IMPORTANT EDIT]

I have now changed my logic to use the WPF BeginAnimation instead of a ticker to do the animation for me. So now I do not need to calculate the new coordinates on every tick, but I just provide the end coordinates, and the BeginAnimation will translate it over a period of time:

public void Ahead(int pix)
    {
        eventQueue.Enqueue((TimerDelegate)delegate
        {

            Animator_Body_X.From = Translate_Body.X;
            Animator_Body_X.To = //The end X-coordinate
            Translate_Body.BeginAnimation(TranslateTransform.XProperty, Animator_Body_X);

            Animator_Body_Y.From = Translate_Body.Y;
            Animator_Body_Y.To = //The end Y-coordinate
            Translate_Body.BeginAnimation(TranslateTransform.YProperty, Animator_Body_Y);
        });
    }

So now, given the angle (0-359) the canvas is currently rotated at, starting x and y coordinates (of where the canvas is currently situated) and distance, how do I calculate to end coordinates?


UPDATE: Solution

Community
  • 1
  • 1
Andreas Grech
  • 105,982
  • 98
  • 297
  • 360

2 Answers2

1

To help with the math:

If you want to move d pixel distances in t seconds then you will need to move on average x/t (pixels/seconds).

For this you will need to store the start time of your animation (start_time).

In every timer tick, compute the percentage of animation completed:

percent_complete= (now - start_time) / t

Multiply percent_complete by the distance you want to move to get the distance you should be from where you started (d_now). Remember to keep track of the start distance when you start the animation.

d_now = percent_complete * d

The robot's x and y for the current timer tick can then be computed by:

x = d_now * cos(heading) + start.x
y = d_now * sin(heading) + start.y

You may need to tweak the signs of things but that's the gist of it. Math aside, aren't basic animation routines already provided for you in WPF? I've never used it but that was my impression. Link.

colithium
  • 10,269
  • 5
  • 42
  • 57
  • Thanks for the reply, but what I can't understand from your answer is how do I get the 't' in [percent_complete= (now - start_time) / t] ? Because I only know the distance the bot wants to move, not the time it will take to do so – Andreas Grech Feb 10 '09 at 05:53
  • And also, what exactly do you mean by 'start_time' ? Isn't start_time always a 0ms ? – Andreas Grech Feb 10 '09 at 07:31
  • How long it should take is: distance/velocity. You can pick the velocity. Start time may not always be time = 0, it may be given in ticks/milliseconds/UNIX time. All you care about is that start_time and now use the same reference point. – user7116 Feb 10 '09 at 14:14
  • I changed my logic, and now I only need to get the end coordinates. How can I calculate the end coordinates? – Andreas Grech Feb 10 '09 at 18:11
  • x = start.x + d * cos(heading) y = stary.y + d * sin(heading) where d is the total distance you want to move. A tip: sin and cos take radians, if you're getting weird results, it's probably because you're passing degrees. – colithium Feb 11 '09 at 05:14
0

Solution

Thanks to the help of both Andy Mikula and Cameron MacFarland, it is finally working as intended.

And here is the working code:

double headingRadians = Heading * (Math.PI / 180);

Animator_Body_X.From = Translate_Body.X;
Animator_Body_X.To = Math.Sin(headingRadians) * pix + Translate_Body.X;
Translate_Body.BeginAnimation(TranslateTransform.XProperty, Animator_Body_X);

Animator_Body_Y.From = Translate_Body.Y;
Animator_Body_Y.To = ((Math.Cos(headingRadians) * pix) * -1) + Translate_Body.Y;
Translate_Body.BeginAnimation(TranslateTransform.YProperty, Animator_Body_Y);
Community
  • 1
  • 1
Andreas Grech
  • 105,982
  • 98
  • 297
  • 360