Animation genie implementation

Source: Internet
Author: User
1. animation genie concept animation is a dynamic picture. It is represented as a runtime data structure and algorithm in a computer. The data structure indicates the animation storage method, which can be stored in advance or computed during runtime. The algorithm declares how to map the data structure to the screen. A Sprite is a rendering unit that stores data that shows how to render the screen. Animation genie is a special genie, so this time the goal is to create a Sprite subclass (animatedsprite ).
2. Before designing the sprite class, you need to preview the sprite class code. (Some code for scaling and rotation is omitted)
/// <Summary> // genie class // </Summary> public class sprite {// <summary> // Number of vertices /// </Summary> const int vertexamount = 6; // two triangles /// <summary> /// vertex coordinates /// </Summary> vector [] _ vertexpositions = new vector [vertexamount]; /// <summary> /// vertex color (partial color) /// </Summary> glcolor [] _ vertexcolors = new glcolor [vertexamount]; /// <summary> /// vertex ing (texture map is used to render a specific part of a polygon) /// </Summary> glpoint [] _ vertexuvs = new glpoint [vertexamount]; /// <summary> /// texture /// </Summary> texture2d _ texture = new texture2d (); /// <summary> /// get or set the sprite texture /// </Summary> Public texture2d texture {get {return _ texture;} set {_ texture = value; // by default, the width and height of the texture are initvertexpositions (centerposition, _ texture. width, _ texture. height) ;}/// <summary> /// obtain the vertex array /// </Summary> Public vector [] vertexpositions {get {return _ vertexpositions ;}} /// <summary> /// obtain the vertex color array /// </Summary> Public glcolor [] vertexcolors {get {return _ vertexcolors ;}} /// <summary> /// obtain the vertex coordinate array /// </Summary> Public glpoint [] vertexuvs {get {return _ vertexuvs ;}} /// <summary> /// get or set the width /// </Summary> Public double width {get {// obtain the width of the actually displayed return _ vertexpositions [1]. x-_ vertexpositions [0]. X ;}set {initvertexpositions (centerposition, value, height );}} /// <summary> /// get or set the height /// </Summary> Public double height {get {// topleft-bottomleft return _ vertexpositions [0]. y-_ vertexpositions [2]. Y ;}set {initvertexpositions (centerposition, width, value) ;}/// <summary> /// create a genie /// </Summary> Public sprite () {initvertexpositions (vector. zero, 1, 1); setcolor (glcolor. getwhite (); setuvs (New glpoint (0, 0), new glpoint (1, 1 )); // set the default initial position _ currentposition = new vector (_ vertexpositions [0]. X + width/2, _ vertexpositions [0]. y-height/2, _ vertexpositions [0]. z);} // <summary> // initialize vertex information // </Summary> void initvertexpositions (vector center, double width, double height) {double halfwidth = width/2; double halfheight = height/2; // create two triangles clockwise to form a square shape // topleft, topright, bottomleft _ vertexpositions [0] = new vector (center. x-halfwidth, center. Y + halfheight, center. z); _ vertexpositions [1] = new vector (center. X + halfwidth, center. Y + halfheight, center. z); _ vertexpositions [2] = new vector (center. x-halfwidth, center. y-halfheight, center. z); // topright, bottomright, bottomleft _ vertexpositions [3] = new vector (center. X + halfwidth, center. Y + halfheight, center. z); _ vertexpositions [4] = new vector (center. X + halfwidth, center. y-halfheight, center. z); _ vertexpositions [5] = new vector (center. x-halfwidth, center. y-halfheight, center. z);} // <summary> // obtain or set the central position // </Summary> Public vector centerposition {get {return _ currentposition ;} set {matrix m = new matrix (); M. settranslation (value-_ currentposition); applymatrix (m); _ currentposition = value ;}} /// <summary> /// set the color /// </Summary> Public void setcolor (glcolor color) {for (INT I = 0; I <Sprite. vertexamount; I ++) {_ vertexcolors [I] = color ;}/// <summary> // set UV, perform texture ing // </Summary> Public void setuvs (glpoint topleft, glpoint bottomright) {// topleft, topright, bottomleft _ vertexuvs [0] = topleft; _ vertexuvs [1] = new glpoint (bottomright. x, topleft. y); _ vertexuvs [2] = new glpoint (topleft. x, bottomright. y); // topright, bottomright, bottomleft _ vertexuvs [3] = new glpoint (bottomright. x, topleft. y); _ vertexuvs [4] = bottomright; _ vertexuvs [5] = new glpoint (topleft. x, bottomright. y);} // <summary> // apply matrix operations /// </Summary> Public void applymatrix (matrix m) {for (INT I = 0; I <vertexpositions. length; I ++) {vertexpositions [I] * = m ;}}}
The sprite class only stores the data used for plotting. Instead of plotting itself, the sprite class is responsible for the render class. The matrix class is used for matrix operations. The application matrix can achieve translation, scaling, and rotation, simplifying the sprite class design.

