Jump to content
Sign in to follow this  
  • entries
    5
  • comments
    5
  • views
    573

Project: 13 RONIN

13 RONIN - DevLog #4 - Say hello to Ester!

ERASERHEAD STUDIO

971 views

Banner950x297

Ester (Eraserhead Animation Editor) is a new tool I've build that will make it easier for me to describe what different animations a spritesheet contains and their different characteristics e.g. how long each frame should be displayed. I can then export the description, as a json-file, and then together with the spritesheet load it into the game and use it to set up my "in game" animations.

This is how Ester looks with a spritesheet loaded and one animation created:  
ester.thumb.png.0a33fc35b599b3fc6f40919d930f042b.png

I'll easily admit that building this tool has been a detour that's taken far too much time from any actual game development, but please let me give you the background.

 

Background

13 RONIN is a pixel-art game with animations based on spritesheets, just like the one below:
Animation_Demo_Spritesheet.thumb.png.7697b6db5af85a926bf570803714a78b.png

The spritesheet together with a json-file describing the sheet are read into the game and turned into different animations. A process that works quite well.
Draw_cropped.gif.2dc83ea18fc755623d29b5846c9e2171.gif  
This is the "Draw"-animation beginning at row 3 and column 1 as described by the json-file below. In this example each frame is displayed for 150 milliseconds

Draw2_cropped.gif.f707155d96c8b66bd1085ff198af9f49.gif
Same animation as above but with individual frame times

 

The description file

The description file started out quite small, but since I prefer to hard-code as few things as possible and also want room for adjustment, the file grew.

This is a file describing the "Draw"-animation starting at row 3 and column 1:

    {
        // General description of the spritesheet
        "spritesheet": { 
            
            // Size of sheet in columns and rows, 
            // where each cell is a sprite
            "gridSize": { 
                width: 13,    // The sheet has a size of 13 columns 
                height: 5    // and 5 rows of sprites
             }
            
            // Size of a sprite in pixels
            "spriteSize": { 
                width: 160,        // Each sprite has a size 
                height: 160        // of 160x160 pixels
            }
        }
    
        // Default values for animation frames
        "frameDefaults": {
        
            // Intended for describing hit-boxes and such. This
            // example would give a hitbox located at same position
            // as the sprite and of the same size
            "margin": { 
                "top": 0,
                "right": 0,
                "bottom": 0,
                "left": 0
            },
            
            // Offset value used when positioning and drawing
            // sprites.
            "offset": { 
                x: 10,    // The sprites should be drawn 10 pixels
                y: 0    // to the right of the destination point
            }
            
            // Frame duration. Display each frame 200 milliseconds
            // before advancing to next frame
            "duration": 200
        },
        
        // Animations found in the spritesheet
        "animations": [
    
            // An animation
            {
                // Name used for identification
                "name": "Draw",        
    
                // OPTIONAL. Will override default setting
                "offset": { 
                    x: 0,    // No offset for this animation
                    y: 0
                },     
                
                // OPTIONAL. Will override default setting
                "margin": { 
                    "top": 0,
                    "right": 0,
                    "bottom": 0,
                    "left": 0
                },
                
                // OPTIONAL. Will override default setting.
                // Frame duration for this animation is 150
                // milliseconds
                "duration": 150,
                                
                // Start location in grid                
                "index": { 
                    x: 0,    // This animation begins with image at
                    y: 2    // row 3 and column 1
                },
                
                // This animation contains 13 frames starting
                // at "index"
                "frameCount": 13,
                
                // OPTIONAL. Using this property it's possible to
                // set frame duration for individual frames
                "frames": [    
                ]
            }
        ]
    }

Writing and maintaining the description files is very tedious and it's also very easy to make mistakes. Remember that the file above only contains one animation and that is an animation without any individual frame duration times. To get the animation seen in the second example above following "frames"-section has to be added:

    "frames": [
        {
            "index": 0,
            "duration": 200
        },
        {
            "index": 1,
            "duration": 175
        },
        {
            "index": 2,
            "duration": 175
        },
        {
            "index": 3,
            "duration": 200
        },                    
        {
            "index": 4,
            "duration": 300
        },            
        {
            "index": 5,
            "duration": 175
        },        
        {
            "index": 10,
            "duration": 175
        },
        {
            "index": 11,
            "duration": 175
        },
        {
            "index": 12,
            "duration": 1000
        }                        
    ]

