character: rework IsOnCharacter to work properly regardless of pivot, rotation and scale

This commit is contained in:
Sebastian Krzyszkowiak 2018-06-04 19:10:29 +02:00
parent 291e4c73d6
commit 81488f9390
2 changed files with 27 additions and 53 deletions

View file

@ -455,32 +455,35 @@ SYMBOL_EXPORT void SetCharacterPosition(struct Game* game, struct Character* cha
SetCharacterPositionF(game, character, x / (float)GetCharacterConfineX(game, character), y / (float)GetCharacterConfineY(game, character), angle); SetCharacterPositionF(game, character, x / (float)GetCharacterConfineX(game, character), y / (float)GetCharacterConfineY(game, character), angle);
} }
SYMBOL_EXPORT ALLEGRO_TRANSFORM GetCharacterTransform(struct Game* game, struct Character* character) {
ALLEGRO_TRANSFORM transform;
int w = character->spritesheet->width, h = character->spritesheet->height;
al_identity_transform(&transform);
al_translate_transform(&transform, -w / 2, -h / 2);
al_scale_transform(&transform, ((character->flipX ^ character->spritesheet->flipX ^ character->frame->flipX) ? -1 : 1), ((character->flipY ^ character->spritesheet->flipY ^ character->frame->flipY) ? -1 : 1)); // flipping; FIXME: should it be here or later?
al_translate_transform(&transform, w / 2, h / 2);
al_translate_transform(&transform, character->spritesheet->frames[character->pos].x, character->spritesheet->frames[character->pos].y); // spritesheet frame offset
al_translate_transform(&transform, -w * character->spritesheet->pivotX, -h * character->spritesheet->pivotY); // pivot
al_scale_transform(&transform, character->scaleX, character->scaleY);
al_rotate_transform(&transform, character->angle);
al_translate_transform(&transform, GetCharacterX(game, character), GetCharacterY(game, character)); // position
return transform;
}
SYMBOL_EXPORT void DrawCharacter(struct Game* game, struct Character* character) { SYMBOL_EXPORT void DrawCharacter(struct Game* game, struct Character* character) {
if (character->hidden) { if (character->hidden) {
return; return;
} }
int w = character->spritesheet->width, h = character->spritesheet->height;
ALLEGRO_TRANSFORM current = *al_get_current_transform(); ALLEGRO_TRANSFORM current = *al_get_current_transform();
// TODO: move to function, use in IsOnCharacter etc.
al_identity_transform(&character->transform);
al_translate_transform(&character->transform, -w / 2, -h / 2);
al_scale_transform(&character->transform, ((character->flipX ^ character->spritesheet->flipX ^ character->frame->flipX) ? -1 : 1), ((character->flipY ^ character->spritesheet->flipY ^ character->frame->flipY) ? -1 : 1)); // flipping; FIXME: should it be here or later?
al_translate_transform(&character->transform, w / 2, h / 2);
al_translate_transform(&character->transform, character->spritesheet->frames[character->pos].x, character->spritesheet->frames[character->pos].y); // spritesheet frame offset ALLEGRO_TRANSFORM transform = GetCharacterTransform(game, character);
al_translate_transform(&character->transform, -w * character->spritesheet->pivotX, -h * character->spritesheet->pivotY); // pivot
al_scale_transform(&character->transform, character->scaleX, character->scaleY);
al_rotate_transform(&character->transform, character->angle);
al_translate_transform(&character->transform, GetCharacterX(game, character), GetCharacterY(game, character)); // position
ALLEGRO_TRANSFORM transform;
al_identity_transform(&transform);
al_compose_transform(&transform, &character->transform);
al_compose_transform(&transform, &current); al_compose_transform(&transform, &current);
al_use_transform(&transform); al_use_transform(&transform);
al_draw_tinted_bitmap(character->frame->bitmap, character->tint, 0, 0, 0); al_draw_tinted_bitmap(character->frame->bitmap, character->tint, 0, 0, 0);
/* al_hold_bitmap_drawing(false); /* al_hold_bitmap_drawing(false);
al_draw_filled_rectangle(character->spritesheet->width * character->spritesheet->pivotX - 5, al_draw_filled_rectangle(character->spritesheet->width * character->spritesheet->pivotX - 5,
character->spritesheet->height * character->spritesheet->pivotY - 5, character->spritesheet->height * character->spritesheet->pivotY - 5,
@ -512,63 +515,33 @@ SYMBOL_EXPORT float GetCharacterY(struct Game* game, struct Character* character
return character->y * GetCharacterConfineY(game, character); return character->y * GetCharacterConfineY(game, character);
} }
/*
static void SortTwoFloats(float* v1, float* v2) { static void SortTwoFloats(float* v1, float* v2) {
float pom = *v1; float pom = *v1;
if (v1 > v2) { if (*v1 > *v2) {
*v1 = *v2; *v1 = *v2;
*v2 = pom; *v2 = pom;
} }
} }
*/
SYMBOL_EXPORT bool IsOnCharacter(struct Game* game, struct Character* character, float x, float y, bool pixelperfect) { SYMBOL_EXPORT bool IsOnCharacter(struct Game* game, struct Character* character, float x, float y, bool pixelperfect) {
// TODO: fucking rework
if (character->hidden) { if (character->hidden) {
return false; return false;
} }
int w = character->spritesheet->width, h = character->spritesheet->height; float x1 = 0.0, y1 = 0.0;
float x2 = character->spritesheet->width, y2 = character->spritesheet->height;
//float x1 = GetCharacterX(game, character), y1 = GetCharacterY(game, character); ALLEGRO_TRANSFORM transform = GetCharacterTransform(game, character);
//x -= GetCharacterX(game, character);
//y -= GetCharacterY(game, character);
float x1 = GetCharacterX(game, character) - (w / 2) * fabs(character->scaleX), y1 = GetCharacterY(game, character) - (h / 2) * fabs(character->scaleY);
float x2 = x1 + w * fabs(character->scaleX), y2 = y1 + h * fabs(character->scaleY);
//PrintConsole(game, "character %s x %f y %f; %fx%f; %fx%f -> %fx%f", character->name, x, y, character->scaleX, character->scaleY, x1, y1, x2, y2);
/* 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, &x1, &y1);
al_transform_coordinates(&transform, &x2, &y2); al_transform_coordinates(&transform, &x2, &y2);
SortTwoFloats(&x1, &x2); SortTwoFloats(&x1, &x2);
SortTwoFloats(&y1, &y2); SortTwoFloats(&y1, &y2);
*/
bool test = ((x >= x1) && (x <= x2) && (y >= y1) && (y <= y2)); bool test = ((x >= x1) && (x <= x2) && (y >= y1) && (y <= y2));
//al_transform_coordinates(&transform, &x, &y);
if (test && pixelperfect) { if (test && pixelperfect) {
x -= x1; al_invert_transform(&transform);
y -= y1; al_transform_coordinates(&transform, &x, &y);
x /= fabs(character->scaleX);
y /= fabs(character->scaleY);
if (character->flipX) {
x = w - x;
}
if (character->flipY) {
y = h - y;
}
ALLEGRO_COLOR color = al_get_pixel(character->frame->bitmap, x, y); ALLEGRO_COLOR color = al_get_pixel(character->frame->bitmap, x, y);
return (color.a > 0.0); return (color.a > 0.0);
} }

View file

@ -97,7 +97,6 @@ struct Character {
void (*callback)(struct Game*, struct Character*, struct Spritesheet* newAnim, struct Spritesheet* oldAnim, void*); void (*callback)(struct Game*, struct Character*, struct Spritesheet* newAnim, struct Spritesheet* oldAnim, void*);
void* callbackData; void* callbackData;
bool shared; /*!< Marks the list of spritesheets as shared, so it won't be freed together with the character. */ bool shared; /*!< Marks the list of spritesheets as shared, so it won't be freed together with the character. */
ALLEGRO_TRANSFORM transform;
// TODO: parents // TODO: parents
}; };
@ -110,6 +109,8 @@ void EnqueueSpritesheet(struct Game* game, struct Character* character, char* na
void RegisterSpritesheet(struct Game* game, struct Character* character, char* name); void RegisterSpritesheet(struct Game* game, struct Character* character, char* name);
struct Spritesheet* GetSpritesheet(struct Game* game, struct Character* character, char* name); struct Spritesheet* GetSpritesheet(struct Game* game, struct Character* character, char* name);
ALLEGRO_TRANSFORM GetCharacterTransform(struct Game* game, struct Character* character);
void DrawCharacter(struct Game* game, struct Character* character); 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 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);