Path following
This commit is contained in:
@@ -9,8 +9,7 @@ add_subdirectory(engine/)
|
|||||||
|
|
||||||
|
|
||||||
add_executable(PixelDefense
|
add_executable(PixelDefense
|
||||||
game/systems/animations.c
|
game/systems/entity_systems.c
|
||||||
game/systems/entity_renderer.c
|
|
||||||
game/systems/systems.h
|
game/systems/systems.h
|
||||||
|
|
||||||
game/utils/building_types.h
|
game/utils/building_types.h
|
||||||
@@ -19,6 +18,7 @@ add_executable(PixelDefense
|
|||||||
|
|
||||||
game/buildings.c
|
game/buildings.c
|
||||||
game/buildings.h
|
game/buildings.h
|
||||||
|
game/components.c
|
||||||
game/components.h
|
game/components.h
|
||||||
game/entrypoint.c
|
game/entrypoint.c
|
||||||
game/main.c
|
game/main.c
|
||||||
|
|||||||
@@ -384,8 +384,8 @@
|
|||||||
"type":"",
|
"type":"",
|
||||||
"visible":true,
|
"visible":true,
|
||||||
"width":10,
|
"width":10,
|
||||||
"x":1155.52,
|
"x":914.186666666667,
|
||||||
"y":473.417
|
"y":396.083666666667
|
||||||
}],
|
}],
|
||||||
"opacity":1,
|
"opacity":1,
|
||||||
"type":"objectgroup",
|
"type":"objectgroup",
|
||||||
|
|||||||
30
game/components.c
Normal file
30
game/components.c
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#include "components.h"
|
||||||
|
|
||||||
|
|
||||||
|
ECS_COMPONENT_DECLARE(TilePosition);
|
||||||
|
ECS_COMPONENT_DECLARE(TileSize);
|
||||||
|
ECS_COMPONENT_DECLARE(Owner);
|
||||||
|
ECS_COMPONENT_DECLARE(Position);
|
||||||
|
ECS_COMPONENT_DECLARE(Size);
|
||||||
|
ECS_COMPONENT_DECLARE(TargetPosition);
|
||||||
|
ECS_COMPONENT_DECLARE(Rotation);
|
||||||
|
ECS_COMPONENT_DECLARE(Health);
|
||||||
|
ECS_COMPONENT_DECLARE(TextureRegion);
|
||||||
|
ECS_COMPONENT_DECLARE(AnimationType);
|
||||||
|
ECS_COMPONENT_DECLARE(Animation);
|
||||||
|
ECS_COMPONENT_DECLARE(Path);
|
||||||
|
|
||||||
|
void initComponentIDs(ecs_world_t *ecs) {
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, TilePosition);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, TileSize);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, Owner);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, Position);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, Size);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, TargetPosition);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, Rotation);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, Health);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, TextureRegion);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, AnimationType);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, Animation);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, Path);
|
||||||
|
}
|
||||||
@@ -2,28 +2,40 @@
|
|||||||
#define PIXELDEFENSE_COMPONENTS_H
|
#define PIXELDEFENSE_COMPONENTS_H
|
||||||
|
|
||||||
#include <breeze.h>
|
#include <breeze.h>
|
||||||
|
#include <flecs.h>
|
||||||
|
|
||||||
#include "utils/building_types.h"
|
#include "utils/building_types.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define ecs_set_p(world, e, T, ...) ecs_set_id(world, e, ecs_id(T), sizeof(T), (T*)__VA_ARGS__)
|
||||||
|
|
||||||
typedef struct TilePosition {
|
typedef struct TilePosition {
|
||||||
BzTile x;
|
BzTile x;
|
||||||
BzTile y;
|
BzTile y;
|
||||||
} TilePosition;
|
} TilePosition;
|
||||||
|
extern ECS_COMPONENT_DECLARE(TilePosition);
|
||||||
|
|
||||||
typedef struct TileSize {
|
typedef struct TileSize {
|
||||||
BzTile sizeX;
|
BzTile sizeX;
|
||||||
BzTile sizeY;
|
BzTile sizeY;
|
||||||
} TileSize;
|
} TileSize;
|
||||||
|
extern ECS_COMPONENT_DECLARE(TileSize);
|
||||||
|
|
||||||
typedef struct Owner {
|
typedef struct Owner {
|
||||||
BuildingType playerID;
|
BuildingType playerID;
|
||||||
} Owner;
|
} Owner;
|
||||||
|
extern ECS_COMPONENT_DECLARE(Owner);
|
||||||
|
|
||||||
typedef Vector2 Position, Size;
|
typedef Vector2 Position, Size, TargetPosition;
|
||||||
|
extern ECS_COMPONENT_DECLARE(Position);
|
||||||
|
extern ECS_COMPONENT_DECLARE(Size);
|
||||||
|
extern ECS_COMPONENT_DECLARE(TargetPosition);
|
||||||
|
|
||||||
typedef f32 Rotation;
|
typedef f32 Rotation;
|
||||||
|
extern ECS_COMPONENT_DECLARE(Rotation);
|
||||||
|
|
||||||
typedef f32 Health;
|
typedef f32 Health;
|
||||||
|
extern ECS_COMPONENT_DECLARE(Health);
|
||||||
|
|
||||||
typedef struct TextureRegion {
|
typedef struct TextureRegion {
|
||||||
Texture2D texture;
|
Texture2D texture;
|
||||||
@@ -31,11 +43,13 @@ typedef struct TextureRegion {
|
|||||||
bool flipX;
|
bool flipX;
|
||||||
bool flipY;
|
bool flipY;
|
||||||
} TextureRegion;
|
} TextureRegion;
|
||||||
|
extern ECS_COMPONENT_DECLARE(TextureRegion);
|
||||||
|
|
||||||
typedef enum AnimationType {
|
typedef enum AnimationType {
|
||||||
ANIMATION_IDLE,
|
ANIMATION_IDLE,
|
||||||
ANIMATION_WALK,
|
ANIMATION_WALK,
|
||||||
} AnimationType;
|
} AnimationType;
|
||||||
|
extern ECS_COMPONENT_DECLARE(AnimationType);
|
||||||
|
|
||||||
typedef struct Animation {
|
typedef struct Animation {
|
||||||
TextureRegion firstFrame;
|
TextureRegion firstFrame;
|
||||||
@@ -45,7 +59,18 @@ typedef struct Animation {
|
|||||||
f32 frameDuration;
|
f32 frameDuration;
|
||||||
f32 elapsed;
|
f32 elapsed;
|
||||||
} Animation;
|
} Animation;
|
||||||
|
extern ECS_COMPONENT_DECLARE(Animation);
|
||||||
|
|
||||||
|
typedef struct Path {
|
||||||
|
Position *waypoints;
|
||||||
|
i32 maxWaypoints;
|
||||||
|
i32 numWaypoints;
|
||||||
|
i32 curWaypoint;
|
||||||
|
} Path;
|
||||||
|
extern ECS_COMPONENT_DECLARE(Path);
|
||||||
|
|
||||||
|
|
||||||
|
void initComponentIDs(ecs_world_t *ecs);
|
||||||
|
|
||||||
|
|
||||||
#endif //PIXELDEFENSE_COMPONENTS_H
|
#endif //PIXELDEFENSE_COMPONENTS_H
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ typedef struct Game {
|
|||||||
ecs_entity_t *entityMap;
|
ecs_entity_t *entityMap;
|
||||||
f32 frameDuration;
|
f32 frameDuration;
|
||||||
Vector2 targetPos;
|
Vector2 targetPos;
|
||||||
|
ecs_entity_t entity;
|
||||||
|
Path path;
|
||||||
|
Position waypoints[128];
|
||||||
} Game;
|
} Game;
|
||||||
|
|
||||||
extern Game *GAME;
|
extern Game *GAME;
|
||||||
|
|||||||
24
game/main.c
24
game/main.c
@@ -40,6 +40,8 @@ bool bzMain(BzAppDesc *appDesc, int argc, const char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool init(Game *game) {
|
bool init(Game *game) {
|
||||||
|
initComponentIDs(ECS);
|
||||||
|
|
||||||
int screenWidth = 1280;
|
int screenWidth = 1280;
|
||||||
int screenHeight = 720;
|
int screenHeight = 720;
|
||||||
|
|
||||||
@@ -48,6 +50,7 @@ bool init(Game *game) {
|
|||||||
game->camera.offset = (Vector2) {screenWidth / 2.0f, screenHeight / 2.0f};
|
game->camera.offset = (Vector2) {screenWidth / 2.0f, screenHeight / 2.0f};
|
||||||
game->camera.rotation = 0.0f;
|
game->camera.rotation = 0.0f;
|
||||||
game->camera.zoom = 1.0f;
|
game->camera.zoom = 1.0f;
|
||||||
|
game->frameDuration = 0.16f;
|
||||||
|
|
||||||
game->terrainTileset = bzTilesetCreate( &(BzTilesetDesc) {
|
game->terrainTileset = bzTilesetCreate( &(BzTilesetDesc) {
|
||||||
.path="assets/terrain.tsj",
|
.path="assets/terrain.tsj",
|
||||||
@@ -86,8 +89,9 @@ bool init(Game *game) {
|
|||||||
|
|
||||||
ECS_SYSTEM(ECS, updateAnimations, EcsOnUpdate, Animation, TextureRegion);
|
ECS_SYSTEM(ECS, updateAnimations, EcsOnUpdate, Animation, TextureRegion);
|
||||||
ECS_SYSTEM(ECS, renderEntities, EcsOnUpdate, Position, Size, Rotation, TextureRegion);
|
ECS_SYSTEM(ECS, renderEntities, EcsOnUpdate, Position, Size, Rotation, TextureRegion);
|
||||||
ECS_SYSTEM(ECS, updatePos, EcsOnUpdate, Position, TextureRegion);
|
ECS_SYSTEM(ECS, updatePos, EcsOnUpdate, Position, TargetPosition, TextureRegion);
|
||||||
|
ECS_OBSERVER(ECS, targetFinish, EcsOnRemove, TargetPosition);
|
||||||
|
ECS_OBSERVER(ECS, startPath, EcsOnSet, Path);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void deinit(Game *game) {
|
void deinit(Game *game) {
|
||||||
@@ -121,8 +125,6 @@ void update(float dt, Game *game) {
|
|||||||
game->camera.zoom += ((float) GetMouseWheelMove() * 0.05f);
|
game->camera.zoom += ((float) GetMouseWheelMove() * 0.05f);
|
||||||
|
|
||||||
Vector2 worldPos = GetScreenToWorld2D(GetMousePosition(), game->camera);
|
Vector2 worldPos = GetScreenToWorld2D(GetMousePosition(), game->camera);
|
||||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
|
|
||||||
game->targetPos = worldPos;
|
|
||||||
int tileX = (int) worldPos.x / 16;
|
int tileX = (int) worldPos.x / 16;
|
||||||
int tileY = (int) worldPos.y / 16;
|
int tileY = (int) worldPos.y / 16;
|
||||||
|
|
||||||
@@ -162,12 +164,26 @@ void render(float dt, Game *game) {
|
|||||||
static PathNode *heap = NULL;
|
static PathNode *heap = NULL;
|
||||||
if (!heap)
|
if (!heap)
|
||||||
heap = bzHeapNew(PathNode, game->map.width * game->map.height);
|
heap = bzHeapNew(PathNode, game->map.width * game->map.height);
|
||||||
|
game->path.waypoints = game->waypoints;
|
||||||
|
game->path.maxWaypoints = 128;
|
||||||
findPath(&(PathfindingDesc) {
|
findPath(&(PathfindingDesc) {
|
||||||
.start=(TilePosition){57, 24},
|
.start=(TilePosition){57, 24},
|
||||||
.target=(TilePosition){tileX, tileY},
|
.target=(TilePosition){tileX, tileY},
|
||||||
.map=&game->map,
|
.map=&game->map,
|
||||||
.heap=heap,
|
.heap=heap,
|
||||||
|
.outPath=&game->path
|
||||||
});
|
});
|
||||||
|
for (i32 i = 0; i < game->path.numWaypoints; i++) {
|
||||||
|
Position pos = game->path.waypoints[i];
|
||||||
|
DrawCircle(pos.x, pos.y, 3.0f, RED);
|
||||||
|
}
|
||||||
|
if (game->path.numWaypoints > 0 && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
|
||||||
|
ecs_entity_t e = game->entity;
|
||||||
|
bzLogInfo("%d", ecs_is_alive(ECS, e));
|
||||||
|
Position pos = worldPos;
|
||||||
|
//ecs_set_ptr(ECS, e, Position, &pos);
|
||||||
|
ecs_set_ptr(ECS, e, Path, &game->path);
|
||||||
|
}
|
||||||
|
|
||||||
ecs_progress(ECS, dt);
|
ecs_progress(ECS, dt);
|
||||||
|
|
||||||
|
|||||||
@@ -18,18 +18,13 @@ bool initGameObjectsLayer(BzTileMap *map, BzTileObjectGroup *objectGroup) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool initEntityObjectsLayer(BzTileMap *map, BzTileObjectGroup *objectGroup) {
|
bool initEntityObjectsLayer(BzTileMap *map, BzTileObjectGroup *objectGroup) {
|
||||||
ECS_COMPONENT(ECS, Position);
|
|
||||||
ECS_COMPONENT(ECS, Size);
|
|
||||||
ECS_COMPONENT(ECS, Rotation);
|
|
||||||
ECS_COMPONENT(ECS, TextureRegion);
|
|
||||||
ECS_COMPONENT(ECS, Animation);
|
|
||||||
|
|
||||||
BzTileset *objectTileset = bzTileObjectGroupGetTileset(&GAME->map, objectGroup);
|
BzTileset *objectTileset = bzTileObjectGroupGetTileset(&GAME->map, objectGroup);
|
||||||
if (!objectTileset) return true;
|
if (!objectTileset) return true;
|
||||||
|
|
||||||
for (i32 i = 0; i < objectGroup->objectCount; i++) {
|
for (i32 i = 0; i < objectGroup->objectCount; i++) {
|
||||||
BzTileObject object = objectGroup->objects[i];
|
BzTileObject object = objectGroup->objects[i];
|
||||||
ecs_entity_t e = ecs_new_id(ECS);
|
ecs_entity_t e = ecs_new_id(ECS);
|
||||||
|
GAME->entity = e;
|
||||||
ecs_set(ECS, e, Position, {object.shape.x, object.shape.y});
|
ecs_set(ECS, e, Position, {object.shape.x, object.shape.y});
|
||||||
ecs_set(ECS, e, Size, {object.shape.sizeX, object.shape.sizeY});
|
ecs_set(ECS, e, Size, {object.shape.sizeX, object.shape.sizeY});
|
||||||
ecs_set(ECS, e, Rotation, {0.0f});
|
ecs_set(ECS, e, Rotation, {0.0f});
|
||||||
@@ -50,10 +45,6 @@ bool initEntityObjectsLayer(BzTileMap *map, BzTileObjectGroup *objectGroup) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool initBuildingsLayer(BzTileMap *map, BzTileLayer *layer) {
|
bool initBuildingsLayer(BzTileMap *map, BzTileLayer *layer) {
|
||||||
ECS_COMPONENT(ECS, TilePosition);
|
|
||||||
ECS_COMPONENT(ECS, TileSize);
|
|
||||||
ECS_COMPONENT(ECS, Owner);
|
|
||||||
|
|
||||||
GAME->entityMap = bzCalloc(sizeof(*GAME->entityMap), layer->width * layer->height);
|
GAME->entityMap = bzCalloc(sizeof(*GAME->entityMap), layer->width * layer->height);
|
||||||
|
|
||||||
BzTileLayer *ownershipLayer = layer;
|
BzTileLayer *ownershipLayer = layer;
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
#include "systems.h"
|
|
||||||
|
|
||||||
#include "../game_state.h"
|
|
||||||
|
|
||||||
void updateAnimations(ecs_iter_t *it) {
|
|
||||||
Animation *anim = ecs_field(it, Animation, 1);
|
|
||||||
TextureRegion *t = ecs_field(it, TextureRegion, 2);
|
|
||||||
|
|
||||||
float dt = GetFrameTime();
|
|
||||||
|
|
||||||
for (i32 i = 0; i < it->count; i++) {
|
|
||||||
anim[i].frameDuration = GAME->frameDuration;
|
|
||||||
anim[i].elapsed += dt;
|
|
||||||
if (anim[i].elapsed < anim[i].frameDuration) continue;
|
|
||||||
|
|
||||||
anim[i].currFrame = (anim[i].currFrame + 1) % anim[i].frameCount;
|
|
||||||
anim[i].elapsed = 0.0f;
|
|
||||||
t[i].rec.x = anim[i].firstFrame.rec.x + anim[i].currFrame * t[i].rec.width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#include "systems.h"
|
|
||||||
|
|
||||||
void renderEntities(ecs_iter_t *it) {
|
|
||||||
Position *p = ecs_field(it, Position, 1);
|
|
||||||
Size *s = ecs_field(it, Size, 2);
|
|
||||||
Rotation *r = ecs_field(it, Rotation, 3);
|
|
||||||
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};
|
|
||||||
Vector2 origin = {dst.width * 0.5f, dst.height * 0.5f};
|
|
||||||
Rectangle src = t[i].rec;
|
|
||||||
if (t[i].flipX) src.width *= -1.0f;
|
|
||||||
if (t[i].flipY) src.height *= -1.0f;
|
|
||||||
DrawTexturePro(t[i].texture, src, dst, origin, r[i], WHITE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
95
game/systems/entity_systems.c
Normal file
95
game/systems/entity_systems.c
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#include "systems.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "../game_state.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include <raymath.h>
|
||||||
|
|
||||||
|
|
||||||
|
void updateAnimations(ecs_iter_t *it) {
|
||||||
|
Animation *anim = ecs_field(it, Animation, 1);
|
||||||
|
TextureRegion *t = ecs_field(it, TextureRegion, 2);
|
||||||
|
|
||||||
|
float dt = GetFrameTime();
|
||||||
|
|
||||||
|
for (i32 i = 0; i < it->count; i++) {
|
||||||
|
anim[i].frameDuration = GAME->frameDuration;
|
||||||
|
anim[i].elapsed += dt;
|
||||||
|
if (anim[i].elapsed < anim[i].frameDuration) continue;
|
||||||
|
|
||||||
|
anim[i].currFrame = (anim[i].currFrame + 1) % anim[i].frameCount;
|
||||||
|
anim[i].elapsed = 0.0f;
|
||||||
|
t[i].rec.x = anim[i].firstFrame.rec.x + anim[i].currFrame * t[i].rec.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderEntities(ecs_iter_t *it) {
|
||||||
|
Position *p = ecs_field(it, Position, 1);
|
||||||
|
Size *s = ecs_field(it, Size, 2);
|
||||||
|
Rotation *r = ecs_field(it, Rotation, 3);
|
||||||
|
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};
|
||||||
|
Vector2 origin = {dst.width * 0.5f, dst.height * 0.5f};
|
||||||
|
Rectangle src = t[i].rec;
|
||||||
|
if (t[i].flipX) src.width *= -1.0f;
|
||||||
|
if (t[i].flipY) src.height *= -1.0f;
|
||||||
|
DrawTexturePro(t[i].texture, src, dst, origin, r[i], WHITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updatePos(ecs_iter_t *it) {
|
||||||
|
Position *pos = ecs_field(it, Position, 1);
|
||||||
|
TargetPosition *target = ecs_field(it, TargetPosition, 2);
|
||||||
|
TextureRegion *t = ecs_field(it, TextureRegion, 3);
|
||||||
|
|
||||||
|
for (i32 i = 0; i < it->count; i++) {
|
||||||
|
Vector2 d = Vector2Subtract(target[i], pos[i]);
|
||||||
|
if (Vector2LengthSqr(d) < 1) {
|
||||||
|
bzLogInfo("Done");
|
||||||
|
ecs_remove(ECS, it->entities[i], TargetPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 dN = Vector2Normalize(d);
|
||||||
|
|
||||||
|
dN = Vector2Scale(dN, 20);
|
||||||
|
t[i].flipX = dN.x < 0;
|
||||||
|
|
||||||
|
|
||||||
|
pos[i].x += dN.x * it->delta_time;
|
||||||
|
pos[i].y += dN.y * it->delta_time;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#include <stdlib.h>
|
||||||
|
void targetFinish(ecs_iter_t *it) {
|
||||||
|
for (i32 i = 0; i < it->count; i++) {
|
||||||
|
ecs_entity_t e = it->entities[i];
|
||||||
|
Path *path = ecs_get(it->world, e, Path);
|
||||||
|
if (!path) continue;
|
||||||
|
path->curWaypoint++;
|
||||||
|
if (path->curWaypoint >= path->numWaypoints) {
|
||||||
|
// Finished
|
||||||
|
ecs_remove(it->world, e, Path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TargetPosition target = path->waypoints[path->curWaypoint - 1];
|
||||||
|
target.x += rand() % (4 + 1 + 2) -2;
|
||||||
|
ecs_set(it->world, e, TargetPosition, {target.x, target.y});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
void startPath(ecs_iter_t *it) {
|
||||||
|
Path *path = ecs_field(it, Path, 1);
|
||||||
|
|
||||||
|
for (i32 i = 0; i < it->count; i++) {
|
||||||
|
ecs_entity_t e = it->entities[i];
|
||||||
|
if (path->numWaypoints == 0) {
|
||||||
|
ecs_remove(it->world, e, Path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ecs_set(it->world, e, TargetPosition, {path[i].waypoints[0].x, path[i].waypoints[0].y});
|
||||||
|
path[i].curWaypoint++;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,39 +7,8 @@
|
|||||||
|
|
||||||
void renderEntities(ecs_iter_t *it);
|
void renderEntities(ecs_iter_t *it);
|
||||||
void updateAnimations(ecs_iter_t *it);
|
void updateAnimations(ecs_iter_t *it);
|
||||||
|
void updatePos(ecs_iter_t *it);
|
||||||
#include "../game_state.h"
|
void targetFinish(ecs_iter_t *it);
|
||||||
#include <math.h>
|
void startPath(ecs_iter_t *it);
|
||||||
#include <raymath.h>
|
|
||||||
static void updatePos(ecs_iter_t *it) {
|
|
||||||
Position *pos = ecs_field(it, Position, 1);
|
|
||||||
TextureRegion *t = ecs_field(it, TextureRegion, 2);
|
|
||||||
|
|
||||||
Vector2 target = GAME->targetPos;
|
|
||||||
if (target.x == 0 && target.y == 0) return;
|
|
||||||
|
|
||||||
for (i32 i = 0; i < it->count; i++) {
|
|
||||||
target = Vector2Subtract(target, pos[i]);
|
|
||||||
float dX = 0, dY = 0;
|
|
||||||
if (target.x > 0) dX = 1;
|
|
||||||
else if (target.x < 0) dX = -1;
|
|
||||||
if (target.y > 0) dY = 1;
|
|
||||||
else if (target.y < 0) dY = -1;
|
|
||||||
|
|
||||||
dX *= 20;
|
|
||||||
dY *= 20;
|
|
||||||
|
|
||||||
if (Vector2Length(target) < 1) continue;
|
|
||||||
|
|
||||||
pos[i].x += dX * it->delta_time;
|
|
||||||
pos[i].y += dY * it->delta_time;
|
|
||||||
|
|
||||||
f32 ddx = GAME->targetPos.x - pos[i].x;
|
|
||||||
if (ddx < 0) ddx *= -1.0f;
|
|
||||||
|
|
||||||
if (ddx > 5)
|
|
||||||
t[i].flipX = dX < 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //PIXELDEFENSE_SYSTEMS_H
|
#endif //PIXELDEFENSE_SYSTEMS_H
|
||||||
|
|||||||
@@ -78,28 +78,46 @@ bool findPath(const PathfindingDesc *desc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawRectangle(desc->start.x * 16, desc->start.y * 16, 16, 16, BLUE);
|
i32 pathLen = 0;
|
||||||
Color color = RED;
|
if (foundPath && desc->outPath) {
|
||||||
if (foundPath) {
|
|
||||||
color = GREEN;
|
|
||||||
TilePosition pos = desc->target;
|
TilePosition pos = desc->target;
|
||||||
int count = 0;
|
|
||||||
while (pos.x != desc->start.x || pos.y != desc->start.y) {
|
while (pos.x != desc->start.x || pos.y != desc->start.y) {
|
||||||
|
Visited *visit = &visited[pos.y * map->width + pos.x];
|
||||||
|
BZ_ASSERT(visit->x != 0 && visit->y != 0);
|
||||||
|
pos.x -= visit->x;
|
||||||
|
pos.y -= visit->y;
|
||||||
|
pathLen++;
|
||||||
|
}
|
||||||
|
Path *out = desc->outPath;
|
||||||
|
out->curWaypoint = 0;
|
||||||
|
pos = desc->target;
|
||||||
|
i32 len = pathLen;
|
||||||
|
// Skip positions
|
||||||
|
while (len >= out->maxWaypoints) {
|
||||||
Visited visit = visited[pos.y * map->width + pos.x];
|
Visited visit = visited[pos.y * map->width + pos.x];
|
||||||
BZ_ASSERT(visit.x != 0 && visit.y != 0);
|
|
||||||
pos.x -= visit.x;
|
pos.x -= visit.x;
|
||||||
pos.y -= visit.y;
|
pos.y -= visit.y;
|
||||||
DrawRectangle(pos.x * 16, pos.y * 16, 16, 16, GREEN);
|
len--;
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
bzLogInfo("Path length: %d", count);
|
// Write path
|
||||||
|
for (i32 i = 0; i < len; i++) {
|
||||||
|
out->waypoints[len - i - 1] = (Position){
|
||||||
|
pos.x * map->tileWidth + map->tileWidth * 0.5f,
|
||||||
|
pos.y * map->tileHeight + map->tileHeight * 0.5f
|
||||||
|
};
|
||||||
|
out->numWaypoints++;
|
||||||
|
Visited visit = visited[pos.y * map->width + pos.x];
|
||||||
|
pos.x -= visit.x;
|
||||||
|
pos.y -= visit.y;
|
||||||
|
}
|
||||||
|
BZ_ASSERT(len == out->maxWaypoints);
|
||||||
|
out->numWaypoints = len;
|
||||||
}
|
}
|
||||||
DrawRectangle(desc->target.x * 16, desc->target.y * 16, 16, 16, color);
|
|
||||||
|
|
||||||
if (!desc->heap) {
|
if (!desc->heap) {
|
||||||
bzHeapFree(heap);
|
bzHeapFree(heap);
|
||||||
heap = NULL;
|
heap = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return foundPath;
|
return foundPath ? pathLen : -1;
|
||||||
}
|
}
|
||||||
@@ -22,6 +22,7 @@ typedef struct PathfindingDesc {
|
|||||||
TilePosition target;
|
TilePosition target;
|
||||||
BzTileMap *map;
|
BzTileMap *map;
|
||||||
PathNode *heap;
|
PathNode *heap;
|
||||||
|
Path *outPath;
|
||||||
} PathfindingDesc;
|
} PathfindingDesc;
|
||||||
|
|
||||||
bool findPath(const PathfindingDesc *desc);
|
bool findPath(const PathfindingDesc *desc);
|
||||||
|
|||||||
@@ -331,7 +331,7 @@
|
|||||||
</data>
|
</data>
|
||||||
</layer>
|
</layer>
|
||||||
<objectgroup id="31" name="Entities">
|
<objectgroup id="31" name="Entities">
|
||||||
<object id="19728" gid="1322" x="1155.52" y="473.417" width="10" height="10"/>
|
<object id="19728" gid="1322" x="914.187" y="396.084" width="10" height="10"/>
|
||||||
</objectgroup>
|
</objectgroup>
|
||||||
<objectgroup id="28" name="Game">
|
<objectgroup id="28" name="Game">
|
||||||
<object id="19726" name="camera" x="1048" y="476">
|
<object id="19726" name="camera" x="1048" y="476">
|
||||||
|
|||||||
Reference in New Issue
Block a user