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

13 RONIN - DevLog #3 - The movie analogy

ERASERHEAD STUDIO

662 views

Banner950x297

Here in Stockholm it's been unusually hot and dry for this season of the year and I'm quite convinced that the pharmacies have broken a new record in anti-histamine sales. Last night we were finally blessed with thunder and rain and today the air is cool and nice and the pollen gone.

I've sneezed quite a lot the last couple of weeks but I've also done some coding. My primary focus has been building an animation framework for use in intro, cutscenes and background movements and coding an editor for animating sprites. Ester (Eraserhead animation editor) will be the subject of an upcoming dev log and this dev log will be about the animation framework.

1076747577_Animationdemo180604.gif.5e60a76a65ad46047cdcf090856ed361.gif

This is an animation demo and not part of the game

Animation framework

The purpose of the animation framework is to ease setting up and running sequences of multiple animations. The need for this arose with my desire to create an animated intro with objects moving in different patterns. But I will also use this framework for pre- and post-fight-animations as well as background animations.

When finished the animation framework will contain:

  • Support for spritesheet-based animations
  • Builders for setting up animations by code
  • Simple script-language for setting up scenes
  • Loader and parser for script-files

In addition to this, I will probably build an editor to use with the script-language for trying out and previewing animations.

The movie analogy

When designing and naming the building blocks of the framework I've taken a "movie scene"-approach and used a nomenclature found in movie scripts. That gave me following main classes:

  • Scene
  • Actor
  • Action
  • Animation

"Animation" might not be a name known from movie scripts, but I kept the name to encourage its use outside of the "animated scene" context. As long as you keep track of calling the update- and draw-methods both actors and animations can be used without a scene.

Animation-Page-1.png.68a449c72c3ba33dd6676e81242cf5b6.png

A simplified diagram describing the relationships between the classes

Scene

Think of a scene just the like a scene in a movie or a theater. It's a "room" where something takes place. A scene can have a name, background image and any number of actors. You draw it on the screen by calling its Draw-method.

Animation_Demo_Background.png.fa866b4c68d9e5ec7fd27ce7d91966c1.png

Background for our demo

Actor

Unlike in a movie or theater, an actor is not only characters but all things living or dead that has it's own image and is separate from the background e.g. character, bullets flying, rising sun.

An actor has a location, it can be visible or hidden, and has a collection of actions to perform that can be looped when done. An actor also has an animation as it's current "gesture".

Action

Just like in the movies, an action is something an actor does, i.e. an actor will act according to its actions.

Some of the available actions are:

  • Show - draw animation
  • Hide - don't draw animation
  • SetPosition - set position of actor
  • BasicMove - move actor to destination with given velocity and acceleration
  • ChangeGesture - change animation

Animation

An animation is based on a spritesheet, start index in the sheet and a frame count. This determines how the actor will appear on the screen.

A note on naming. The property for the animation is named Gesture in the Actor-class, that is a choice I made to keep the movie analogy consistent. I've named the class Animation to encourage use of it outside of the "animated scene"-context.

Idle.gif.91480bbd157d95ee29f9584ef1d978a9.gif

Our famous actor doing one of it's gestures

How to

To create the scene in the demo above following steps have to be made:

  1. Load content
  2. Create an animation sheet configuration
  3. Create an animation factory
  4. Create an actor
  5. Create the scene
  6. Start the scene
  7. Draw scene

Step 1 - 5 can all be done in the Initialize-method of the Game-class.

Step 1 - Load content

As a first step we load background- and spritesheet-images as textures.

var background = Content.Load<Texture2D>("Animation_demo_background");
var texture = Content.Load<Texture2D>("Animation_demo_spritesheet");

Animation_Demo_Spritesheet.thumb.png.9f95467f2b19667dc9edb4ea9a302dea.png

The demo spritesheet

Step 2 - Create animation sheet configuration

Then we create a configuration describing animations found in the spritesheet. This object will later be used as argument to our animation factory.

var sheetConf =
  AnimSheetConfigBuilder
  .Begin()
  .Name("Samurai gestures")
  .GridSize(new Point(13, 4))
  .SpriteSize(new Point(160, 160))
  .DefaultFrameDuration(150)
  .AddAnimation("Idle", new Point(0, 0), 6)
  .AddAnimation("Bow", new Point(0, 3), 11)
  .AddAnimation("Draw", new Point(0, 2), 13)
  .AddAnimation("Walk wo sword", new Point(0, 1), 8)
  .AddAnimation("Walk w sword", new Point(0, 4), 8)
  .Build();

We create a configuration describing a spritesheet with a size of 13 columns and 4 rows where each sprite has a size of 160 x 160 pixels. The spritesheet is called "Samurai gestures" and default frame duration for all animations in this sheet is 150 milliseconds. It contains four different animations. Note that all names must be unique.

