WIP character rework from Rumina

This commit is contained in:
Sebastian Krzyszkowiak 2018-02-18 14:42:58 +01:00
parent 4ca0e94277
commit b86e168831
2 changed files with 120 additions and 83 deletions

View file

@ -22,6 +22,7 @@
#include "utils.h"
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_ttf.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
@ -43,15 +44,12 @@ SYMBOL_EXPORT void SelectSpritesheet(struct Game* game, struct Character* charac
} else {
character->successor = NULL;
}
character->repeat = tmp->repeat;
character->repeats = tmp->repeats;
character->pos = 0;
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);
} 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);
}
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));
return;
@ -61,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);
}
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) {
free(character->successor);
}
@ -111,20 +109,17 @@ SYMBOL_EXPORT void RegisterSpritesheet(struct Game* game, struct Character* char
s = malloc(sizeof(struct Spritesheet));
s->name = strdup(name);
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->cols = strtol(al_get_config_value(config, "", "cols"), NULL, 10);
s->blanks = strtol(al_get_config_value(config, "", "blanks"), NULL, 10);
s->delay = strtod(al_get_config_value(config, "", "delay"), NULL);
const char* val = al_get_config_value(config, "", "repeat");
s->width = 0;
s->height = 0;
const char* val = al_get_config_value(config, "", "repeats");
if (val) {
s->repeat = strtod(val, NULL);
s->repeats = strtod(val, NULL);
} else {
s->repeat = 0;
}
s->kill = false;
const char* kill = al_get_config_value(config, "", "kill");
if (kill) {
s->kill = strtol(kill, NULL, 10);
s->repeats = 0;
}
s->successor = NULL;
const char* successor = al_get_config_value(config, "", "successor");
@ -141,23 +136,29 @@ SYMBOL_EXPORT struct Character* CreateCharacter(struct Game* game, char* name) {
PrintConsole(game, "Creating character %s...", name);
struct Character* character = malloc(sizeof(struct Character));
character->name = strdup(name);
character->angle = 0;
character->bitmap = NULL;
character->data = NULL;
character->spritesheet = NULL;
character->spritesheets = NULL;
character->pos = 0;
character->pos_tmp = 0;
character->successor = NULL;
character->x = -1;
character->y = -1;
character->tint = al_map_rgb(255, 255, 255);
character->pivotX = 0.5;
character->pivotY = 0.5;
character->scaleX = 1.0;
character->scaleY = 1.0;
character->angle = 0;
character->confineX = -1;
character->confineY = -1;
character->spritesheets = NULL;
character->spritesheet = NULL;
character->successor = NULL;
character->repeat = 0;
character->flipX = false;
character->flipY = false;
character->shared = false;
character->dead = false;
character->repeats = 0;
character->parent = NULL;
character->data = NULL;
return character;
}
@ -189,8 +190,8 @@ SYMBOL_EXPORT void DestroyCharacter(struct Game* game, struct Character* charact
free(character);
}
SYMBOL_EXPORT void AnimateCharacter(struct Game* game, struct Character* character, float speed_modifier) {
if (character->dead) { return; }
SYMBOL_EXPORT void AnimateCharacter(struct Game* game, struct Character* character, float delta, float speed_modifier) {
speed_modifier *= delta / (1 / 60.f); // TODO: proper delta handling
if (speed_modifier) {
character->pos_tmp++;
if (character->pos_tmp >= character->spritesheet->delay / speed_modifier) {
@ -199,16 +200,16 @@ SYMBOL_EXPORT void AnimateCharacter(struct Game* game, struct Character* charact
}
if (character->pos >= character->spritesheet->cols * character->spritesheet->rows - character->spritesheet->blanks) {
character->pos = 0;
if (character->repeat) {
character->repeat--;
} else {
if (character->spritesheet->kill) {
character->dead = true;
} else if (character->successor) {
SelectSpritesheet(game, character, character->successor);
}
if (character->repeats) {
character->repeats--;
} else if (character->successor) {
SelectSpritesheet(game, character, character->successor);
}
}
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->spritesheet->width / character->spritesheet->cols, character->spritesheet->height / character->spritesheet->rows);
}
}
@ -217,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) {
if (character->dead) { return; }
character->x += x;
character->y += y;
character->angle += 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->y = y;
character->angle = angle;
@ -239,26 +238,14 @@ SYMBOL_EXPORT void SetCharacterPivotPoint(struct Game* game, struct Character* c
character->pivotY = y;
}
SYMBOL_EXPORT void DrawScaledCharacterF(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, 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);
}
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) {
DrawScaledCharacter(game, character, tint, 1, 1, flags);
// TODO: coords are centered (pivot-related) or top left?
SYMBOL_EXPORT void DrawCharacter(struct Game* game, struct Character* character) {
int w = al_get_bitmap_width(character->bitmap), h = al_get_bitmap_height(character->bitmap);
al_draw_tinted_scaled_rotated_bitmap(character->bitmap, character->tint,
w * character->pivotX, h * character->pivotY,
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 SetCharacterConfines(struct Game* game, struct Character* character, int x, int y) {
@ -274,21 +261,57 @@ SYMBOL_EXPORT int GetCharacterConfineY(struct Game* game, struct Character* char
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);
}
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);
}
SYMBOL_EXPORT float GetCharacterAngle(struct Game* game, struct Character* character) {
return character->angle;
static void SortTwoFloats(float* v1, float* v2) {
float pom = *v1;
if (v1 > v2) {
*v1 = *v2;
*v2 = pom;
}
}
SYMBOL_EXPORT bool IsOnCharacter(struct Game* game, struct Character* character, int x, int y) {
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);
SYMBOL_EXPORT bool IsOnCharacter(struct Game* game, struct Character* character, float x, float y, bool pixelperfect) {
// TODO: fucking rework
return ((x >= x1) && (x <= x2) && (y >= y1) && (y <= y2));
int w = al_get_bitmap_width(character->bitmap), h = al_get_bitmap_height(character->bitmap);
float x1 = GetCharacterX(game, character), y1 = GetCharacterY(game, character);
float x2 = x1 + w, y2 = y1 + h;
/* float scalex = character->scaleX;
float scaley = character->scaleY;
if (character->flipX) {
scalex *= -1;
}
if (character->flipY) {
scaley *= -1;
}
ALLEGRO_TRANSFORM transform;
al_identity_transform(&transform);
al_translate_transform(&transform, -character->pivotX * w, -character->pivotY * h);
al_scale_transform(&transform, scalex, scaley);
al_translate_transform(&transform, character->pivotX * w, character->pivotY * h);
al_transform_coordinates(&transform, &x1, &y1);
al_transform_coordinates(&transform, &x2, &y2);
SortTwoFloats(&x1, &x2);
SortTwoFloats(&y1, &y2);
*/
bool test = ((x >= x1) && (x <= x2) && (y >= y1) && (y <= y2));
//al_transform_coordinates(&transform, &x, &y);
if (test && pixelperfect) {
x -= x1;
y -= y1;
ALLEGRO_COLOR color = al_get_pixel(character->bitmap, x, y);
return (color.a > 0.0);
}
return test;
}

View file

@ -29,45 +29,60 @@
struct Spritesheet {
char* name; /*!< Name of the spritesheet (used in file paths). */
ALLEGRO_BITMAP* bitmap; /*!< Spritesheet bitmap. */
// TODO: bitmap file
int rows; /*!< Number of rows in the spritesheet. */
int cols; /*!< Number of columns in the spritesheet. */
int blanks; /*!< Number of blank frames at the end of the spritesheet. */
int width;
int height;
int delay;
bool kill;
int repeat;
float scale; /*!< Scale modifier of the frame. */
int repeats; /*!< Number of repeats to make before the spritesheet is changed to its successor. */
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. */
// TODO: loopmode
// TODO: playmode
// TODO: missing docs
};
/*! \brief Structure representing one visible character. */
struct Character {
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* spritesheets; /*!< List of all spritesheets registered to character. */
char* successor;
ALLEGRO_BITMAP* bitmap;
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 y; /*!< Vertical position of character. */
float angle; /*!< Characters display angle (radians). */
float pivotX, pivotY; /*!< Pivot point, relative of character's size. */
int confineX, confineY; /*!< Size of the canvas being drawn to, for correct position calculation; when -1, uses viewport size */
ALLEGRO_COLOR tint; /*!< Color with which the character's pixels will be multiplied (tinted). White for no effect. */
float pivotX; /*!< Pivot point's X, for scaling and rotating, relative of character's size. */
float pivotY; /*!< Pivot point's Y, for scaling and rotating, relative of character's size. */
float scaleX; /*!< Scale factor for X axis. */
float scaleY; /*!< Scale factor for Y axis. */
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.). */
int repeat;
bool shared;
bool dead;
// 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 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 DrawCharacterF(struct Game* game, struct Character* character, ALLEGRO_COLOR tint, int flags);
void DrawCharacter(struct Game* game, struct Character* character, ALLEGRO_COLOR tint, int flags);
void DrawCharacter(struct Game* game, struct Character* character);
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);
@ -77,7 +92,7 @@ void DestroyCharacter(struct Game* game, struct Character* character);
void LoadSpritesheets(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 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);
@ -85,12 +100,11 @@ void SetCharacterPositionF(struct Game* game, struct Character* character, float
void SetCharacterPivotPoint(struct Game* game, struct Character* character, float x, float y);
void SetCharacterConfines(struct Game* game, struct Character* character, int x, int y);
int GetCharacterX(struct Game* game, struct Character* character);
int GetCharacterY(struct Game* game, struct Character* character);
float GetCharacterAngle(struct Game* game, struct Character* character);
float GetCharacterX(struct Game* game, struct Character* character);
float GetCharacterY(struct Game* game, struct Character* character);
int GetCharacterConfineX(struct Game* game, struct Character* character);
int GetCharacterConfineY(struct Game* game, struct Character* character);
bool IsOnCharacter(struct Game* game, struct Character* character, int x, int y);
bool IsOnCharacter(struct Game* game, struct Character* character, float x, float y, bool pixelperfect);
#endif