3. consistent material format in flash, only key frames are provided by the user, and the rest of the frames are completed through compensation, all frames of the animation genie designed this time are provided by users (from image materials), which greatly simplifies the design. Therefore, the only problem is how to collect and present materials. "Collect" loads scattered image resources into a data structure of an orderly organization, and "render" displays memory data on the screen using the graphic Renderer. I have selected the rendering component of C # + OpenGL to render normal sprite to the screen. I only need to consider how to transmit the texture to be rendered to OpenGL in sequence, dual buffering and other rendering technologies do not need to be considered.
The clips required for an animation may have different rendering formats, but they must be loaded into a consistent memory representation. There are roughly two ways to solve this problem. The first is to pre-process the animation material and express the material as a consistent standard format through non-programming means. The second is to develop appropriate loading algorithms for different formats. Obviously, the first solution should be adopted, which facilitates simplified system design.
Agreed material format: 1. An animation genie is provided by an image file (PNG/jpg. 2. An animation consists of several frames. The size of each frame is the same. 3. frames are arranged by text and cannot be left blank. 4. In addition to providing files, you must specify the size and number of frames.

4. Because the sprite class already exists in the class design of the animation genie, some methods can be simply inherited and reused. All we need to do is map the current frame to the display data (vertex array, color array, UV array), which can be obtained through runtime computation or computed in advance. The default UV includes the entire texture image, which is the general sprite display mode-display the entire image. You can modify UV to display only part of the image. If UV is set for each change of the current frame, the image representing the corresponding frame is displayed, you can achieve the animation effect.
This design can be completed through reverse lookup. -> Know the current frame, how to set UV data-> call the setuvs method of the base class and pass two coordinates that uniquely determine the display area. -> You already know the size of the entire image and the size of the unit frame. You only need to know the coordinates of the current frame in the upper left corner of the texture image. -> You can calculate the number of frames in a row and know the size of the frames.-> OK is not actually a reverse method. This is the real normal solution to the problem. It is impossible to start from the condition, which is the reverse direction of normal thinking.
/// <Summary> /// animation genie /// </Summary> public class animatedsprite: sprite {/// <summary> /// total number of frames /// </Summary> int _ totalframe; /// <summary> /// frame width /// </Summary> double _ framewidth; /// <summary> /// frame height /// </Summary> double _ frameheight; /// <summary> /// current frame /// </Summary> int _ currentframe; /// <summary> /// timer of the current frame /// </Summary> double _ currentframetime; /// <summary >/// get or set the duration of each frame /// </Summary> Public double frameduration {Get; set ;} /// <summary> /// whether to play cyclically or not /// </Summary> Public bool looping {Get; set ;} /// <summary> /// whether or not the playback ends /// </Summary> Public bool finished {Get; private set ;} /// <summary> /// get the number of frames of a row /// </Summary> Public int rowframe {get {return (INT) math. round (width/_ framewidth) ;}/// <summary> /// create a playable animation genie /// </Summary> Public animatedsprite () {looping = false; finished = false; frameduration = 0.05; _ frameheight = 0; _ framewidth = 0; _ currentframe = 0; _ totalframe = 1; _ currentframetime = frameduration ;} /// <summary> /// scroll to the next frame /// </Summary> Public void advanceframe () {_ currentframe = (_ currentframe + 1) % _ totalframe;} // <summary> // obtain the position index of the frame value in the source image. // </Summary> glpoint getindexfromframe (INT frame) {glpoint point = new glpoint (); point. y = frame/rowframe; point. X = frame-(point. y * rowframe); return point;} // <summary> // update the display data /// </Summary> void updatedisplay () {glpoint Index = getindexfromframe (_ currentframe); vector startposition = new vector (index. x * _ framewidth, index. y * _ frameheight); vector endposition = startposition + new vector (_ framewidth, _ frameheight); setuvs (New glpoint (float) (startposition. x/width), (float) (startposition. y/height), new glpoint (float) (endposition. x/width), (float) (endposition. y/height);} // <summary> // The total number of frames of the notification animation genie /// </Summary> Public void settotalframe (INT totalframe) {_ totalframe = totalframe; _ currentframe = 0; _ currentframetime = frameduration; updatedisplay () ;}/// <summary> // notify the animation Genie of the frame size, each frame will apply the same size // </Summary> Public void setframesize (double width, double height) {_ framewidth = width; _ frameheight = height; updatedisplay ();} // <summary> // process updates /// </Summary> Public override void process (double elapsedtime) {If (_ currentframe = _ totalframe-1 & looping = false) {finished = true; return;} _ currentframetime-= elapsedtime; If (_ currentframetime <0) {_ currentframetime = frameduration; advanceframe (); updatedisplay ();}} /// <summary> /// maintain the frame size During Scaling /// </Summary> Public override void setscale (Double X, Double Y) {_ framewidth/= _ scalex; _ frameheight/= _ scaley; base. setscale (x, y); _ framewidth * = x; _ frameheight * = y; updatedisplay ();}}

Note that for the rowframe attribute that returns an integer value, you cannot simply round down or forcibly replace the evaluate result, because the result of the floating point operation is incorrect, A general game can ignore the error of floating point operations, but when the floating point value is converted into an integer, this error may lead to a qualitative leap.
5. Simple test code is written here for the test. The more important test is to observe the effect during actual running.
        public void ProcessTest()        {            AnimatedSprite target = new AnimatedSprite();            target.Texture = new Texture2D(0, 256, 256);            target.SetTotalFrame(16);            target.SetFrameSize(64, 64);            target.CenterPosition = Vector.Zero;            Assert.IsTrue(target.CurrentFrame == 0);            Assert.IsTrue(target.Finished == false);            double elapsedTime = 0.32;            MultiProcess(target, elapsedTime);            Assert.IsTrue(target.CurrentFrame == 3);            MultiProcess(target, elapsedTime);            MultiProcess(target, elapsedTime);            MultiProcess(target, elapsedTime);            MultiProcess(target, elapsedTime);            MultiProcess(target, elapsedTime);            MultiProcess(target, elapsedTime);            MultiProcess(target, elapsedTime);            Assert.IsTrue(target.Finished == true);            Assert.IsTrue(target.CurrentFrame == 15);        }

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.