About the ccactionease in Cococs

Source: Internet
Author: User

Respecting the author's labor, please indicate the source of the article when reproduced.
Bugs Bunny
Address: http://www.cnblogs.com/cocos2d-x/archive/2012/03/13/2393898.html

This function image is drawn using Geogebra, thanks to its talented author.

In order to facilitate the user to control the elf movement flexibly, Cocos2d-x provides the action of the Ccactionease class system. They have similar names--cceasexxxxin, Cceasexxxxout, Cceasexxxxinout, and also have similar behaviors-from slow to fast, from fast to slow, from slow to fast and from fast to slow. But apart from this, we know nothing about ccactionease. Even if we look at the reference manuals, the information we can get is just a short description of ease Sine in. What exactly are they like, and how do we choose?

Today we are going to solve this problem. Given the sheer size of the ccactionease, the article may be divided into two or three articles.

1) Cceasesinein

In the article "Analysis of Cocos2d-x Action system", it is mentioned that:
The update function accepts a percent parameter, which represents the progress of the action's completion. Update adjusts the target object accordingly according to this percentage.
It can be said that this update function is the soul of Ccactionease.

1 void Cceasesinein::update (Cctime time)
2 {
3 m_pother->update ( -1 * COSF (Time * (float) m_pi_2) + 1);
4}

We already know that the ccactionease of the class system is to adjust the speed of other actions, and to change the new effect. The m_pother here is the action that is affected, and the source of all the magic is on the parameters it accepts. Cceasesinein a series of transformations on the passed-in percent parameter, which is then passed to the M_pother.

We extract this transformation formula, which is written as:
F (x) =1-cos (π/2*x) x∈[0,1]
This is the relationship between the percentage of time spent and the actual completion progress. In uniform motion, they should be equal, but in variable motion, their relationships can be unpredictable.

The black curve is the function image of f (x). It defines the domain from 0, to 1, and so on. According to the trend of this line, it can be seen that the speed is more and more rapid, but still not enough image.
In kinematics, the time derivative of an object's displacement is the instantaneous velocity of the object. If we can get this instantaneous velocity curve, it's much more intuitive. The above function f (x) is the relationship between the used time percentage and the actual completion progress, which can be roughly understood as the relationship between time and distance.
So we derive the derivative of f (x):
F ' (x) =π/2*sin (π/2*x) x∈[0,1]
It corresponds to the red curve in the graph. It can be clearly seen that the faster the speed, the higher the C point has reached the highest.
As its name says, its speed varies from slow to fast and sinusoidal.

2) Cceasesineout

Let's look at the Cceasesineout class again.

1 void Cceasesineout::update (Cctime time)
2 {
3 m_pother->update (Sinf (Time * (float) m_pi_2));
6?

In the same vein:
F (x) =sin (π/2*x) x∈[0,1]
F ' (x) =π/2*cos (π/2*x)

We are also more concerned with the red curve, which starts at the highest point C and drops all the way down to a point. This shows that in the Cceasesineout action, the speed is more and more slow, its image is also sinusoidal change.

3) Cceasesineinout

We know that the speed change of Cceasexxxxinout is first from slow to fast, then from fast to slow. If we put the above two images together and then reduce the horizontal scale by one fold, the result is the shape of the curve.
In general, we need to divide the function into two segments, the first paragraph between 0 and 0.5, and the second between 0.5 and 1. Let's take a look at how cceasesineinout is implemented.

1 void Cceasesineinout::update (Cctime time)
2 {
3 m_pother->update ( -0.5f * (COSF ((float) M_PI * time)-1));
4}

F (x) =-0.5* (cos (π*x)-1) x∈[0,1]
F ' (x) =π/2*sin (π*x)

In Cceasesineinout, these two curves are exactly the same function (non-segmented function) of the image. It's ingenious, isn't it?
The red curve starts at the Origin o and rises all the way up to the highest point C, then slides down to point D. It is also a curve of sinusoidal variation. The speed of the action seems to be from slow to fast, then from fast to slow.

Summary

The three motions of Cceasesinein, Cceasesineout and cceasesineinout are of the same speed sine variation, and the range of variation is [0,Π/2].

4) Cceaseexponentialin

With the previous experience, it's much easier to take a look at the Cceaseexponentialin update function.

1 void Cceaseexponentialin::update (Cctime time)
2 {
3 m_pother->update (time = = 0) 0:POWF (2, Ten * (TIME/1-1))-1 * 0.001f);
6?

As you may have noticed, a conditional operator is used here, and the expression is changed into a piecewise function.
When x=0, f (x) =0
When X∈ (0,1], f (x) =2^ (10* (x-1))-0.001

Note that this is not a curve of speed.
The image in the upper sub-plot area is the overall movement of this function, and we give a close-up to the curve near the origin in the main plot area. You can see that in addition to the x=0, the curve has an intersection with the x-axis.
For 2^ (10* (x-1)) -0.001=0 solution, it is concluded that:
X=1-LN (+)/(10*LN (2)) =0.00342

