Calculate acceleration / deceleration

Discussion in 'Mac Programming' started by larswik, Aug 20, 2015.

  1. larswik macrumors 68000

    Joined:
    Sep 8, 2006
    #1
    I started adding on to a program I use that will convert a bunch of stills images in to an mp4 video file.

    i have one large NSImage that is 5120 x 720. At each frame I adjust the NSRect x.origin to slide the image a little. The image needs to move 1280 pixels over 30 frames. By just dividing these values I get an x.origin value 42.666.... I am trying to accelerate and decelerate the image over 30 frames? Dividing them gives me a constant speed, I am looking to ramp up and then down the velocity over time.

    I did a google search on acceleration and get lots of mathematical equations but I am at a loss for converting this to code? I have Time and Distance but can't seem to get figure out the multiplier?

    Here is the code so far, not that it really makes a difference to the question.

    Code:
    #import "FramesGenerator.h"
    
    @implementation FramesGenerator
    @synthesize importImage, frameNumber;
    
    -(void)startProcess{
        frameSlideSpeed = 42.666;
        if (!framesArray) {
            framesArray = [[NSMutableArray alloc]init];
        }
       
        for (int i = 0; i < totalFrames; i++) {
            [self createFrame];
        }
    }
    
    -(void)createFrame{
        NSImage *toSaveImage = [[NSImage alloc] initWithSize:CGSizeMake(1280, 720)]; // image to save after created.
        [toSaveImage lockFocus]; //prep for writing to layer
        [importImage drawInRect:NSMakeRect((frameSlideSpeed * frameNumber) * -1, 0, 1280 * 4, 720) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
        [toSaveImage unlockFocus];
        frameNumber++; // starts with 1
        [framesArray addObject:toSaveImage];
    }
    
    @end
     
  2. denniscote macrumors newbie

    Joined:
    Jul 19, 2011
    #2
    This may be best explained by an example. The table below show the acceleration, velocity (integral of acceleration), and position (integral of velocity) for each frame using a constant acceleration of +5 pixels/frame for the first 15 frames, and then -5 pixels/frame for the last 15 frames.

    Frame Acceleration Velocity Position
    0 0 0 0
    1 5 5 5
    2 5 10 15
    3 5 15 30
    4 5 20 50
    5 5 25 75
    6 5 30 105
    7 5 35 140
    8 5 40 180
    9 5 45 225
    10 5 50 275
    11 5 55 330
    12 5 60 390
    13 5 65 455
    14 5 70 525
    15 5 75 600
    16 -5 70 670
    17 -5 65 735
    18 -5 60 795
    19 -5 55 850
    20 -5 50 900
    21 -5 45 945
    22 -5 40 985
    23 -5 35 1020
    24 -5 30 1050
    25 -5 25 1075
    26 -5 20 1095
    27 -5 15 1110
    28 -5 10 1120
    29 -5 5 1125
    30 -5 0 1125

    At each frame the new velocity is the sum of the previous velocity and the current acceleration, and the new position is the sum of the previous position and the new velocity. You can see that the velocity in pixels/frame ramps up from 0 to 75, and then down from 75 back to 0 over the course of the 30 frames. At the same time the position increase from 0 to 1125.

    This is an example of Euler numerical integration.

    To get the image to move some specific number of pixels you will have to vary the acceleration and deceleration. The deceleration does not have to be the same as the acceleration. To have the image stop smoothly at the end frame the velocity must be 0, so the integral of the positive acceleration must be equal to the integral of the negative acceleration. You could accelerate twice as hard as you decelerate, but you would have to decelerate twice as long to get back to zero velocity.

    HTH
     
  3. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #3
    Thanks, that seems to easy? I don't know why I was looking for a more complicated solution. I will try it out now. That solution will be a linear motion but should work fine. Thanks for taking the time!
     
  4. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #4
    This code gets me close to 1280. Seems like there would be a more elegant way of doing this, but it works?

    Code:
       
    for (int i = 0; i < 30; i++) {
            if (i < 15) { // speed up for first 15 frames
                speed = incramentor++ * 5.75 + lastSpeed;
                lastSpeed = speed;
            }
            else{
                speed = (incramentor-- * 5.75) + lastSpeed;
                lastSpeed = speed;
            }
            currentPosition = speed * -1; // need the image to move to the left so I multiply the results by -1
            pIntArray[counter] = currentPosition; // store the values in an C int Array
            counter++;
       }
    
     
  5. Vegard7, Aug 23, 2015
    Last edited: Aug 26, 2015

    Vegard7 macrumors newbie

    Joined:
    Aug 23, 2015
    #5
    Here's a simple solution:



    Take your standard (x,y) coordinate axes and change them to (t,v), time and velocity. If you travel a constant velocity v0 to some time t0, and if you graph this, you end up with a nice little box whose area represents the distance you just traveled since distance = velocity * time. The shape doesn't have to be a rectangle. Your velocity can vary up and down over the course of your travel time and the area under the curve will always represent the distance traveled. The slope of the line (or slope of the tangent line if it's a curve) represents the acceleration since that is equal to the rate of change of velocity with respect to time.



    You probably want a trapezoid. Start at (0,0), accelerate upwards at constant rate for a period of time, level off the velocity for awhile, and then decelerate back to zero -- (30, 0) in your case. The area of this trapezoid will be 1280. You will probably wish to accelerate and decelerate for the same amount of time, although you certainly don't have to. For this example, I will assume you will wish to accelerate, maintain a constant velocity and decelerate over a time period of 10 frames each.



    Google "area of a trapezoid". There they provide you with an area of a trapezoid calculator. The base of the trapezoid b is your total time of 30 frames. The top of the trapezoid a represents the time spent traveling at a constant velocity. The slope of c is your acceleration and the slope of d is your deceleration. (The lengths of c and d are irrelevant other than the fact the length of their horizontal components = the time spent accelerating or decelerating.) The height of the trapezoid h represents the constant velocity you'll be traveling at after you've stopped accelerating.



    Given Area A = (a+b)/2 * h, we can rewrite that to h = 2*A/(a+b). Thus, h = 2*1280/(10+30) = 64, which is your constant velocity in pixels per frame. Now since you're accelerating over a time of 10 frames, your acceleration during these 10 frames will be the slope of c = h/10 = 6.4 pixels per frame per frame. Your initial velocity will start at zero, and for the first 10 frames you will add 6.4 to it. For the next 10 frames, your acceleration goes to zero and your velocity will remain constant, and for the last 10 frames your acceleration goes to -6.4 and you continue to add this to the velocity. The distance traveled each frame is equal to the velocity at that time (d = v when time = 1), and of course the cumulative distance traveled is the sum of these velocities.



    Here's the chart: (frame, acceleration, velocity, distance)

    v = previous v + previous a

    d = previous d + current velocity



    f a v d

    0 6.4 0 0

    1 6.4 6.4 6.4

    2 6.4 12.8 19.2

    3 6.4 19.2 38.4

    4 6.4 25.6 64

    5 6.4 32 96

    6 6.4 38.4 134.4

    7 6.4 44.8 179.2

    8 6.4 51.2 230.4

    9 6.4 57.6 288

    10 0 64 352

    11 0 64 416

    12 0 64 480

    13 0 64 544

    14 0 64 608

    15 0 64 672

    16 0 64 736

    17 0 64 800

    18 0 64 864

    19 0 64 928

    20 -6.4 64 992

    21 -6.4 57.6 1049.6

    22 -6.4 51.2 1100.8

    23 -6.4 44.8 1145.6

    24 -6.4 38.4 1184

    25 -6.4 32 1216

    26 -6.4 25.6 1241.6

    27 -6.4 19.2 1260.8

    28 -6.4 12.8 1273.6

    29 -6.4 6.4 1280

    30 -6.4 0 1280


    So why is v = 0 at frame 30 and d = 1280 at frame 30? It's just the way I've got it set up. Your 30 frames are actually frames 0 - 29. v is actually the velocity at the beginning of that frame which equals the velocity at the "end" of the previous frame, so I included a frame 30 just to show that the velocity did indeed go to 0. (Or 1.776E-15 if you prefer.) Your last frame (frame 29) should reflect the final distance and it does.

    How's the artillery game coming along?
     
  6. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #6
    Hey, thanks for that detailed explanation! I have been gone this weekend but look forward to rewriting this code this week.

    The artillery game, Castles & Canons!!! I was making good progress with that. It was tough coming up with an AI to play against and making an AI is still a bit complicated. Got graphics from an artist friend of mine. Then one day I sat Cocos 2D and working with sprites seemed easier so I started to recode for Sprites and they had some physics that I could tap into as well. As I was getting into that Apple released their sprite kit and made working with physics MUCH easier. But at that point I had already started with Cocos 2D so I started adding and changing code for SpriteKit.

    I don't seem to have the time to write code faster then Apple and everyone updates code and makes new frameworks. I struggled with Canon Ball math and now with physics I don't need it.

    As I work on larger projects I can see how beneficial it would be to work within a team to get projects finished. I barely write code faster then it gets depreciated. :)

    I will return to it soon though, thanks for asking!
     
  7. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #7
    Thanks Vegard7, I got it working this morning perfectly. I don't know why but it took me a couple days to wrap my head around this concept but I get it now.

    Thanks!
     
  8. Vegard7 macrumors newbie

    Joined:
    Aug 23, 2015
    #8
    Glad to have helped. If, after you've worked on your artillery game some more, you repost an update on where you're at with your physics I might throw in my two cents. I'm unfamiliar with Cocos 2D and its physics engine, so I wouldn't be able to be of any help there. And since I'm evil: have an airplane fly over and try shooting it down with your cannon's AI. And no cheating (e.g. limit your shell's velocity to 4 times the airplane's velocity, and don't shoot dozens of rounds over a variety of angles -- shoot only one round every few seconds at where you calculate the airplane will be.) Good fun.
     

Share This Page