diff --git a/engine/EC.h b/engine/EC.h index ca966e2..67a3b67 100644 --- a/engine/EC.h +++ b/engine/EC.h @@ -192,10 +192,25 @@ typedef struct Sprite { } Sprite_t; typedef unsigned int (*sprite_transition_func_t)(Entity_t *ent); // Transition requires knowledge of the entity + +typedef enum AnchorPoint { + AP_TOP_LEFT, + AP_TOP_CENTER, + AP_TOP_RIGHT, + AP_MID_LEFT, + AP_MID_CENTER, + AP_MID_RIGHT, + AP_BOT_LEFT, + AP_BOT_CENTER, + AP_BOT_RIGHT, +} AnchorPoint_t; + typedef struct _SpriteRenderInfo { Sprite_t* sprite; Vector2 offset; + Vector2 src_anchor; + AnchorPoint_t dest_anchor; } SpriteRenderInfo_t; typedef struct _CSprite_t { diff --git a/engine/assets.c b/engine/assets.c index a8eb624..53d148a 100644 --- a/engine/assets.c +++ b/engine/assets.c @@ -1,6 +1,7 @@ #include "assets.h" #include "assert.h" #include "engine_conf.h" +#include "raymath.h" #define RRES_RAYLIB_IMPLEMENTATION #include "rres.h" @@ -551,15 +552,20 @@ void draw_sprite_pro(Sprite_t* spr, int frame_num, Vector2 pos, float rotation, spr->frame_size.x * ((flip & 1) ? -1 : 1), spr->frame_size.y * ((flip & 2) ? -1 : 1), }; - Rectangle dest = { - .x = pos.x, - .y = pos.y, - .width = spr->frame_size.x * scale.x, - .height = spr->frame_size.y * scale.y - }; + + // The anchor here is only for rotation and scaling. + // Translational anchor is expected to be accounted for + // So need to offset render position with anchor position Vector2 anchor = spr->anchor; anchor.x *= scale.x; anchor.y *= scale.y; + + Rectangle dest = { + .x = pos.x + anchor.x, + .y = pos.y + anchor.y, + .width = spr->frame_size.x * scale.x, + .height = spr->frame_size.y * scale.y + }; DrawTexturePro( *spr->texture, rec, @@ -568,3 +574,54 @@ void draw_sprite_pro(Sprite_t* spr, int frame_num, Vector2 pos, float rotation, rotation, colour ); } + +Vector2 shift_bbox(Vector2 bbox, Vector2 new_bbox, AnchorPoint_t anchor) +{ + Vector2 p1 = get_anchor_offset(bbox, anchor); + Vector2 p2 = get_anchor_offset(new_bbox, anchor); + + return Vector2Subtract(p1, p2); +} + +Vector2 get_anchor_offset(Vector2 bbox, AnchorPoint_t anchor) +{ + Vector2 offset = {0}; + switch (anchor) + { + case AP_TOP_LEFT: + break; + case AP_TOP_CENTER: + offset.x = bbox.x / 2; + break; + case AP_TOP_RIGHT: + offset.x = bbox.x; + break; + case AP_MID_LEFT: + offset.x = 0; + offset.y = bbox.y / 2; + break; + case AP_MID_CENTER: + offset.x = bbox.x / 2; + offset.y = bbox.y / 2; + break; + case AP_MID_RIGHT: + offset.x = bbox.x; + offset.y = bbox.y / 2; + break; + case AP_BOT_LEFT: + offset.x = 0; + offset.y = bbox.y; + break; + case AP_BOT_CENTER: + offset.x = bbox.x / 2; + offset.y = bbox.y; + break; + case AP_BOT_RIGHT: + offset.x = bbox.x; + offset.y = bbox.y; + break; + } + return offset; +} + + diff --git a/engine/assets.h b/engine/assets.h index 3d30859..43e5459 100644 --- a/engine/assets.h +++ b/engine/assets.h @@ -83,6 +83,8 @@ LevelPack_t* get_level_pack(Assets_t* assets, const char* name); void draw_sprite(Sprite_t* spr, int frame_num, Vector2 pos, float rotation, bool flip_x); void draw_sprite_pro(Sprite_t* spr, int frame_num, Vector2 pos, float rotation, uint8_t flip, Vector2 scale, Color colour); +Vector2 get_anchor_offset(Vector2 bbox, AnchorPoint_t anchor); +Vector2 shift_bbox(Vector2 bbox, Vector2 new_bbox, AnchorPoint_t anchor); typedef struct SFX { diff --git a/scenes/editor_scene.c b/scenes/editor_scene.c index 9234f6f..7f9f401 100644 --- a/scenes/editor_scene.c +++ b/scenes/editor_scene.c @@ -220,6 +220,7 @@ static void render_editor_game_scene(Scene_t* scene) int y = tile_y * TILE_SIZE; + //if (!tilemap.tiles[i].moveable) //{ // // Draw water tile @@ -432,7 +433,17 @@ static void render_editor_game_scene(Scene_t* scene) const SpriteRenderInfo_t spr = p_cspr->sprites[p_cspr->current_idx]; if (spr.sprite != NULL) { - Vector2 pos = Vector2Add(p_ent->position, spr.offset); + Vector2 pos = p_ent->position; + if (p_bbox != NULL) + { + pos = Vector2Add( + pos, + get_anchor_offset(p_bbox->size, spr.dest_anchor) + ); + pos = Vector2Subtract(pos, spr.src_anchor); + } + + pos = Vector2Add(pos, spr.offset); draw_sprite(spr.sprite, p_cspr->current_frame, pos, 0.0f, p_cspr->flip_x); } } diff --git a/scenes/game_systems.c b/scenes/game_systems.c index 224f41d..32a14d3 100644 --- a/scenes/game_systems.c +++ b/scenes/game_systems.c @@ -12,17 +12,6 @@ bool check_in_water(const ParticleEmitter_t* emitter, float delta_time); static const Vector2 GRAVITY = {0, GRAV_ACCEL}; static const Vector2 UPTHRUST = {0, -GRAV_ACCEL * 1.1}; -typedef enum AnchorPoint { - AP_TOP_LEFT, - AP_TOP_CENTER, - AP_TOP_RIGHT, - AP_MID_LEFT, - AP_MID_CENTER, - AP_MID_RIGHT, - AP_BOT_LEFT, - AP_BOT_CENTER, - AP_BOT_RIGHT, -} AnchorPoint_t; static inline unsigned int get_tile_idx(int x, int y, TileGrid_t gridmap) { @@ -160,73 +149,6 @@ collision_end: return overlap_mode > 0; } -static Vector2 shift_bbox(Vector2 bbox, Vector2 new_bbox, AnchorPoint_t anchor) -{ - Vector2 p1; - Vector2 p2; - - Vector2 offset = {0}; - switch (anchor) - { - case AP_TOP_LEFT: - // When resizing bbox, it is implicitly assumed that to be already in topleft - // due to the coordindate system (+ve towards right and downwards) - // So do nothing - return offset; - case AP_TOP_CENTER: - p1.x = bbox.x / 2; - p1.y = 0; - p2.x = new_bbox.x / 2; - p2.y = 0; - break; - case AP_TOP_RIGHT: - p1.x = bbox.x; - p1.y = 0; - p2.x = new_bbox.x; - p2.y = 0; - break; - case AP_MID_LEFT: - p1.x = 0; - p1.y = bbox.y / 2; - p2.x = 0; - p2.y = new_bbox.y / 2; - break; - case AP_MID_CENTER: - p1.x = bbox.x / 2; - p1.y = bbox.y / 2; - p2.x = new_bbox.x / 2; - p2.y = new_bbox.y / 2; - break; - case AP_MID_RIGHT: - p1.x = bbox.x; - p1.y = bbox.y / 2; - p2.x = new_bbox.x; - p2.y = new_bbox.y / 2; - break; - case AP_BOT_LEFT: - p1.x = 0; - p1.y = bbox.y; - p2.x = 0; - p2.y = new_bbox.y; - break; - case AP_BOT_CENTER: - p1.x = bbox.x / 2; - p1.y = bbox.y; - p2.x = new_bbox.x / 2; - p2.y = new_bbox.y; - break; - case AP_BOT_RIGHT: - p1.x = bbox.x; - p1.y = bbox.y; - p2.x = new_bbox.x; - p2.y = new_bbox.y; - break; - } - offset.x = p1.x - p2.x; - offset.y = p1.y - p2.y; - return offset; -} - void destroy_entity(Scene_t* scene, TileGrid_t* tilemap, Entity_t* p_ent) { Vector2 half_size = {0,0}; diff --git a/scenes/player_ent.c b/scenes/player_ent.c index 7eb8632..4b4b964 100644 --- a/scenes/player_ent.c +++ b/scenes/player_ent.c @@ -172,8 +172,13 @@ static bool init_player_file(FILE* in_file, Assets_t* assets) return false; } Sprite_t* spr = get_sprite(assets, name); + spr->anchor = Vector2Scale(spr->frame_size, 0.5f); player_sprite_map[i].sprite = spr; - player_sprite_map[i].offset = offset; + //player_sprite_map[i].offset = offset; + player_sprite_map[i].offset = (Vector2){0}; + player_sprite_map[i].src_anchor = spr->frame_size; + player_sprite_map[i].src_anchor.x /= 2.0f; + player_sprite_map[i].dest_anchor = AP_BOT_CENTER; i++; } already_init = true;