Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags
(2 edits)

I almost finished to work on the character controller and entity system, and beside lots of bug fixes and polishing left, it will not change a lot until the end of the project.
So it's time for little bit explanation over some main components of the engine.


Entities and Planets

The engine is similar with a point and click engine : entities (characters and objects to interact with) are put on the surface of the ground and the player can move around by clicking any position on the x-axis.
Except that in our case, the scene is a small planet where player can walk around.The ground is not flat and entities can lie anywhere around the planet, which make it a little bit more complicated in terms of coordinate and orientation.

So I had to organize it in 3 different frames of reference, each allowing to focus on a specific level of detail.
- world reference frame: planet surface and sky background are set in absolute coordinate and can only rotate around the center of the planet, respectively planet rotation for simulating camera rotation to follow player, and sky rotation for animating it in a simple way. This all takes place in " Planet.java"
- planet reference frame: all entities belong to a planet and coordinates are defined with a relative angle and distance for the center. This is handled inside " Entity.java" and their derived classes, such as "Character.java".
- entity reference frame: entities are drawn and animated in their local position.
Characters and objects have many parts to draw, with offsets which can be translated and rotated for animation. So, it's very useful to not have to worry about their real position and orientation and just taking care of local details.
All entities are composed with an instance of a class " RenderData.java" or any derivated one from "Render" folder to handle this.

For example, here is the pipeline to draw a simple entity.

1) in world reference frame ("Planet.java")

set planet absolute position and orientation

        mat.translate(center.x, center.y, 0);
        mat.rotateRad(0, 0, 1, -angle);

draw surface texture

        batch.setTransformMatrix(mat);
        batch.begin();
        surface.Draw(batch);
        batch.end();

draw entities

        for (Entity entity : entities)
        {
            entity.Draw(mat, batch);
        }

revert render matrix to original state

        mat.rotateRad(0, 0, 1, angle);
        mat.translate(-center.x, -center.y, 0);
    }

2) in planet reference frame ("Entity.java")

compute cartesian coordinates

       float cosa = (float)Math.cos(angle);
       float sina = (float)Math.sin(angle);        
       float localX = sina * dist;
       float localY = cosa * dist;

set entity position and orientation

       mat.translate(localX, localY, 0);
       mat.rotateRad(0, 0, 1, -angle);
       batch.setTransformMatrix(mat);
       mat.rotateRad(0, 0, 1, angle);
       mat.translate(-localX, -localY, 0);

draw entity

       batch.begin();
       renderData.Draw(batch);
       batch.end();

3) in local reference frame (example with "Billboard.java")

just draw in local reference

       sprite.draw(batch);

And here you can see the result when putting all together: planet, vegetation and main character.
But be aware: those assets are not the final ones (especially the character controller), but only first draft to test if the system is working well, before the artist spend so much time polishing the assets, coloring, etc... once we are sure the method will not change.



Character Controller & Animation

So, given the previously described entity system, character movement will be as simple as changing the angle for moving along the ground, and changing the distance for jumping (not sure if we will need this one). All the character animations will be handled independently in the local reference frame, in " Human.java" for human type character.

Let's talk about the way we split the work between programmer and artist, because it's a little bit unusual. @PouleyKetchoupp is not only good at doing 2D art, he's also a talented programmer, and he will not be afraid to change some chunk of the code as he needs, and he already started.

So the way we will do the animation is a little bit special too.
All different parts of the body consists in separate sprites will are animated procedurally from code.

Here with the temporary assets:


I already wrote a basic system to handle walk animation, and it will be polished and new features will be added from this, either by me for big changes or by the artist directly for smaller adjustments.
But we will see. If I'm too much busy to finish other parts of the code, he will be able to handle himself all the animation code if needed.

Now, some details about the procedural animation code.

- During movement, oscillations based on walk cycle time are used to calculate vertical and horizontal offsets for the legs :

update walk cycle time

       step += deltatime * moveDir * cycleSpeed
       step -= MathUtils.floor(step);

compute oscillations

       float angle = MathUtils.PI2 * step;
       float sina = MathUtils.sin(angle);
       float cosa = MathUtils.cos(angle);

horizontal offset

       float legOffset = walkLegOffset * legL.getWidth() * sina;

vertical offset

       float legStepL = cosa > 0.f ?
              stepStrength * legL.getWidth() * cosa : 0.f;
       float legStepR = cosa < 0.f ?
              -stepStrength * legR.getWidth() * cosa : 0.f;

apply to leg sprites

       legL.setPosition(
              -0.5f * legL.getWidth() + legOffset,
              legStepL);
       legR.setPosition(
              -0.5f * legR.getWidth() - legOffset,
              legStepR);

- and small rotation of the arms:

arm rotation angle

       if (step <= 0.5f)
              armAngle = walkArmAngle * (4.f * step - 1.f);
       else
              armAngle = walkArmAngle * (4.f * (1.f - step) - 1.f);

apply to arm sprites

       armL.setRotation(armAngle);
       armR.setRotation(-armAngle);

- To have the arms rotating around the right pivot, it's important to initialize somewhere the right origin :

arbitrary pivot position

       armL.setOrigin(
              armL.getWidth() * 0.5f,
              armL.getHeight() * 0.8f);

- Then, there is also little more to take care when the character change direction, to flip the body parts :

       armL.setFlip(dir < 0, false);
       armR.setFlip(dir < 0, false);
       legL.setFlip(dir < 0, false);
       legR.setFlip(dir < 0, false);
       // etc...


Interaction Animation

There will be some special animations while interacting with the environment, and it will have to be written procedurally in code too.
Since we will need only few simple animations (take, drop, etc), this will do.



Now I'm working on a dialogue system, and I hope I can post something about it soon!