We now have 3 pages of json and only one animation described. I grew tired of this and felt a need for a tool to assist me in describing and tuning the animations as well as automatically generating the json. Together with a desire to improve my skills as a front-end developer I started the development of Ester.

 

Tech

Ester is an Electron based application using React as UI-framework. I'm not really a front-end developer and since this isn't the main focus of the blog I won't dwell and deeper into the subject, but for anyone interested in trying out these technologies, there are a lot of posts written on the subject, so just use your magic friend google and you'll get lucky.

And please feel free to browse or clone the Ester-repo. I think the project- and component-structure is quite good, but I'm sure there could be a lot of improvements made on the JavaScript- and CSS-code. If you find something really horrific please let me know.

 

Using Ester

If you would like to give Ester a try, please visit my BitBucket account for further instructions. 

If you find Ester useful, run into bugs or have ideas for new features, please don't hesitate from letting me know.

Please be aware that this is not a finished product, but something I'm working on as part of the game development project. Fatal crashes might happen and breaking changes be introduced.

You're also very welcome to clone and extend the product yourself.

Happy coding!  
/jan.

 

NOTE. As always, everything I show, share or write about here is work under progress and subject to change.



3 Comments


Recommended Comments

Hello Ester! ;)

Looks pretty cool, and reasonably simple to work with.

Share this comment


Link to comment

Hello Ester! ;)

Looks pretty cool, and reasonably simple to work with.

Share this comment


Link to comment

Thanks for your nice words!

I know the UI could be better, but I felt a little bit short of time, and this was kind of good enough 🙂

