Saturday, 5 September 2015

Rendering sprites #2 (part 9)

So we're taking baby steps going forward. First because I want to detail how I'm slowly progressing to something that allows the user to fully control the character, but also because time is too short to do it all at once:) I'm trying to find and use every spare few minutes I can find between family, work and playing games. Owh and I'm still hard at work building a HALO suit, that's turning out a much larger project then I initially thought.

First off, I made a few more changes on the work done so far just to complete it. I ended up enhancing spritesheet.h so that sprites are centered but you add an offset to position it properly. This also allows the animation to give flexibility on the movement.

Our sprite struct thus is now defined as:
// structure to keep data about our spritesheet
typedef struct sprite {
  GLfloat left;                   // left position of our sprite in our texture
  GLfloat top;                    // top position of our sprite in our texture
  GLfloat width;                  // width of our sprite
  GLfloat height;                 // height of our sprite
  GLfloat offsetx;                // horizontal offset
  GLfloat offsety;                // vertical offset
} sprite;

Our array of sprites now defines about the first 4 rows in our spritesheet. That is as far as I'll go for now. Eventually I'll add the climb in because I need that for this little demo but I'll leave most of the other animations alone.

Defining animations

The next step is to bring some structure to our animations. We're going to break up all the animations into small pieces that can be sequenced depending on the users input. For now we'll just switch between them so we can see if we've got them right but eventually after each animation ends we'll check for user input and determine what the next animation is.

I've define a struct in engine.h that allows me to define one animations sequence:
typedef struct animation {
  GLint     firstSprite;            // first sprite of animation
  GLint     lastSprite;             // last sprite of animation
  bool      flip;                   // flip sprite horizontally
  GLfloat   moveX;                  // add this to our X after anim is finished
  GLfloat   moveY;                  // add this to our Y after anim is finished  
} animation;

To make it easier to use my animation I've also added an enum to engine.h that lists all the different animations:
enum conrad_animations {
  CR_ANIM_LOOK_LEFT,
  CR_ANIM_TURN_LEFT_TO_RIGHT,
  CR_ANIM_LOOK_RIGHT,
  CR_ANIM_TURN_RIGHT_TO_LEFT,

...

  CR_ANIM_JUMP_UP_LEFT,
  CR_ANIM_COME_DOWN_LEFT,

  CR_ANIM_COUNT
};

The animations themselves are then defined in an array in engine.c:
// now define our animations
animation conradAnim[] = {
    0,    0,  false,   0.0,  0.0,    //  0 - look left
    0,    6,  false,   0.0,  0.0,    //  1 - turn from looking left to looking right
    6,    6,  false,   0.0,  0.0,    //  2 - look right
    6,    0,  false,   0.0,  0.0,    //  3 - turn from looking right to looking left

...

   50,   66,  false,   0.0,  0.0,    // 16 - jump up (facing right)
   67,   78,  false,   0.0,  0.0,    // 17 - coming back down (facing right)   
};

The code for displaying the animation hasn't changed much. We're just cycling through a single animation instead of all defined sprites.

I've turned off the back ground for now and I'm displaying all sprites in the current selected animation on the left and right slightly overlapped to help with changing the offset of each sprite. Until we actually start with controlling the character we won't know if we've gotten these right.



The final change at this point is changing the animation. I've removed the camera control (this will be changes anyway) and for the time being am sending key presses to the engine (again I'm trying to leave any GLFW specific code out of the engine). In the engine I'm simply keeping a stack of unhandled keypresses which I check at the end of each animation. This won't be the final solution for when we start to control our character but it does the job for cycling through the animations without loosing keypresses when the animation hasn't finished yet.

Download the source code here

So where from here?

The next step is simple, to react on keyboard input and actually control the character.

At first we won't worry about any character interaction with his surroundings and implement basic walk left, walk right, roll left, roll right and straight jump logic. I may through in a few more animations just for the heck of it.

After that we'll add a more appropriate background and start looking at properly interacting with it.

No comments:

Post a Comment