Now we begin to imagine the detailed steps of the sprite moving in accordance with the Cceaseexponentialin action.
First, the time starts at zero, and the sprite is set to the starting position. This step is normal and no problem.
Next, the Genie jerked a small distance in the opposite direction. This distance is very, very small, that is, near Point B on the graph, about 0.00234% of the total moving distance.
The genie then begins to move toward the target point at a varying speed. The sprite goes back to its original position after point a. At this point, the movement we designed was just beginning.
If we put x=1 into the formula, we can deduce:
F (x) =1-0.001=0.999
In other words, the image eventually does not reach the end, but a short distance.

In short, the first 0.342% parts of the total time and the final moment of movement are not normal.
If you design a motion that is longer than 1000 seconds, the exact position of the genie will not be in the trajectory of your design for the first 3 seconds.
Of course, if you want to observe this problem, the distance of the movement is also a key.
Let's say you're frantically designing a 100,000-megapixel sprite and exercising for more than 1000 seconds, you can see that. 3 seconds, reverse 2 pixels.

But why is that? Is it a bug in the engine?
Specifically, this should not be a bug, this is just the problem caused by precision.

The following paragraph is my own speculation, that is to guess, we look at the good.
I guess the original prototype of this formula should be:
F (x) =2^ (10* (x-1)) x∈[0,1]
But it has a problem, that is when X=0, F (0) =1/1024
When the time is zero, the genie has about 1 per thousand of the displacement, and it is very obvious that when the motion of an object starts, it is beating violently. So the designer moves the 1 per thousand error to the end, which is when the movement ends.
The formula now looks like this:
F (x) =2^ (10* (x-1)) -1/1024 x∈[0,1]

We all know that cocos2d-x use single-precision floating-point numbers, as well as write 0.0009765625f more trouble, and so many other factors, and finally this formula is simplified into the shape of the present.

My guess is over, we'll take the derivative:
F ' (x) =10*2^ (10* (x-1)) *ln (2) x∈[0,1]

Draw the image according to the ideal formula, here we only look at the red curve. This curve rises all the way from Point D, and quickly arrives at point C. If you take the derivative again, you can draw the law of its acceleration. It should be seen from the DC curve that the acceleration is also getting larger.
Well, that's a bit far. Let's focus our attention first and calculate the minimum and maximum speed values.
F ' (0) =10*2^ ( -10) *ln (2) =0.006769
F ' (1) =10*2^0*ln (2) =6.931472

The speed of the Cceaseexponentialin is from slow to fast, from 0.006769 to 6.931472, with a number of exponential changes.

5) Cceaseexponentialout
1 void Cceaseexponentialout::update (Cctime time)
2 {
3 m_pother->update (time = = 1? 1: (-POWF (2, -10 * time/1) + 1));
6?

Cceaseexponentialout and Cceaseexponentialin are similar, the only difference is that the cceaseexponentialout will have a short distance jump (1 per thousand error) in the last moment, And Cceaseexponentialin is a part of abandonment. Personally, I think the cceaseexponentialout is more reasonable to deal with.
All right, direct.

There is no difficulty here, I directly let the tool generate the derivative image.
We are concerned with point A (0,6.93147) and Point D (1,0.00677), which is the same as the speed range of the Cceaseexponentialin. From 6.93147 down to 0.00677, the speed is from fast to slow exponential change.

6) Cceaseexponentialinout

In the "Easy game development tutorial Cocos2d-x transplant version 003" There is a cceaseexponentialinout of the demo code, test run will find that the genie finally flew out of the screen at a very fast speed, is the author use improper, or other reasons? At that time, due to the lack of research on the issue of timing and energy, I take this opportunity to analyze the problem today.

1 void Cceaseexponentialinout::update (Cctime time)
2 {
3 time /= 0.5f;
4 if (Time < 1)
5 {
6 Time = 0.5f * POWF (2, Ten * (time-1));
7 }
8 Else
9 {
Time = 0.5f * (-POWF (2, Ten * (time-1)) + 2);
One }

m_pother->update (time);
14}

Hehe, a typical piecewise function. The drawing function image is as follows:

The blue curve in the figure is the segmented function used by cceaseexponentialinout. It is obvious that at point A, the curve is moving at a 90° change, extending toward the point (1,-511). It's not as close to point C as the previously mentioned function, which explains why the genie flew out of the screen somehow.

This is a bug and we want the second half of the curve to be like the green curve AC. (I only test on the Win32 platform, I do not know whether other platforms also exist this problem, interested friends can test under.) )

My changes are as follows:

1 void Cceaseexponentialinout::update (Cctime time)
2 {
3 time /= 0.5f;
4 if (Time < 1)
5 {
6 Time = 0.5f * POWF (2, Ten * (time-1));
7 }
8 Else
9 {
(time-1) Change (1-time)
One time = 0.5f * (-POWF (2, Ten * (1-time)) + 2);
-- }

m_pother->update (time);
15}

After the correction, the action behaves normally.
Derivation of the new function, the red curve in the graph. The coordinates of Point D, Point E, and Point F are (0.5,6.93147), (0,0.00677), (1,0.00677) respectively.
The attentive friend may have found that dot C did not arrive (with a). Yes, there are 0.000488 errors, and the starting point of the curve is the same. That is, the original 1/1024 error is split to the beginning and end.

Summary

The three movements of Cceaseexponentialin, Cceaseexponentialout and Cceaseexponentialinout are all of the same speed-scale changes, the range of which is [0.00677,6.93147].

About the ccactionease in Cococs

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.