Step 3 - Create animation factory

When the sheet config is ready this step is easy. Call the AnimationFactory-constructor passing in the spritesheet texture and the sheet configuration. Our factory is ready.

var animFactory = new AnimationFactory(texture, sheetConf);

Step 4 - Create actor

Just as it takes some time for an actor to prepare for a big movie role, it takes some coding for us to set up the actor for our scene.

var actor =
  ActorBuilder
    .Begin(animFactory)
    .Actions(
      actionBuilder =>
      {
        return
          actionBuilder
            .Hide()
            .SetPosition(new Point(-120, -4))
            .ChangeAnimation("Walk wo sword")
            .LoopAnimation()
            .Show()
            .Move(new Point(-60, -4), 0.1f, 0.0f)
            .ChangeAnimation("Bow")
            .WaitForAnimation()
            .ChangeAnimation("Walk wo sword")
            .LoopAnimation()
            .Move(new Point(110, -4), 0.1f, 0.0f)
            .ChangeAnimation("Draw")
            .WaitForAnimation()
            .ChangeAnimation("Idle")
            .WaitForAnimation()
            .ChangeAnimation("Walk w sword")
            .LoopAnimation()
            .Move(new Point(312, -4), 0.1f, 0.0f)
            .Build();
      })
    .Build();

actor.Loop = true;

Here we use the ActorBuilder in combination with the ActionBuilder to create the actor and the collection of actions to perform. All these actions will be performed in sequence and when done the actions will, thanks to the "actor.Loop = true;" statement, be restarted.

Step 5 - Create scene

As a last building step we tie everything together by creating our scene, and for this, we also have a dedicated builder.

_scene =
  SceneBuilder
    .CreateScene(animFactory)
    .Name("Demo")
    .Background(background)
    .AddActor(actor)
    .Build();

  Our scene is now ready.

Step 6 - Start scene

If you run the project you'll find that nothing happens. That's because we haven't included the scene in the game loop yet.

Add following lines to the Update-method:

if (_scene.State == State.NotStarted)
	_scene.Start();
_scene.Update(gameTime);

Step 7 - Draw scene

Still, nothing happens. It's because we're still not drawing the scene. And following line to the Draw-method:

_scene.Draw(_spriteBatch, Vector2.Zero);

Run the project and enjoy!

The future

You're as always more than welcome to download the code and use it in any way you like, but since it's still early days please regard it more as inspiration than a working framework. I'm sure there are lots of bugs. And changes will come.

If not discouraged, visit my BitBucket-account and get going, or wait for an announcement of a more stable version.

Please visit Eraserhead Studio for more.

 

Happy coding!

/jan.

Avatar_transparent_background.png.f044a47dac917fdb89bbba1949a8207a.png

NOTE. As always, everything I publish here or on any other site is work in progress and subject to change.

 




0 Comments


Recommended Comments

There are no comments to display.

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 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
    • 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
       
    • By Pixelated_Nate
      Hello!
      I'm currently looking for a programmer for my hobby project, to be built in Unity and released on the PC.
      It's currently in the pre-alpha stages, as I am currently working out how all the systems should eventually work and quickly realized I didn't have the coding knowledge to achieve it. (I'm more of an artist than a coder.)
      This is where you can potentially come in!
      Should the game be released, all funds accrued will be split equally and credit will of course be given wherever applicable, I can't guarantee it will get released, however.
       
      The Premise
      A fantasy, pixel art game in which you build a city and look after its inhabitants by supplying them with the things they want. (Education, Politics, Entertainment, ect..)
      The people can be visually customized, gain skills & jobs, marry, have children, grow old and die, their lives are at your whim. 
      As you are building your city, you'll find that some citizens can go on quests for unique building materials, this turns the game into a X-Com style turn-based strategy, using the people that you send.
      Your city can be built however you want, with decorations and such, though your people may get upset if you don't give them what they need/want and abandon your city.
       
      The Programmer
      As the only coder in our project duo, I'd really need to insist that you know your way around a coding environment fairly well,
      as well as be able to utilize those scripts with Unity, the engine the game is being built in.
      The project will require:
      Pathfinding Coding UI Coding AI Coding Shader Coding (This may not be required if another method can be found)  
      Communication
      I've found using Google Drive for documents, Unity Collab for file-sharing and Discord for communication really helps keep everything tidy and easy to access.
      If you have any problems with these systems, please let me know.
       
      If you are interested, please contact me at nathan.jenkins1012@gmail.com 
      Whilst it is difficult to showcase coding, some examples of your work would be highly appreciated. 
       
      Thanks for reading!
       
×

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!