General Characters refactor

This commit is contained in:
Sebastian Krzyszkowiak 2018-02-10 04:29:57 +01:00
parent f0417b09f6
commit aa1f7f3ab9
2 changed files with 82 additions and 89 deletions

View file

@ -44,16 +44,11 @@ SYMBOL_EXPORT void SelectSpritesheet(struct Game* game, struct Character* charac
} else { } else {
character->successor = NULL; character->successor = NULL;
} }
character->repeat = tmp->repeat; character->repeats = tmp->repeats;
character->pos = 0; character->pos = 0;
if (character->bitmap) { if (character->bitmap) {
//if ((al_get_bitmap_width(character->bitmap) != tmp->width / tmp->cols) || (al_get_bitmap_height(character->bitmap) != tmp->height / tmp->rows)) {
// al_destroy_bitmap(character->bitmap);
// character->bitmap = al_create_bitmap(tmp->width / tmp->cols, tmp->height / tmp->rows);
//}
al_reparent_bitmap(character->bitmap, tmp->bitmap, 0, 0, tmp->width / tmp->cols, tmp->height / tmp->rows); al_reparent_bitmap(character->bitmap, tmp->bitmap, 0, 0, tmp->width / tmp->cols, tmp->height / tmp->rows);
} else { } else {
//character->bitmap = al_create_bitmap(tmp->width / tmp->cols, tmp->height / tmp->rows);
character->bitmap = al_create_sub_bitmap(tmp->bitmap, 0, 0, tmp->width / tmp->cols, tmp->height / tmp->rows); character->bitmap = al_create_sub_bitmap(tmp->bitmap, 0, 0, tmp->width / tmp->cols, tmp->height / tmp->rows);
} }
PrintConsole(game, "SUCCESS: Spritesheet for %s activated: %s (%dx%d)", character->name, character->spritesheet->name, al_get_bitmap_width(character->bitmap), al_get_bitmap_height(character->bitmap)); PrintConsole(game, "SUCCESS: Spritesheet for %s activated: %s (%dx%d)", character->name, character->spritesheet->name, al_get_bitmap_width(character->bitmap), al_get_bitmap_height(character->bitmap));
@ -64,7 +59,7 @@ SYMBOL_EXPORT void SelectSpritesheet(struct Game* game, struct Character* charac
PrintConsole(game, "ERROR: No spritesheets registered for %s with given name: %s", character->name, name); PrintConsole(game, "ERROR: No spritesheets registered for %s with given name: %s", character->name, name);
} }
SYMBOL_EXPORT void ChangeSpritesheet(struct Game* game, struct Character* character, char* name) { SYMBOL_EXPORT void EnqueueSpritesheet(struct Game* game, struct Character* character, char* name) {
if (character->successor) { if (character->successor) {
free(character->successor); free(character->successor);
} }
@ -114,21 +109,17 @@ SYMBOL_EXPORT void RegisterSpritesheet(struct Game* game, struct Character* char
s = malloc(sizeof(struct Spritesheet)); s = malloc(sizeof(struct Spritesheet));
s->name = strdup(name); s->name = strdup(name);
s->bitmap = NULL; s->bitmap = NULL;
s->cols = strtol(al_get_config_value(config, "", "cols"), NULL, 10);
s->rows = strtol(al_get_config_value(config, "", "rows"), NULL, 10); s->rows = strtol(al_get_config_value(config, "", "rows"), NULL, 10);
s->cols = strtol(al_get_config_value(config, "", "cols"), NULL, 10);
s->blanks = strtol(al_get_config_value(config, "", "blanks"), NULL, 10); s->blanks = strtol(al_get_config_value(config, "", "blanks"), NULL, 10);
s->delay = strtod(al_get_config_value(config, "", "delay"), NULL); s->delay = strtod(al_get_config_value(config, "", "delay"), NULL);
s->flip = false; s->width = 0;
const char* val = al_get_config_value(config, "", "repeat"); s->height = 0;
const char* val = al_get_config_value(config, "", "repeats");
if (val) { if (val) {
s->repeat = strtod(val, NULL); s->repeats = strtod(val, NULL);
} else { } else {
s->repeat = 0; s->repeats = 0;
}
s->kill = false;
const char* kill = al_get_config_value(config, "", "kill");
if (kill) {
s->kill = strtol(kill, NULL, 10);
} }
s->successor = NULL; s->successor = NULL;
const char* successor = al_get_config_value(config, "", "successor"); const char* successor = al_get_config_value(config, "", "successor");
@ -145,23 +136,29 @@ SYMBOL_EXPORT struct Character* CreateCharacter(struct Game* game, char* name) {
PrintConsole(game, "Creating character %s...", name); PrintConsole(game, "Creating character %s...", name);
struct Character* character = malloc(sizeof(struct Character)); struct Character* character = malloc(sizeof(struct Character));
character->name = strdup(name); character->name = strdup(name);
character->angle = 0;
character->bitmap = NULL; character->bitmap = NULL;
character->data = NULL; character->spritesheet = NULL;
character->spritesheets = NULL;
character->pos = 0; character->pos = 0;
character->pos_tmp = 0; character->pos_tmp = 0;
character->successor = NULL;
character->x = -1; character->x = -1;
character->y = -1; character->y = -1;
character->tint = al_map_rgb(255, 255, 255);
character->pivotX = 0.5; character->pivotX = 0.5;
character->pivotY = 0.5; character->pivotY = 0.5;
character->scaleX = 1.0;
character->scaleY = 1.0;
character->angle = 0;
character->confineX = -1; character->confineX = -1;
character->confineY = -1; character->confineY = -1;
character->spritesheets = NULL; character->flipX = false;
character->spritesheet = NULL; character->flipY = false;
character->successor = NULL;
character->repeat = 0;
character->shared = false; character->shared = false;
character->dead = false; character->repeats = 0;
character->parent = NULL;
character->data = NULL;
return character; return character;
} }
@ -193,8 +190,8 @@ SYMBOL_EXPORT void DestroyCharacter(struct Game* game, struct Character* charact
free(character); free(character);
} }
SYMBOL_EXPORT void AnimateCharacter(struct Game* game, struct Character* character, float speed_modifier) { SYMBOL_EXPORT void AnimateCharacter(struct Game* game, struct Character* character, float delta, float speed_modifier) {
if (character->dead) { return; } speed_modifier *= delta / (1 / 60.f); // TODO: proper delta handling
if (speed_modifier) { if (speed_modifier) {
character->pos_tmp++; character->pos_tmp++;
if (character->pos_tmp >= character->spritesheet->delay / speed_modifier) { if (character->pos_tmp >= character->spritesheet->delay / speed_modifier) {
@ -203,16 +200,13 @@ SYMBOL_EXPORT void AnimateCharacter(struct Game* game, struct Character* charact
} }
if (character->pos >= character->spritesheet->cols * character->spritesheet->rows - character->spritesheet->blanks) { if (character->pos >= character->spritesheet->cols * character->spritesheet->rows - character->spritesheet->blanks) {
character->pos = 0; character->pos = 0;
if (character->repeat) { if (character->repeats) {
character->repeat--; character->repeats--;
} else {
if (character->spritesheet->kill) {
character->dead = true;
} else if (character->successor) { } else if (character->successor) {
SelectSpritesheet(game, character, character->successor); SelectSpritesheet(game, character, character->successor);
} }
} }
}
al_reparent_bitmap(character->bitmap, character->spritesheet->bitmap, al_reparent_bitmap(character->bitmap, character->spritesheet->bitmap,
(character->pos % character->spritesheet->cols) * (character->spritesheet->width / character->spritesheet->cols), (character->pos / character->spritesheet->cols) * (character->spritesheet->height / character->spritesheet->rows), (character->pos % character->spritesheet->cols) * (character->spritesheet->width / character->spritesheet->cols), (character->pos / character->spritesheet->cols) * (character->spritesheet->height / character->spritesheet->rows),
character->spritesheet->width / character->spritesheet->cols, character->spritesheet->height / character->spritesheet->rows); character->spritesheet->width / character->spritesheet->cols, character->spritesheet->height / character->spritesheet->rows);
@ -224,14 +218,12 @@ SYMBOL_EXPORT void MoveCharacter(struct Game* game, struct Character* character,
} }
SYMBOL_EXPORT void MoveCharacterF(struct Game* game, struct Character* character, float x, float y, float angle) { SYMBOL_EXPORT void MoveCharacterF(struct Game* game, struct Character* character, float x, float y, float angle) {
if (character->dead) { return; }
character->x += x; character->x += x;
character->y += y; character->y += y;
character->angle += angle; character->angle += angle;
} }
SYMBOL_EXPORT void SetCharacterPositionF(struct Game* game, struct Character* character, float x, float y, float angle) { SYMBOL_EXPORT void SetCharacterPositionF(struct Game* game, struct Character* character, float x, float y, float angle) {
if (character->dead) { return; }
character->x = x; character->x = x;
character->y = y; character->y = y;
character->angle = angle; character->angle = angle;
@ -246,30 +238,13 @@ SYMBOL_EXPORT void SetCharacterPivotPoint(struct Game* game, struct Character* c
character->pivotY = y; character->pivotY = y;
} }
SYMBOL_EXPORT void DrawScaledCharacterF(struct Game* game, struct Character* character, ALLEGRO_COLOR tint, float scalex, float scaley, int flags) { SYMBOL_EXPORT void DrawCharacter(struct Game* game, struct Character* character) {
if (character->dead) { return; } int w = al_get_bitmap_width(character->bitmap), h = al_get_bitmap_height(character->bitmap);
int spritesheetX = al_get_bitmap_width(character->bitmap) * (character->pos % character->spritesheet->cols); al_draw_tinted_scaled_rotated_bitmap(character->bitmap, character->tint,
int spritesheetY = al_get_bitmap_height(character->bitmap) * (character->pos / character->spritesheet->cols); w * character->pivotX, h * character->pivotY,
al_draw_tinted_scaled_rotated_bitmap_region(character->spritesheet->bitmap, spritesheetX, spritesheetY, al_get_bitmap_width(character->bitmap), al_get_bitmap_height(character->bitmap), tint, al_get_bitmap_width(character->bitmap) * character->pivotX, al_get_bitmap_height(character->bitmap) * character->pivotY, GetCharacterX(game, character) + al_get_bitmap_width(character->bitmap) * scalex * character->pivotX, GetCharacterY(game, character) + al_get_bitmap_height(character->bitmap) * scaley * character->pivotY, scalex, scaley, character->angle, flags); GetCharacterX(game, character) + w * character->pivotX, GetCharacterY(game, character) + h * character->pivotY,
} character->scaleX, character->scaleY, character->angle,
(character->flipX ? ALLEGRO_FLIP_HORIZONTAL : 0) | (character->flipY ? ALLEGRO_FLIP_VERTICAL : 0));
SYMBOL_EXPORT void DrawCharacterF(struct Game* game, struct Character* character, ALLEGRO_COLOR tint, int flags) {
DrawScaledCharacterF(game, character, tint, 1, 1, flags);
}
SYMBOL_EXPORT void DrawScaledCharacter(struct Game* game, struct Character* character, ALLEGRO_COLOR tint, float scalex, float scaley, int flags) {
if (character->dead) { return; }
int spritesheetX = al_get_bitmap_width(character->bitmap) * (character->pos % character->spritesheet->cols);
int spritesheetY = al_get_bitmap_height(character->bitmap) * (character->pos / character->spritesheet->cols);
al_draw_tinted_scaled_rotated_bitmap_region(character->spritesheet->bitmap, spritesheetX, spritesheetY, al_get_bitmap_width(character->bitmap), al_get_bitmap_height(character->bitmap), tint, al_get_bitmap_width(character->bitmap) * character->pivotX, al_get_bitmap_height(character->bitmap) * character->pivotY, (int)(GetCharacterX(game, character) + al_get_bitmap_width(character->bitmap) * scalex * character->pivotX), (int)(GetCharacterY(game, character) + al_get_bitmap_height(character->bitmap) * scaley * character->pivotY), scalex, scaley, character->angle, flags);
}
SYMBOL_EXPORT void DrawCharacter(struct Game* game, struct Character* character, ALLEGRO_COLOR tint, int flags) {
if (character->spritesheet->flip) {
flags = flags | ALLEGRO_FLIP_HORIZONTAL | ALLEGRO_FLIP_VERTICAL;
}
al_draw_bitmap(character->bitmap, GetCharacterX(game, character), GetCharacterY(game, character), flags);
// DrawScaledCharacter(game, character, tint, 1, 1, flags);
} }
SYMBOL_EXPORT void SetCharacterConfines(struct Game* game, struct Character* character, int x, int y) { SYMBOL_EXPORT void SetCharacterConfines(struct Game* game, struct Character* character, int x, int y) {
@ -285,27 +260,32 @@ SYMBOL_EXPORT int GetCharacterConfineY(struct Game* game, struct Character* char
return (character->confineY >= 0) ? character->confineY : game->viewport.height; return (character->confineY >= 0) ? character->confineY : game->viewport.height;
} }
SYMBOL_EXPORT int GetCharacterX(struct Game* game, struct Character* character) { SYMBOL_EXPORT float GetCharacterX(struct Game* game, struct Character* character) {
return character->x * GetCharacterConfineX(game, character); return character->x * GetCharacterConfineX(game, character);
} }
SYMBOL_EXPORT int GetCharacterY(struct Game* game, struct Character* character) { SYMBOL_EXPORT float GetCharacterY(struct Game* game, struct Character* character) {
return character->y * GetCharacterConfineY(game, character); return character->y * GetCharacterConfineY(game, character);
} }
SYMBOL_EXPORT float GetCharacterAngle(struct Game* game, struct Character* character) {
return character->angle;
}
SYMBOL_EXPORT bool IsOnCharacter(struct Game* game, struct Character* character, int x, int y, bool pixelperfect) { SYMBOL_EXPORT bool IsOnCharacter(struct Game* game, struct Character* character, int x, int y, bool pixelperfect) {
int x1 = GetCharacterX(game, character), y1 = GetCharacterY(game, character); int x1 = GetCharacterX(game, character), y1 = GetCharacterY(game, character);
int x2 = x1 + al_get_bitmap_width(character->bitmap), y2 = y1 + al_get_bitmap_height(character->bitmap); int w = al_get_bitmap_width(character->bitmap), h = al_get_bitmap_height(character->bitmap);
int x2 = x1 + w, y2 = y1 + h;
bool test = ((x >= x1) && (x <= x2) && (y >= y1) && (y <= y2)); bool test = ((x >= x1) && (x <= x2) && (y >= y1) && (y <= y2));
if (test && pixelperfect) { if (test && pixelperfect) {
// TODO: handle being flipped // TODO: handle scale and rotation
ALLEGRO_COLOR color = al_get_pixel(character->bitmap, x - x1, y - y1); x -= x1;
y -= y1;
if (character->flipX) {
x = w - x;
}
if (character->flipY) {
y = w - y;
}
ALLEGRO_COLOR color = al_get_pixel(character->bitmap, x, y);
return (color.a > 0.0); return (color.a > 0.0);
} }

View file

@ -29,46 +29,60 @@
struct Spritesheet { struct Spritesheet {
char* name; /*!< Name of the spritesheet (used in file paths). */ char* name; /*!< Name of the spritesheet (used in file paths). */
ALLEGRO_BITMAP* bitmap; /*!< Spritesheet bitmap. */ ALLEGRO_BITMAP* bitmap; /*!< Spritesheet bitmap. */
// TODO: bitmap file
int rows; /*!< Number of rows in the spritesheet. */ int rows; /*!< Number of rows in the spritesheet. */
int cols; /*!< Number of columns in the spritesheet. */ int cols; /*!< Number of columns in the spritesheet. */
int blanks; /*!< Number of blank frames at the end of the spritesheet. */ int blanks; /*!< Number of blank frames at the end of the spritesheet. */
int width; int width;
int height; int height;
int delay; int delay;
bool kill; int repeats; /*!< Number of repeats to make before the spritesheet is changed to its successor. */
int repeat;
bool flip;
float scale; /*!< Scale modifier of the frame. */
char* successor; /*!< Name of animation successor. If it's not blank, then animation will be played only once. */ char* successor; /*!< Name of animation successor. If it's not blank, then animation will be played only once. */
struct Spritesheet* next; /*!< Next spritesheet in the queue. */ struct Spritesheet* next; /*!< Next spritesheet in the queue. */
// TODO: loopmode
// TODO: playmode
// TODO: missing docs
}; };
/*! \brief Structure representing one visible character. */ /*! \brief Structure representing one visible character. */
struct Character { struct Character {
char* name; /*!< Name of the character (used in file paths). */ char* name; /*!< Name of the character (used in file paths). */
struct Character* parent; /*!< Parent character. NULL is no parent. */
ALLEGRO_BITMAP* bitmap; /*!< Subbitmap with character's current frame. */
struct Spritesheet* spritesheet; /*!< Current spritesheet used by character. */ struct Spritesheet* spritesheet; /*!< Current spritesheet used by character. */
struct Spritesheet* spritesheets; /*!< List of all spritesheets registered to character. */ struct Spritesheet* spritesheets; /*!< List of all spritesheets registered to character. */
char* successor;
ALLEGRO_BITMAP* bitmap;
int pos; /*!< Current spritesheet position. */ int pos; /*!< Current spritesheet position. */
int pos_tmp; /*!< A counter used to slow down spritesheet animation. */ int pos_tmp; /*!< A counter used internally to slow down spritesheet animation. */ // TODO: change to delta
char* successor; /*!< Name of the next spritesheet to be played when the current one finishes. */
float x; /*!< Horizontal position of character. */ float x; /*!< Horizontal position of character. */
float y; /*!< Vertical position of character. */ float y; /*!< Vertical position of character. */
float angle; /*!< Characters display angle (radians). */ ALLEGRO_COLOR tint; /*!< Color with which the character's pixels will be multiplied (tinted). White for no effect. */
float pivotX, pivotY; /*!< Pivot point, relative of character's size. */ float pivotX; /*!< Pivot point's X, for scaling and rotating, relative of character's size. */
int confineX, confineY; /*!< Size of the canvas being drawn to, for correct position calculation; when -1, uses viewport size */ float pivotY; /*!< Pivot point's Y, for scaling and rotating, relative of character's size. */
int repeat; // TODO: remove float scaleX; /*!< Scale factor for X axis. */
bool shared; float scaleY; /*!< Scale factor for Y axis. */
bool dead; // TODO: remove float angle; /*!< Character's rotation angle (radians). */
int confineX; /*!< Width of the canvas being drawn to, for correct position calculation; when -1, uses parent's confines or viewport size */
int confineY; /*!< Height of the canvas being drawn to, for correct position calculation; when -1, uses parent's confines or viewport size */
bool flipX; /*!< Flips the character's sprite vertically. */
bool flipY; /*!< Flips the character's sprite horizontally. */
bool shared; /*!< Marks the list of spritesheets as shared, so it won't be freed together with the character. */
int repeats; /*!< Number of repeats left before the spritesheet is changed to its successor. */
void* data; /*!< Additional, custom character data (HP etc.). */ void* data; /*!< Additional, custom character data (HP etc.). */
// TODO: add a callback for when the animation finishes
// TODO: playmode
// TODO: parents
}; };
// TODO: document functions
void SelectSpritesheet(struct Game* game, struct Character* character, char* name); void SelectSpritesheet(struct Game* game, struct Character* character, char* name);
void ChangeSpritesheet(struct Game* game, struct Character* character, char* name); void EnqueueSpritesheet(struct Game* game, struct Character* character, char* name);
void RegisterSpritesheet(struct Game* game, struct Character* character, char* name); void RegisterSpritesheet(struct Game* game, struct Character* character, char* name);
void DrawCharacterF(struct Game* game, struct Character* character, ALLEGRO_COLOR tint, int flags); void DrawCharacter(struct Game* game, struct Character* character);
void DrawCharacter(struct Game* game, struct Character* character, ALLEGRO_COLOR tint, int flags);
void DrawScaledCharacterF(struct Game* game, struct Character* character, ALLEGRO_COLOR tint, float scalex, float scaley, int flags); void DrawScaledCharacterF(struct Game* game, struct Character* character, ALLEGRO_COLOR tint, float scalex, float scaley, int flags);
void DrawScaledCharacter(struct Game* game, struct Character* character, ALLEGRO_COLOR tint, float scalex, float scaley, int flags); void DrawScaledCharacter(struct Game* game, struct Character* character, ALLEGRO_COLOR tint, float scalex, float scaley, int flags);
@ -78,7 +92,7 @@ void DestroyCharacter(struct Game* game, struct Character* character);
void LoadSpritesheets(struct Game* game, struct Character* character); void LoadSpritesheets(struct Game* game, struct Character* character);
void UnloadSpritesheets(struct Game* game, struct Character* character); void UnloadSpritesheets(struct Game* game, struct Character* character);
void AnimateCharacter(struct Game* game, struct Character* character, float speed_modifier); void AnimateCharacter(struct Game* game, struct Character* character, float delta, float speed_modifier);
void MoveCharacter(struct Game* game, struct Character* character, float x, float y, float angle); void MoveCharacter(struct Game* game, struct Character* character, float x, float y, float angle);
void MoveCharacterF(struct Game* game, struct Character* character, float x, float y, float angle); void MoveCharacterF(struct Game* game, struct Character* character, float x, float y, float angle);
void SetCharacterPosition(struct Game* game, struct Character* character, float x, float y, float angle); void SetCharacterPosition(struct Game* game, struct Character* character, float x, float y, float angle);
@ -86,9 +100,8 @@ void SetCharacterPositionF(struct Game* game, struct Character* character, float
void SetCharacterPivotPoint(struct Game* game, struct Character* character, float x, float y); void SetCharacterPivotPoint(struct Game* game, struct Character* character, float x, float y);
void SetCharacterConfines(struct Game* game, struct Character* character, int x, int y); void SetCharacterConfines(struct Game* game, struct Character* character, int x, int y);
int GetCharacterX(struct Game* game, struct Character* character); float GetCharacterX(struct Game* game, struct Character* character);
int GetCharacterY(struct Game* game, struct Character* character); float GetCharacterY(struct Game* game, struct Character* character);
float GetCharacterAngle(struct Game* game, struct Character* character);
int GetCharacterConfineX(struct Game* game, struct Character* character); int GetCharacterConfineX(struct Game* game, struct Character* character);
int GetCharacterConfineY(struct Game* game, struct Character* character); int GetCharacterConfineY(struct Game* game, struct Character* character);