Fix hitboxes for entities

This commit is contained in:
2024-01-28 14:09:27 +01:00
parent a61768e912
commit 5d96a02284
11 changed files with 67 additions and 49 deletions

View File

@@ -28,7 +28,7 @@ bool canPlaceBuilding(Game *game, BuildingType type, BzTile tileX, BzTile tileY)
BzSpatialGridIter it = bzSpatialGridIter(game->entityGrid, buildArea.x, buildArea.y, buildArea.width, buildArea.height);
while (bzSpatialGridQueryNext(&it)) { ecs_entity_t entity = *(ecs_entity_t *) it.data;
Rectangle bounds;
if (!getEntityHitBox(entity, NULL, &bounds)) continue;
if (!entityGetHitBox(entity, NULL, &bounds)) continue;
if (CheckCollisionRecs(buildArea, bounds))
return false;
@@ -62,6 +62,7 @@ ecs_entity_t placeBuilding(Game *game, BuildingType type,
.x = sizeX * tileWidth,
.y = sizeY * tileHeight,
};
pos.y += size.y;
HitBox hitbox = {
.x = 0.0f, .y = 0.0f,
.width = size.x,
@@ -73,8 +74,9 @@ ecs_entity_t placeBuilding(Game *game, BuildingType type,
ecs_set_ptr(ECS, building, HitBox, &hitbox);
ecs_set(ECS, building, Rotation, {0});
HitBox tHitBox = entityTransformHitBox(pos, hitbox);
SpatialGridID gridID = bzSpatialGridInsert(game->entityGrid, &building,
pos.x, pos.y, hitbox.width, hitbox.height);
tHitBox.x, tHitBox.y, tHitBox.width, tHitBox.height);
ecs_set_ptr(ECS, building, SpatialGridID, &gridID);
ecs_set(ECS, building, Owner, {player});
BzTileset *tileset = &game->tileset;

View File

@@ -8,7 +8,7 @@ ecs_entity_t entityCreateEmpty() {
return e;
}
ecs_entity_t entityCreateBaseUnit(const Position position, Player player,
ecs_entity_t entityCreateBaseUnit(const Position position, f32 size, Player player,
EntityType type, AnimType startAnim, Game *game) {
BzTileset *tileset = &game->tileset;
BzTileID tileID = getEntityTile(type);
@@ -19,7 +19,13 @@ ecs_entity_t entityCreateBaseUnit(const Position position, Player player,
HitBox hitbox = getEntityHitBoxRec(tileID);
ecs_entity_t e = entityCreateEmpty();
ecs_set_ptr(ECS, e, Position, &position);
//ecs_set_ptr(ECS, e, HitBox, &hitbox);
f32 scl = size / region.rec.width;
ecs_set(ECS, e, Size, {region.rec.width * scl, region.rec.height * scl});
hitbox.x *= scl;
hitbox.y *= scl;
hitbox.width *= scl;
hitbox.height *= scl;
ecs_set_ptr(ECS, e, HitBox, &hitbox);
BzSpatialGridID spatialID = bzSpatialGridInsert(game->entityGrid, &e,
position.x + hitbox.x, position.y + hitbox.y,
hitbox.width, hitbox.height);
@@ -60,13 +66,13 @@ ecs_entity_t entityCreateBaseUnit(const Position position, Player player,
}
ecs_entity_t entityCreateSoldier(const Position position, Player player, Game *game) {
ecs_entity_t e = entityCreateBaseUnit(position, player, ENTITY_SOLDIER, ANIM_IDLE, game);
ecs_entity_t e = entityCreateBaseUnit(position, 10.0f, player, ENTITY_SOLDIER, ANIM_IDLE, game);
return e;
}
ecs_entity_t entityCreateWorker(const Position position, Player player, Game *game) {
BzTileset *tileset = &game->tileset;
ecs_entity_t e = entityCreateBaseUnit(position, player, ENTITY_WORKER, ANIM_IDLE, game);
ecs_entity_t e = entityCreateBaseUnit(position, 10.0f, player, ENTITY_WORKER, ANIM_IDLE, game);
ecs_set(ECS, e, Worker, {
.collectSpeed = 0.8f,

View File

@@ -6,7 +6,7 @@
ecs_entity_t entityCreateEmpty();
ecs_entity_t entityCreateBaseUnit(const Position position, Player player,
ecs_entity_t entityCreateBaseUnit(const Position position, f32 size, Player player,
EntityType type, AnimType startAnim, Game *game);
ecs_entity_t entityCreateSoldier(const Position position, Player player, Game *game);
ecs_entity_t entityCreateWorker(const Position position, Player player, Game *game);

View File

@@ -1717,23 +1717,23 @@ static bool hasEntityHitBoxRec(BzTile tile) {
static Rectangle getEntityHitBoxRec(BzTile tile) {
switch (tile) {
case 27: return (Rectangle) {4, 2, 8, 12};
case 539: return (Rectangle) {4, 0, 8, 14};
case 1051: return (Rectangle) {4, 0, 8, 14};
case 1563: return (Rectangle) {4, 0, 8, 14};
case 2075: return (Rectangle) {4, 1, 8, 13};
case 2587: return (Rectangle) {4, 3, 8, 11};
case 5888: return (Rectangle) {4, 4, 8, 9};
case 5889: return (Rectangle) {3, 7, 10, 7};
case 5890: return (Rectangle) {6, 4, 4, 10};
case 5891: return (Rectangle) {6, 4, 4, 10};
case 6146: return (Rectangle) {6, 4, 4, 10};
case 6147: return (Rectangle) {6, 4, 4, 10};
case 6402: return (Rectangle) {6, 4, 4, 10};
case 6403: return (Rectangle) {6, 4, 4, 10};
case 6656: return (Rectangle) {6, 4, 4, 10};
case 6912: return (Rectangle) {6, 4, 4, 10};
case 539: return (Rectangle) {4, 2, 8, 14};
case 1051: return (Rectangle) {4, 2, 8, 14};
case 1563: return (Rectangle) {4, 2, 8, 14};
case 2075: return (Rectangle) {4, 2, 8, 13};
case 2587: return (Rectangle) {4, 2, 8, 11};
case 5888: return (Rectangle) {4, 3, 8, 9};
case 5889: return (Rectangle) {3, 2, 10, 7};
case 5890: return (Rectangle) {6, 2, 4, 10};
case 5891: return (Rectangle) {6, 2, 4, 10};
case 6146: return (Rectangle) {6, 2, 4, 10};
case 6147: return (Rectangle) {6, 2, 4, 10};
case 6402: return (Rectangle) {6, 2, 4, 10};
case 6403: return (Rectangle) {6, 2, 4, 10};
case 6656: return (Rectangle) {6, 2, 4, 10};
case 6912: return (Rectangle) {6, 2, 4, 10};
case 7170: return (Rectangle) {3, 3, 10, 10};
case 7171: return (Rectangle) {3, 4, 10, 9};
case 7171: return (Rectangle) {3, 3, 10, 9};
case 7172: return (Rectangle) {1, 3, 14, 10};
default: return (Rectangle) { 0.0f, 0.0f, 0.0f, 0.0f};
}

View File

@@ -386,10 +386,10 @@ static void renderGame(Game *game, float dt) {
Rotation *r = ecs_field(&it, Rotation, 3);
TextureRegion *t = ecs_field(&it, TextureRegion, 4);
for (i32 i = 0; i < it.count; i++) {
f32 sclX = s[i].x / t[i].rec.width;
f32 sclY = s[i].y / t[i].rec.height;
Rectangle dst = {p[i].x, p[i].y,
t[i].rec.width * sclX, t[i].rec.height * sclY};
Rectangle dst = {p[i].x, p[i].y - s[i].y,
s[i].x, s[i].y};
DrawCircleV(p[i], 1.0f, BLUE);
Vector2 origin = {0.0f, 0.0f};
//dst.x += origin.x - dst.width * 0.5f;
//dst.y += origin.y - dst.height * 0.5f;

View File

@@ -8,6 +8,7 @@
#include "game_state.h"
#include "map_layers.h"
#include "utils.h"
#include "systems/systems.h"
bool initGameObjectsLayer(BzTileMap *map, BzTileObjectGroup *objectGroup) {
Game *game = ecs_singleton_get_mut(ECS, Game);
@@ -163,10 +164,12 @@ bool initTreesLayer(BzTileMap *map, BzTileLayer *layer) {
f32 sizeY = tileset->tileHeight;
f32 posX = layer->offsetX + x * sizeX;
f32 posY = layer->offsetY + y * sizeY;
posY += sizeY;
ecs_entity_t e = entityCreateEmpty();
HitBox tHitBox = entityTransformHitBox((Position) {posX, posY}, hb);
SpatialGridID gridID = bzSpatialGridInsert(game->entityGrid, &e,
posX + hb.x, posY + hb.y,
hb.width, hb.height);
tHitBox.x, tHitBox.y,
tHitBox.width, tHitBox.height);
ecs_set(ECS, e, SpatialGridID, {gridID});
ecs_set(ECS, e, Position, {posX, posY});
ecs_set(ECS, e, Size, {sizeX, sizeY});

View File

@@ -101,12 +101,8 @@ void entityUpdateSpatialID(ecs_iter_t *it) {
BZ_UNUSED(velocity);
for (i32 i = 0; i < it->count; i++) {
Rectangle rec = {
position[i].x + hitbox[i].x,
position[i].y + hitbox[i].y,
hitbox[i].width, hitbox[i].height
};
bzSpatialGridUpdate(game->entityGrid, id[i], rec.x, rec.y, rec.width, rec.height);
HitBox hb = entityTransformHitBox(position[i], hitbox[i]);
bzSpatialGridUpdate(game->entityGrid, id[i], hb.x, hb.y, hb.width, hb.height);
}
}
@@ -227,9 +223,7 @@ void renderColliders(ecs_iter_t *it) {
HitBox *hitbox = ecs_field(it, HitBox , 2);
for (i32 i = 0; i < it->count; i++) {
HitBox hb = hitbox[i];
hb.x += pos[i].x;
hb.y += pos[i].y;
HitBox hb = entityTransformHitBox(pos[i], hitbox[i]);
DrawRectangleLinesEx(hb, 1.0f, RED);
}
}

View File

@@ -309,22 +309,19 @@ void drawPlayerInputUIGround() {
for (i32 i = 0; i < it.count; i++) {
ecs_entity_t entity = it.entities[i];
f32 radius = BZ_MAX(hitbox[i].width, hitbox[i].height);
Position center = entityGetCenter(pos[i], hitbox[i]);
radius *= 0.8f;
const f32 lineThickness = 1.0f;
if (ecs_has(ECS, entity, Building)) {
const f32 padding = 2.0f;
Rectangle bounds = {
pos[i].x + hitbox[i].x - padding,
pos[i].y - hitbox[i].y - padding,
pos[i].y - hitbox[i].height - padding,
hitbox[i].width + padding * 2,
hitbox[i].height + padding * 2,
};
DrawRectangleLinesEx(bounds, lineThickness, GREEN);
} else {
Position center = {
pos[i].x + hitbox[i].x + hitbox[i].width * 0.5f,
pos[i].y + hitbox[i].y + hitbox[i].height * 0.5f,
};
DrawRing(center, radius, radius + lineThickness, 0, 360, 12, GREEN);
}
}
@@ -372,7 +369,7 @@ ecs_entity_t queryEntity(BzSpatialGrid *entityGrid, Vector2 point, ecs_entity_t
if (!ecs_has_id(ECS, entity, tag)) continue;
Vector2 pos;
Rectangle hitbox;
if (!getEntityHitBox(entity, &pos, &hitbox)) continue;
if (!entityGetHitBox(entity, &pos, &hitbox)) continue;
if (!CheckCollisionPointRec(point, hitbox)) continue;
@@ -410,7 +407,7 @@ void selectUnits(BzSpatialGrid *entityGrid, Rectangle area, Player player) {
}
if (!ecs_has_id(ECS, entity, ecs_id(Unit))) continue;
Rectangle hitbox;
if (!getEntityHitBox(entity, NULL, &hitbox)) continue;
if (!entityGetHitBox(entity, NULL, &hitbox)) continue;
if (!CheckCollisionRecs(area, hitbox)) continue;
ecs_add(ECS, entity, Selected);

View File

@@ -2,7 +2,7 @@
#include "../game_state.h"
bool getEntityHitBox(ecs_entity_t entity, Position *outPos, Rectangle *outHitBox) {
bool entityGetHitBox(ecs_entity_t entity, Position *outPos, Rectangle *outHitBox) {
if (!ecs_is_alive(ECS, entity))
return false;
@@ -18,11 +18,25 @@ bool getEntityHitBox(ecs_entity_t entity, Position *outPos, Rectangle *outHitBox
if (outHitBox) {
*outHitBox = *hitbox;
outHitBox->x += pos->x;
outHitBox->y += pos->y;
outHitBox->y = pos->y - hitbox->y - hitbox->height;
}
return true;
}
Rectangle entityTransformHitBox(Position position, HitBox hitBox) {
return (Rectangle) {
position.x + hitBox.x,
position.y - hitBox.y - hitBox.height,
hitBox.width,
hitBox.height
};
}
Vector2 entityGetCenter(Position position, HitBox hitBox) {
return (Vector2) {
position.x + hitBox.x + hitBox.width * 0.5f,
position.y - hitBox.y - hitBox.height * 0.5f
};
}
ecs_entity_t renderCollidersSystem;
ecs_entity_t renderOrientDirSystem;

View File

@@ -199,7 +199,9 @@ void drawSettingsUI(Game *game, f32 dt);
* Utils
**********************************/
bool getEntityHitBox(ecs_entity_t entity, Position *outPos, Rectangle *outHitBox);
bool entityGetHitBox(ecs_entity_t entity, Position *outPos, Rectangle *outHitBox);
Rectangle entityTransformHitBox(Position position, HitBox hitBox);
Vector2 entityGetCenter(Position position, HitBox hitBox);
/**********************************
* MISC

View File

@@ -106,7 +106,7 @@ tile_writer.output_index_tile_offset("getTileOffset", "player", 256, TILE_WIDTH,
vec2_transform = ["Vector2", "(Vector2) {0.0f, 0.0f}",
lambda x: f"(Vector2) {{{x['x']}, {x['y']}}}"]
rec_transform = ["Rectangle", "(Rectangle) { 0.0f, 0.0f, 0.0f, 0.0f}",
lambda x: f"(Rectangle) {{{x['x']}, {x['y']}, {x['width']}, {x['height']}}}"]
lambda x: f"(Rectangle) {{{x['x']}, {TILE_HEIGHT - x['y'] - x['height']}, {x['width']}, {x['height']}}}"]
tile_writer.output_has_object("hasItemHandlePoint", "handle")
tile_writer.output_get_object("getItemHandlePoint", "handle", *vec2_transform)