Add weapons

This commit is contained in:
2024-01-06 19:54:22 +01:00
parent dbc0ce5981
commit f667614cfe
398 changed files with 1209 additions and 66 deletions

View File

@@ -16,6 +16,7 @@ ECS_COMPONENT_DECLARE(Position);
ECS_COMPONENT_DECLARE(Size);
ECS_COMPONENT_DECLARE(Velocity);
ECS_COMPONENT_DECLARE(Rotation);
ECS_COMPONENT_DECLARE(Orientation);
ECS_COMPONENT_DECLARE(Steering);
ECS_COMPONENT_DECLARE(TargetPosition);
ECS_COMPONENT_DECLARE(Path);
@@ -25,6 +26,8 @@ ECS_COMPONENT_DECLARE(TextureRegion);
ECS_COMPONENT_DECLARE(Animation);
ECS_COMPONENT_DECLARE(Easing);
ECS_COMPONENT_DECLARE(Arms);
ECS_COMPONENT_DECLARE(Arm);
ECS_COMPONENT_DECLARE(UnitAI);
ECS_COMPONENT_DECLARE(UnitAction);
@@ -53,6 +56,7 @@ void initComponentIDs(ecs_world_t *ecs) {
ECS_COMPONENT_DEFINE(ecs, Size);
ECS_COMPONENT_DEFINE(ecs, Velocity);
ECS_COMPONENT_DEFINE(ecs, Rotation);
ECS_COMPONENT_DEFINE(ecs, Orientation);
ECS_COMPONENT_DEFINE(ecs, Steering);
ECS_COMPONENT_DEFINE(ecs, TargetPosition);
ECS_COMPONENT_DEFINE(ecs, Path);
@@ -62,6 +66,8 @@ void initComponentIDs(ecs_world_t *ecs) {
ECS_COMPONENT_DEFINE(ecs, Animation);
ECS_COMPONENT_DEFINE(ecs, Easing);
ECS_COMPONENT_DEFINE(ecs, Arms);
ECS_COMPONENT_DEFINE(ecs, Arm);
ECS_COMPONENT_DEFINE(ecs, UnitAI);
ECS_COMPONENT_DEFINE(ecs, UnitAction);

View File

@@ -60,12 +60,13 @@ typedef BzSpatialGridID SpatialGridID;
extern ECS_COMPONENT_DECLARE(SpatialGridID);
typedef Vector2 Position, Size, Velocity, TargetPosition, Steering;
typedef f32 Rotation;
typedef f32 Rotation, Orientation;
extern ECS_COMPONENT_DECLARE(Position);
extern ECS_COMPONENT_DECLARE(Size);
extern ECS_COMPONENT_DECLARE(Velocity);
extern ECS_COMPONENT_DECLARE(Rotation);
extern ECS_COMPONENT_DECLARE(Orientation);
extern ECS_COMPONENT_DECLARE(Steering);
extern ECS_COMPONENT_DECLARE(TargetPosition);
@@ -152,20 +153,31 @@ typedef struct EntityArms {
* Gameplay components
*********************************************************/
typedef Vector2 ItemOffset;
typedef struct WeaponMelee {
ecs_entity_t weapon;
f32 reach;
f32 damage;
f32 speed;
} WeaponMelee;
typedef struct WeaponRanged {
ecs_entity_t weapon;
int32_t ammo;
} WeaponRanged;
typedef struct WeaponShield {
ecs_entity_t weapon;
} WeaponShield;
typedef struct AttachedWeapons {
typedef struct Arms {
ecs_entity_t primary;
ecs_entity_t secondary;
} AttachedWeapons;
} Arms;
extern ECS_COMPONENT_DECLARE(Arms);
typedef struct Arm {
f32 offset;
f32 extended;
} Arm;
extern ECS_COMPONENT_DECLARE(Arm);
extern ECS_COMPONENT_DECLARE(UnitAction);
extern ECS_COMPONENT_DECLARE(UnitAI);

View File

@@ -18,6 +18,7 @@ ecs_entity_t entityCreateWorker(const Position position, Game *game) {
size.x, size.y);
ecs_set(ECS, e, SpatialGridID, { spatialID });
ecs_set(ECS, e, Rotation, { 0.0f });
ecs_set(ECS, e, Orientation, {0.0f});
ecs_set(ECS, e, Velocity, {});
ecs_set(ECS, e, Steering, {});
TextureRegion workerRegion = {
@@ -46,5 +47,19 @@ ecs_entity_t entityCreateWorker(const Position position, Game *game) {
.depositSpeed = 0.2f,
.carryCapacity = 5,
});
ecs_entity_t right = entityCreateEmpty();
Arms arms = {.primary = right};
ecs_set_ptr(ECS, e, Arms, &arms);
ecs_set(ECS, right, Arm, {.offset = 45.0f, 4.5f});
ecs_set(ECS, right, Size, {8, 8});
ecs_set(ECS, right, Rotation, { 0.0f });
TextureRegion daggerRegion = {
tileset->tiles,
bzTilesetGetTileRegion(tileset, getItemTile(ITEM_AXE))
};
ecs_set_ptr(ECS, right, TextureRegion, &daggerRegion);
return e;
}

View File

@@ -393,4 +393,55 @@ static AnimationFrame entityGetAnimationFrame(EntityType entity, AnimType type,
return (AnimationFrame) {-1, -1.0f};
}
typedef enum ItemType {
ITEM_STAFF,
ITEM_PICKAXE,
ITEM_AXE,
ITEM_DAGGER,
ITEM_WOOD_SHIELD,
ITEM_SHIELD,
ITEM_IRON_SHIELD,
ITEM_BOW,
ITEM_JAVLIN,
ITEM_ARROW,
ITEM_SWORD,
ITEM_GREATSWORD,
ITEM_CUTLASS,
ITEM_BATTLEAXE,
ITEM_GREATEAXE,
ITEM_SYTHE,
ITEM_MACE,
ITEM_BATTLEHAMMER,
ITEM_SPEAR,
ITEM_TRIDENT,
ITEM_COUNT,
ITEM_NONE,
} ItemType;
static ItemType getItemTile(ItemType type) {
switch (type) {
case ITEM_STAFF: return 7680;
case ITEM_PICKAXE: return 7681;
case ITEM_AXE: return 7682;
case ITEM_DAGGER: return 7683;
case ITEM_WOOD_SHIELD: return 7936;
case ITEM_SHIELD: return 7937;
case ITEM_IRON_SHIELD: return 7938;
case ITEM_BOW: return 7939;
case ITEM_JAVLIN: return 7942;
case ITEM_ARROW: return 7943;
case ITEM_SWORD: return 8192;
case ITEM_GREATSWORD: return 8193;
case ITEM_CUTLASS: return 8194;
case ITEM_BATTLEAXE: return 8195;
case ITEM_GREATEAXE: return 8196;
case ITEM_SYTHE: return 8197;
case ITEM_MACE: return 8198;
case ITEM_BATTLEHAMMER: return 8199;
case ITEM_SPEAR: return 8200;
case ITEM_TRIDENT: return 8201;
default: return -1;
}
}
#endif // GAME_TILESET_H

View File

@@ -313,6 +313,7 @@ static void renderGame(Game *game, float dt) {
// Entities
bzArrayClear(game->drawData);
ecs_iter_t it = ecs_query_iter(ECS, game->drawQuery);
ecs_entity_t worker = 0;
while (ecs_iter_next(&it)) {
Position *p = ecs_field(&it, Position, 1);
Size *s = ecs_field(&it, Size, 2);
@@ -320,6 +321,9 @@ static void renderGame(Game *game, float dt) {
TextureRegion *t = ecs_field(&it, TextureRegion, 4);
for (i32 i = 0; i < it.count; i++) {
Rectangle dst = {p[i].x, p[i].y, s[i].x, s[i].y};
if (dst.width == 10 && dst.height == 10) {
worker = it.entities[i];
}
Vector2 origin = {dst.width * 0.5f, dst.height};
dst.x += origin.x - dst.width * 0.5f;
dst.y += origin.y - dst.height * 0.5f;
@@ -327,8 +331,8 @@ static void renderGame(Game *game, float dt) {
// Fixes texture bleeding issue
src.x += 0.01f;
src.y += 0.01f;
src.width -= 0.01f;
src.height -= 0.01f;
src.width -= 0.02f;
src.height -= 0.02f;
if (t[i].flipX) src.width *= -1.0f;
if (t[i].flipY) src.height *= -1.0f;
bzArrayPush(game->drawData, (DrawData) {
@@ -346,6 +350,32 @@ static void renderGame(Game *game, float dt) {
DrawData draw = game->drawData[i];
DrawTexturePro(draw.tex, draw.src, draw.dst, draw.origin, draw.rotation, WHITE);
}
Vector2 target = GetMousePosition();
target = GetScreenToWorld2D(target, game->camera);
static f32 elapsed = 0;
static bool attack = false;
static Vector2 lockedTarget;
if (!attack && IsMouseButtonPressed(0)) {
attack = true;
lockedTarget = target;
elapsed = 0;
}
elapsed += dt * 2;
elapsed = Clamp(elapsed, 0, 1.0f);
attack = false;
if (worker && false) {
Position *pos = ecs_get_mut(ECS, worker, Position);
DrawCircle(pos->x, pos->y, 2.0f, BLUE);
Vector2 attackVector = Vector2Subtract(lockedTarget, *pos);
attackVector = Vector2Normalize(attackVector);
attackVector = Vector2Scale(attackVector, 2.0f);
DrawLine(pos->x, pos->y, pos->x + attackVector.x, pos->y + attackVector.y, RED);
Rotation *rot = ecs_get_mut(ECS, worker, Rotation);
f32 targetRot = Vector2Angle(*pos, lockedTarget);
targetRot += 25 * DEG2RAD;
*rot = targetRot * bzEase(BZ_EASE_IN_BACK, elapsed);
bzLogInfo("%.2f", Vector2Angle(*pos, lockedTarget) * RAD2DEG);
}
ecs_progress(ECS, dt);
ecs_enable(ECS, renderDebugPathSystem, game->debugDraw.path);

View File

@@ -141,6 +141,31 @@ void entityFollowPath(ecs_iter_t *it) {
}
}
static void entityUpdateArm(ecs_entity_t armEntity, Position pos, Velocity vel,
Rotation rot, Orientation orient) {
if (!armEntity) return;
const Arm arm = *ecs_get(ECS, armEntity, Arm);
Vector2 v = {arm.extended, 0.0f};
v = Vector2Rotate(v, orient + arm.offset);
v = Vector2Add(v, pos);
ecs_set_ptr(ECS, armEntity, Position, &v);
}
void entityUpdateArms(ecs_iter_t *it) {
Position *position = ecs_field(it, Position, 1);
Velocity *velocity = ecs_field(it, Velocity, 2);
Rotation *rotation = ecs_field(it, Rotation, 3);
Orientation *orientation = ecs_field(it, Orientation, 4);
Arms *arms = ecs_field(it, Arms, 5);
for (i32 i = 0; i < it->count; i++) {
entityUpdateArm(arms[i].primary, position[i], velocity[i],
rotation[i], orientation[i]);
entityUpdateArm(arms[i].secondary, position[i], velocity[i],
rotation[i], orientation[i]);
}
}
void renderColliders(ecs_iter_t *it) {
Position *pos = ecs_field(it, Position, 1);
Size *size = ecs_field(it, Size, 2);
@@ -152,19 +177,27 @@ void renderColliders(ecs_iter_t *it) {
}
}
void renderRotationDirection(ecs_iter_t *it) {
void renderOrientationDirection(ecs_iter_t *it) {
Position *pos = ecs_field(it, Position, 1);
Rotation *rot = ecs_field(it, Rotation, 2);
Orientation *orientation = ecs_field(it, Orientation, 2);
for (i32 i = 0; i < it->count; i++) {
Vector2 v = {10.0f, 0.0f};
v = Vector2Rotate(v, rot[i]);
Vector2 v = {6.0f, 0.0f};
v = Vector2Rotate(v, orientation[i]);
v = Vector2Add(v, pos[i]);
DrawCircle(v.x, v.y, 1.0f, RED);
DrawLine(pos->x, pos->y, v.x, v.y, RED);
}
}
void renderArmPosition(ecs_iter_t *it) {
Position *pos = ecs_field(it, Position, 1);
Arm *arm = ecs_field(it, Arm, 2);
for (i32 i = 0; i < it->count; i++) {
DrawCircle(pos[i].x, pos[i].y, 1.5f, ORANGE);
}
}
void renderDebugPath(ecs_iter_t *it) {
Path *path = ecs_field(it, Path, 1);

View File

@@ -124,7 +124,12 @@ void inputUnitAction(Game *game, InputState *input) {
while (ecs_iter_next(&it)) {
for (i32 i = 0; i < it.count; i++) {
const ecs_entity_t entity = it.entities[i];
entitySetPath(entity, target, game);
clearActions(entity, game);
addAction(entity, game, &(const Action) {
.type = ACTION_MOVE_TO,
.as.moveTo.target = target,
.as.moveTo.proximityThreshold = 6.0f,
});
}
}
ecs_defer_end(ECS);

View File

@@ -3,6 +3,8 @@
#include "../game_state.h"
ecs_entity_t renderCollidersSystem;
ecs_entity_t renderOrientDirSystem;
ecs_entity_t renderArmPositionSystem;
ecs_entity_t renderDebugPathSystem;
ECS_DTOR(SpatialGridID, gridID, {
@@ -43,6 +45,7 @@ void setupSystems() {
ECS_SYSTEM(ECS, entityMoveToTarget, EcsOnUpdate, Position, Velocity, TargetPosition, Steering);
ECS_SYSTEM(ECS, entityFollowPath, EcsOnUpdate, Path);
ECS_SYSTEM(ECS, entityUpdateArms, EcsOnUpdate, Position, Velocity, Rotation, Orientation, Arms);
ECS_SYSTEM(ECS, handleUnitActionsSystem, EcsOnUpdate, UnitAction);
ECS_SYSTEM(ECS, updateUnitAISystem, EcsOnUpdate, UnitAI, UnitAction);
@@ -56,9 +59,14 @@ void setupSystems() {
ECS_SYSTEM(ECS, renderDebugPath, EcsOnUpdate, Path);
ECS_SYSTEM(ECS, renderColliders, EcsOnUpdate, Position, Size);
ECS_SYSTEM(ECS, renderRotationDirection, EcsOnUpdate, Position, Rotation);
ECS_SYSTEM(ECS, renderOrientationDirection, EcsOnUpdate, Position, Orientation);
ECS_SYSTEM(ECS, renderArmPosition, EcsOnUpdate, Position, Arm);
renderDebugPathSystem = renderDebugPath;
renderOrientDirSystem = renderOrientationDirection;
renderArmPositionSystem = renderArmPosition;
renderCollidersSystem = renderColliders;
ecs_enable(ECS, renderOrientDirSystem, false);
ecs_enable(ECS, renderArmPositionSystem, false);
}

View File

@@ -101,6 +101,15 @@ void entityMoveToTarget(ecs_iter_t *it);
*/
void entityFollowPath(ecs_iter_t *it);
/*
* 1. Position
* 2. Velocity
* 3. Rotation
* 4. Orientation
* 5. Arms
*/
void entityUpdateArms(ecs_iter_t *it);
/*
* 1: Position
@@ -110,9 +119,15 @@ void renderColliders(ecs_iter_t *it);
/*
* 1: Position
* 2: Rotation
* 2: Orientation
*/
void renderRotationDirection(ecs_iter_t *it);
void renderOrientationDirection(ecs_iter_t *it);
/*
* 1. Position
* 2. Arm
*/
void renderArmPosition(ecs_iter_t *it);
/*
* 1: Path
@@ -161,6 +176,8 @@ void drawPlayerInputUI();
**********************************/
extern ecs_entity_t renderCollidersSystem;
extern ecs_entity_t renderOrientDirSystem;
extern ecs_entity_t renderArmPositionSystem;
extern ecs_entity_t renderDebugPathSystem;
void setupSystems();

View File

@@ -12,8 +12,14 @@ void actionMoveTo(ecs_entity_t entity, Action *action, Game *game) {
entitySetPath(entity, target, game);
return;
}
Vector2 pos = *ecs_get(ECS, entity, Position);
const f32 dt = GetFrameTime();
const Vector2 pos = *ecs_get(ECS, entity, Position);
if (ecs_has(ECS, entity, Orientation)) {
Orientation *orientation = ecs_get_mut(ECS, entity, Orientation);
f32 dif = Vector2Angle(pos, target) - *orientation;
dif = Clamp(dif, -10, 10) * dt * 10;
*orientation += dif;
}
f32 dst = Vector2Distance(pos, target);
if (dst < action->as.moveTo.proximityThreshold) {
action->finished = true;