As I will be focusing on creating animations during the summer I'll fix bugs and glitches as I found then and hopefully have a release candidate of Ester ready in the fall. By then I'll probably also have an .exe or installable version ready.

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
  • Advertisement
  • Blog Entries

  • Similar Content

    • By null777
      Hello, I'm working on developing a 2D platformer. In the game, the player can run/jump/etc, and they can also often shoot at the same time that they're performing these other actions. For programming these actions, I have no issue constructing the relevant FSMs and getting them to behave as intended. My issue comes when I need to find the right frames or animations for the sprite to show. Should the game just check if the player is shooting and what state they're in and then have the right animations hardcoded in to play in each possible outcome of that if statement? I've considered some potentially more elegant solutions like having a normal sprite sheet and then a shooting sprite sheet where the shooting sheet has the corresponding shooting frame at the same position in the sheet. Then the animator would just have to load the correct frame of its current sheet no matter what, and whenever the player is shooting, it simply swaps out the regular sprite sheet for the shooting one.

      Basically I can think of a few different ideas that sort of solve this problem, but none of them seem ideal. I wanted to know what the generally accepted best practices are for this type of problem. Any advice would be appreciated.
    • By nxrighthere
      BenchmarkNet is a console application for testing the reliable UDP networking solutions.
      Features:
      Asynchronous simulation of a large number of clients Stable under high loads Simple and flexible simulation setup Detailed session information Multi-process instances Supported networking libraries:
      ENet UNet LiteNetLib Lidgren MiniUDP Hazel Photon Neutrino DarkRift More information and source code on GitHub.
      You can find the latest benchmark results on the wiki page.
       
    • By CommanderLake
      I've been experimenting with my own n-body simulation for some time and I recently discovered how to optimize it for efficient multithreading and vectorization with the Intel compiler. It did exactly the same thing after making it multithreaded and scaled very well on my ancient i7 3820 (4.3GHz). Then I changed the interleaved xy coordinates to separate arrays for x and y to eliminate the strided loads to improve AVX scaling and copy the coordinates to an interleaved array for OpenTK to render as points. Now the physics is all wrong, the points form clumps that interact with each other but they are unusually dense and accelerate faster than they decelerate causing the clumps to randomly fly off into the distance and after several seconds I get a NaN where 2 points somehow occupy exactly the same x and y float coordinates. This is the C++ DLL:
      #include "PPC.h" #include <thread> static const float G = 0.0000001F; const int count = 4096; __declspec(align(64)) float pointsx[count]; __declspec(align(64)) float pointsy[count]; void SetData(float* x, float* y){ memcpy(pointsx, x, count * sizeof(float)); memcpy(pointsy, y, count * sizeof(float)); } void Compute(float* points, float* velx, float* vely, long pcount, float aspect, float zoom) { #pragma omp parallel for for (auto i = 0; i < count; ++i) { auto forcex = 0.0F; auto forcey = 0.0F; for (auto j = 0; j < count; ++j) { if(j == i)continue; const auto distx = pointsx[i] - pointsx[j]; const auto disty = pointsy[i] - pointsy[j]; //if(px != px) continue; //most efficient way to avoid a NaN failure const auto force = G / (distx * distx + disty * disty); forcex += distx * force; forcey += disty * force; } pointsx[i] += velx[i] -= forcex; pointsy[i] += vely[i] -= forcey; if (zoom != 1) { points[i * 2] = pointsx[i] * zoom / aspect; points[i * 2 + 1] = pointsy[i] * zoom; } else { points[i * 2] = pointsx[i] / aspect; points[i * 2 + 1] = pointsy[i]; } /*points[i * 2] = pointsx[i]; points[i * 2 + 1] = pointsy[i];*/ } } This is the relevant part of the C# OpenTK GameWindow:
      private void PhysicsLoop(){ while(true){ if(stop){ for(var i = 0; i < pcount; ++i) { velx[i] = vely[i] = 0F; } } if(reset){ reset = false; var r = new Random(); for(var i = 0; i < Startcount; ++i){ do{ pointsx[i] = (float)(r.NextDouble()*2.0F - 1.0F); pointsy[i] = (float)(r.NextDouble()*2.0F - 1.0F); } while(pointsx[i]*pointsx[i] + pointsy[i]*pointsy[i] > 1.0F); velx[i] = vely[i] = 0.0F; } NativeMethods.SetData(pointsx, pointsy); pcount = Startcount; buffersize = (IntPtr)(pcount*8); } are.WaitOne(); NativeMethods.Compute(points0, velx, vely, pcount, aspect, zoom); var pointstemp = points0; points0 = points1; points1 = pointstemp; are1.Set(); } } protected override void OnRenderFrame(FrameEventArgs e){ GL.Clear(ClearBufferMask.ColorBufferBit); GL.EnableVertexAttribArray(0); GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); mre1.Wait(); are1.WaitOne(); GL.BufferData(BufferTarget.ArrayBuffer, buffersize, points1, BufferUsageHint.StaticDraw); are.Set(); GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 0, 0); GL.DrawArrays(PrimitiveType.Points, 0, pcount); GL.DisableVertexAttribArray(0); SwapBuffers(); } These are the array declarations:
      private const int Startcount = 4096; private readonly float[] pointsx = new float[Startcount]; private readonly float[] pointsy = new float[Startcount]; private float[] points0 = new float[Startcount*2]; private float[] points1 = new float[Startcount*2]; private readonly float[] velx = new float[Startcount]; private readonly float[] vely = new float[Startcount];  
      Edit 0: It seems that adding 3 zeros to G increases the accuracy of the simulation but I'm at a loss as to why its different without interleaved coordinates. Edit 1: I somehow achieved an 8.3x performance increase with AVX over scalar with the new code above!
    • By Iw/biz
      I'm an animator/programmer, and my specialty is animating static images using 3D modelling software (Blender). Looking for a 2d artist who can produce NSFW images (NOT the sprites/spritesheets, just a static scene) to use in an action-RPG style of h-game. Mostly for a hobby joint-project, but It would be a good opportunity for both parties to practice their skills. Please message if you're interested or want to invite me to an already established team. Thanks!
    • By Effekseer
      Effekseer Project develops "Effekseer," which is visual software for creating open source games; on September 13,
      I released "Effekseer 1.4," which is the latest major version release. 
      Effekseer is a tool to create various visual effects used in games and others.
      With Effekseer, you can easily create various visual effects such as explosion, light emission, and particle simply by specifying different parameters.
      Effekseer's effect creation tool works on Windows and macOS.
      The created visual effects can be viewed on Windows, macOS, Linux, iOS, Android and other environments with DirectX, OpenGL and so on.
      In addition, there are plugins / libraries for game engines such as Unity and UnrealEngine4 to view visual effects.
      Effekseer 1.4 is an updated version of Effekseer 1.3 released in November 2017.
      This update contains the following changes:
      The renewal of UI. Support the tool for macOS. Addition of a function to read FBX with animation. Addition of parameters to protect collied effects and objects. Addition of parameters for easier control of the effects. In addtion I improve plugins/libraries for Unity, UnrealEngine4 and Cocos2d-x.
      Besides that, more than 40 new sample effects have been added and many bugs have been fixed.
      Effekseer 1.4 is available on the project website.
      The license for the software is the MIT license.
      Effekseer 
      http://effekseer.github.io/

      Github
      https://github.com/effekseer/Effekseer
      
      Sample Effects.
      Tool Demo
       

      View full story
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!