Add chase/evade behaviour
This commit is contained in:
@@ -47,11 +47,89 @@ BzBTStatus aiResetElapsed(AIBlackboard *data, f32 dt) {
|
|||||||
return BZ_BT_SUCCESS;
|
return BZ_BT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ENEMY_NEARBY_DST 26.0f
|
||||||
|
|
||||||
BzBTStatus aiIsEnemyNearby(AIBlackboard *data, f32 dt) {
|
BzBTStatus aiIsEnemyNearby(AIBlackboard *data, f32 dt) {
|
||||||
|
if (data->seenEnemy && ecs_is_alive(ECS, data->seenEnemy)) {
|
||||||
|
Position enemyPos = *ecs_get(ECS, data->seenEnemy, Position);
|
||||||
|
Position pos = *ecs_get(ECS, data->entity, Position);
|
||||||
|
|
||||||
|
if (Vector2Distance(enemyPos, pos) > ENEMY_NEARBY_DST)
|
||||||
|
return BZ_BT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
const f32 range = 20.0f;
|
||||||
|
Position pos = *ecs_get(ECS, data->entity, Position);
|
||||||
|
HitBox hb = *ecs_get(ECS, data->entity, HitBox);
|
||||||
|
Vector2 center = entityGetCenter(pos, hb);
|
||||||
|
Owner owner = *ecs_get(ECS, data->entity, Owner);
|
||||||
|
|
||||||
|
ecs_entity_t closest = 0;
|
||||||
|
f32 closestDst = 10000.0f;
|
||||||
|
|
||||||
|
Game *game = ecs_singleton_get_mut(ECS, Game);
|
||||||
|
BzSpatialGridIter it = bzSpatialGridIter(game->entityGrid,
|
||||||
|
center.x - range, center.y - range,
|
||||||
|
center.x + range, center.y + range);
|
||||||
|
while (bzSpatialGridQueryNext(&it)) {
|
||||||
|
ecs_entity_t other = *(ecs_entity_t *) it.data;
|
||||||
|
if (!ecs_is_alive(ECS, other)) continue;
|
||||||
|
|
||||||
|
if (!ecs_has(ECS, other, Owner) ||
|
||||||
|
ecs_get(ECS, other, Owner)->player == owner.player)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Position otherPos = *ecs_get(ECS, other, Position);
|
||||||
|
HitBox otherHB = *ecs_get(ECS, other, HitBox);
|
||||||
|
Vector2 otherCenter = entityGetCenter(otherPos, otherHB);
|
||||||
|
|
||||||
|
f32 dst = Vector2Distance(center, otherCenter);
|
||||||
|
if (dst > range) continue;
|
||||||
|
|
||||||
|
if (!bzTileMapCanRayCastLine(&game->map, center, otherCenter))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (dst < closestDst) {
|
||||||
|
closest = other;
|
||||||
|
closestDst = dst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closest) {
|
||||||
|
data->seenEnemy = closest;
|
||||||
|
return BZ_BT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
return BZ_BT_FAIL;
|
return BZ_BT_FAIL;
|
||||||
}
|
}
|
||||||
BzBTStatus aiEvadeTarget(AIBlackboard *data, f32 dt) {
|
BzBTStatus aiAttackEnemy(AIBlackboard *data, f32 dt) {
|
||||||
|
if (!ecs_is_alive(ECS, data->seenEnemy))
|
||||||
return BZ_BT_SUCCESS;
|
return BZ_BT_SUCCESS;
|
||||||
|
|
||||||
|
Position enemyPos = *ecs_get(ECS, data->seenEnemy, Position);
|
||||||
|
Position pos = *ecs_get(ECS, data->entity, Position);
|
||||||
|
|
||||||
|
Vector2 dif = Vector2Subtract(enemyPos, pos);
|
||||||
|
// Overload steering
|
||||||
|
Steering *steering = ecs_get_mut(ECS, data->entity, Steering);
|
||||||
|
*steering = Vector2Normalize(dif);
|
||||||
|
|
||||||
|
return BZ_BT_RUNNING;
|
||||||
|
|
||||||
|
}
|
||||||
|
BzBTStatus aiEvadeEnemy(AIBlackboard *data, f32 dt) {
|
||||||
|
if (!ecs_is_alive(ECS, data->seenEnemy))
|
||||||
|
return BZ_BT_SUCCESS;
|
||||||
|
|
||||||
|
Position enemyPos = *ecs_get(ECS, data->seenEnemy, Position);
|
||||||
|
Position pos = *ecs_get(ECS, data->entity, Position);
|
||||||
|
|
||||||
|
Vector2 dif = Vector2Subtract(pos, enemyPos);
|
||||||
|
// Overload steering
|
||||||
|
Steering *steering = ecs_get_mut(ECS, data->entity, Steering);
|
||||||
|
*steering = Vector2Normalize(dif);
|
||||||
|
|
||||||
|
return BZ_BT_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
BzBTStatus aiFindNextHarvestable(AIBlackboard *data, f32 dt) {
|
BzBTStatus aiFindNextHarvestable(AIBlackboard *data, f32 dt) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
typedef struct AIBlackboard {
|
typedef struct AIBlackboard {
|
||||||
ecs_entity_t entity;
|
ecs_entity_t entity;
|
||||||
|
|
||||||
|
ecs_entity_t seenEnemy;
|
||||||
Vector2 moveToPos;
|
Vector2 moveToPos;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
@@ -29,7 +30,8 @@ BzBTStatus aiMoveTo(AIBlackboard *data, f32 dt);
|
|||||||
BzBTStatus aiResetElapsed(AIBlackboard *data, f32 dt);
|
BzBTStatus aiResetElapsed(AIBlackboard *data, f32 dt);
|
||||||
|
|
||||||
BzBTStatus aiIsEnemyNearby(AIBlackboard *data, f32 dt);
|
BzBTStatus aiIsEnemyNearby(AIBlackboard *data, f32 dt);
|
||||||
BzBTStatus aiEvadeTarget(AIBlackboard *data, f32 dt);
|
BzBTStatus aiAttackEnemy(AIBlackboard *data, f32 dt);
|
||||||
|
BzBTStatus aiEvadeEnemy(AIBlackboard *data, f32 dt);
|
||||||
|
|
||||||
// Worker
|
// Worker
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "entity_factory.h"
|
#include "entity_factory.h"
|
||||||
|
|
||||||
#include "ai_actions.h"
|
#include "ai_actions.h"
|
||||||
|
#include "systems/systems.h"
|
||||||
|
|
||||||
ecs_entity_t entityCreateEmpty() {
|
ecs_entity_t entityCreateEmpty() {
|
||||||
ecs_entity_t e = ecs_new_id(ECS);
|
ecs_entity_t e = ecs_new_id(ECS);
|
||||||
@@ -18,7 +19,10 @@ ecs_entity_t entityCreateBaseUnit(const Position position, f32 size, Player play
|
|||||||
};
|
};
|
||||||
HitBox hitbox = getEntityHitBoxRec(tileID);
|
HitBox hitbox = getEntityHitBoxRec(tileID);
|
||||||
ecs_entity_t e = entityCreateEmpty();
|
ecs_entity_t e = entityCreateEmpty();
|
||||||
ecs_set_ptr(ECS, e, Position, &position);
|
ecs_set(ECS, e, Position, {
|
||||||
|
position.x - size * 0.5f,
|
||||||
|
position.y + size * 0.5f,
|
||||||
|
});
|
||||||
f32 scl = size / region.rec.width;
|
f32 scl = size / region.rec.width;
|
||||||
ecs_set(ECS, e, Size, {region.rec.width * scl, region.rec.height * scl});
|
ecs_set(ECS, e, Size, {region.rec.width * scl, region.rec.height * scl});
|
||||||
hitbox.x *= scl;
|
hitbox.x *= scl;
|
||||||
@@ -86,6 +90,9 @@ ecs_entity_t entityCreateSoldier(const Position position, Player player, Game *g
|
|||||||
unit.maxDamage = 10.0f;
|
unit.maxDamage = 10.0f;
|
||||||
unit.attackCooldown = 1.0f;
|
unit.attackCooldown = 1.0f;
|
||||||
ecs_set_ptr(ECS, e, Unit, &unit);
|
ecs_set_ptr(ECS, e, Unit, &unit);
|
||||||
|
setAIBehaviour(e, game->BTs.unit, &(AIBlackboard) {
|
||||||
|
.moveToPos = position,
|
||||||
|
});
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
ecs_entity_t entityCreateWarrior(const Position position, Player player, Game *game) {
|
ecs_entity_t entityCreateWarrior(const Position position, Player player, Game *game) {
|
||||||
@@ -100,6 +107,9 @@ ecs_entity_t entityCreateWarrior(const Position position, Player player, Game *g
|
|||||||
unit.maxDamage = 22.0f;
|
unit.maxDamage = 22.0f;
|
||||||
unit.attackCooldown = 1.8f;
|
unit.attackCooldown = 1.8f;
|
||||||
ecs_set_ptr(ECS, e, Unit, &unit);
|
ecs_set_ptr(ECS, e, Unit, &unit);
|
||||||
|
setAIBehaviour(e, game->BTs.unit, &(AIBlackboard) {
|
||||||
|
.moveToPos = position,
|
||||||
|
});
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,6 +128,10 @@ ecs_entity_t entityCreateWorker(const Position position, Player player, Game *ga
|
|||||||
.lastChanged = -1000.0f
|
.lastChanged = -1000.0f
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setAIBehaviour(e, game->BTs.unit, &(AIBlackboard) {
|
||||||
|
.moveToPos = position,
|
||||||
|
});
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,8 +91,9 @@ typedef struct Game {
|
|||||||
|
|
||||||
BzStackAlloc stackAlloc;
|
BzStackAlloc stackAlloc;
|
||||||
struct {
|
struct {
|
||||||
BzBTNode *workerHarvest;
|
BzBTNode *worker;
|
||||||
BzBTNode *moveTo;
|
BzBTNode *unit;
|
||||||
|
BzBTNode *unitEvasive;
|
||||||
} BTs;
|
} BTs;
|
||||||
struct {
|
struct {
|
||||||
BzObjectPool *pathData;
|
BzObjectPool *pathData;
|
||||||
|
|||||||
47
game/main.c
47
game/main.c
@@ -259,25 +259,52 @@ bool init(void *userData) {
|
|||||||
});
|
});
|
||||||
game->pools.btNode = bzObjectPoolCreate(&(BzObjectPoolDesc) {
|
game->pools.btNode = bzObjectPoolCreate(&(BzObjectPoolDesc) {
|
||||||
.objectSize = bzBTGetNodeSize(),
|
.objectSize = bzBTGetNodeSize(),
|
||||||
.objectsPerPage = 64
|
.objectsPerPage = 40
|
||||||
});
|
});
|
||||||
game->pools.btNodeState = bzObjectPoolCreate(&(BzObjectPoolDesc) {
|
game->pools.btNodeState = bzObjectPoolCreate(&(BzObjectPoolDesc) {
|
||||||
.objectSize = bzBTGetNodeStateSize(),
|
.objectSize = bzBTGetNodeStateSize(),
|
||||||
.objectsPerPage = 1024,
|
.objectsPerPage = 1024,
|
||||||
});
|
});
|
||||||
BzObjectPool *nodePool = game->pools.btNode;
|
BzObjectPool *nodePool = game->pools.btNode;
|
||||||
// moveTo
|
// unit (aggressive)
|
||||||
{
|
{
|
||||||
BzBTNode *root = NULL;
|
BzBTNode *root = NULL;
|
||||||
BzBTNode *node = NULL;
|
BzBTNode *node = NULL;
|
||||||
root = bzBTMakeRoot(nodePool);
|
root = bzBTMakeRoot(nodePool);
|
||||||
game->BTs.moveTo = root;
|
game->BTs.unit = root;
|
||||||
|
|
||||||
// Just a single action for now
|
BzBTNode *sel = bzBTCompSelector(nodePool, root);
|
||||||
BzBTNode *seq = bzBTCompSequence(nodePool, root);
|
BzBTNode *attackSeq = bzBTCompSequence(nodePool, sel);
|
||||||
node = bzBTAction(nodePool, seq, (BzBTActionFn) aiMoveTo);
|
{
|
||||||
|
node = bzBTAction(nodePool, attackSeq, (BzBTActionFn) aiIsEnemyNearby);
|
||||||
|
bzBTNodeSetName(node, "isEnemyNearby");
|
||||||
|
|
||||||
|
node = bzBTAction(nodePool, attackSeq, (BzBTActionFn) aiAttackEnemy);
|
||||||
|
bzBTNodeSetName(node, "attackEnemy");
|
||||||
|
}
|
||||||
|
node = bzBTAction(nodePool, sel, (BzBTActionFn) aiMoveTo);
|
||||||
bzBTNodeSetName(node, "moveTo");
|
bzBTNodeSetName(node, "moveTo");
|
||||||
bzBTDecorDelay(nodePool, seq, 6.0f);
|
bzBTDecorDelay(nodePool, sel, 2.0f);
|
||||||
|
}
|
||||||
|
// Unit (evasive)
|
||||||
|
{
|
||||||
|
BzBTNode *root = NULL;
|
||||||
|
BzBTNode *node = NULL;
|
||||||
|
root = bzBTMakeRoot(nodePool);
|
||||||
|
game->BTs.unitEvasive = root;
|
||||||
|
|
||||||
|
BzBTNode *sel = bzBTCompSelector(nodePool, root);
|
||||||
|
BzBTNode *evadeSeq = bzBTCompSequence(nodePool, sel);
|
||||||
|
{
|
||||||
|
node = bzBTAction(nodePool, evadeSeq, (BzBTActionFn) aiIsEnemyNearby);
|
||||||
|
bzBTNodeSetName(node, "isEnemyNearby");
|
||||||
|
|
||||||
|
node = bzBTAction(nodePool, evadeSeq, (BzBTActionFn) aiEvadeEnemy);
|
||||||
|
bzBTNodeSetName(node, "evadeEnemy");
|
||||||
|
}
|
||||||
|
node = bzBTAction(nodePool, sel, (BzBTActionFn) aiMoveTo);
|
||||||
|
bzBTNodeSetName(node, "moveTo");
|
||||||
|
bzBTDecorDelay(nodePool, sel, 2.0f);
|
||||||
}
|
}
|
||||||
// evade
|
// evade
|
||||||
BzBTNode *evade = NULL;
|
BzBTNode *evade = NULL;
|
||||||
@@ -290,18 +317,16 @@ bool init(void *userData) {
|
|||||||
node = bzBTAction(nodePool, evadeSeq, (BzBTActionFn) aiIsEnemyNearby);
|
node = bzBTAction(nodePool, evadeSeq, (BzBTActionFn) aiIsEnemyNearby);
|
||||||
bzBTNodeSetName(node, "enemyNearby");
|
bzBTNodeSetName(node, "enemyNearby");
|
||||||
|
|
||||||
node = bzBTAction(nodePool, evadeSeq, (BzBTActionFn) aiEvadeTarget);
|
node = bzBTAction(nodePool, evadeSeq, (BzBTActionFn) aiEvadeEnemy);
|
||||||
bzBTNodeSetName(node, "evadeTarget");
|
bzBTNodeSetName(node, "evadeTarget");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// worker harvest
|
// worker harvest
|
||||||
{
|
{
|
||||||
BzBTNode *root = NULL;
|
BzBTNode *root = NULL;
|
||||||
BzBTNode *node = NULL;
|
BzBTNode *node = NULL;
|
||||||
root = bzBTMakeRoot(nodePool);
|
root = bzBTMakeRoot(nodePool);
|
||||||
game->BTs.workerHarvest = root;
|
game->BTs.worker = root;
|
||||||
|
|
||||||
BzBTNode *pSel = bzBTCompPSelector(nodePool, root);
|
BzBTNode *pSel = bzBTCompPSelector(nodePool, root);
|
||||||
bzBTSubTree(evade, pSel);
|
bzBTSubTree(evade, pSel);
|
||||||
|
|||||||
@@ -377,7 +377,7 @@ void loadMap(Game *game, const char *path, bool mainMenu) {
|
|||||||
if (nearest.entity == 0) continue;
|
if (nearest.entity == 0) continue;
|
||||||
|
|
||||||
ResourceType resType = ecs_get(ECS, nearest.entity, Resource)->type;
|
ResourceType resType = ecs_get(ECS, nearest.entity, Resource)->type;
|
||||||
setAIBehaviour(workers[i].entity, game->BTs.workerHarvest, &(AIBlackboard) {
|
setAIBehaviour(workers[i].entity, game->BTs.worker, &(AIBlackboard) {
|
||||||
.as.worker = {
|
.as.worker = {
|
||||||
.harvestType = resType,
|
.harvestType = resType,
|
||||||
.harvestTarget = nearest.entity,
|
.harvestTarget = nearest.entity,
|
||||||
|
|||||||
@@ -115,6 +115,16 @@ void inputUnitAction(Game *game, InputState *input) {
|
|||||||
const i32 numUnits = ecs_query_entity_count(query);
|
const i32 numUnits = ecs_query_entity_count(query);
|
||||||
BZ_ASSERT(numUnits > 0);
|
BZ_ASSERT(numUnits > 0);
|
||||||
|
|
||||||
|
ecs_entity_t *units = bzStackAlloc(&game->stackAlloc, sizeof(*units) * numUnits);
|
||||||
|
i32 unitIdx = 0;
|
||||||
|
ecs_iter_t it = ecs_query_iter(ECS, query);
|
||||||
|
while (ecs_query_next(&it)) {
|
||||||
|
for (i32 i = 0; i < it.count; i++) {
|
||||||
|
ecs_entity_t entity = it.entities[i];
|
||||||
|
units[unitIdx++] = entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const MouseButton actionBtn = input->mapping.secondaryBtn;
|
const MouseButton actionBtn = input->mapping.secondaryBtn;
|
||||||
|
|
||||||
input->cursor = CURSOR_NONE;
|
input->cursor = CURSOR_NONE;
|
||||||
@@ -166,13 +176,10 @@ void inputUnitAction(Game *game, InputState *input) {
|
|||||||
qsort(harvestables, numHarvestables, sizeof(*harvestables), entityFloatPairCmp);
|
qsort(harvestables, numHarvestables, sizeof(*harvestables), entityFloatPairCmp);
|
||||||
i32 idxHarvestable = 0;
|
i32 idxHarvestable = 0;
|
||||||
|
|
||||||
ecs_defer_begin(ECS);
|
for (i32 i = 0; i < unitIdx; i++) {
|
||||||
ecs_iter_t it = ecs_query_iter(ECS, query);
|
|
||||||
while (ecs_query_next(&it)) {
|
|
||||||
for (i32 i = 0; i < it.count; i++) {
|
|
||||||
if (idxHarvestable >= numHarvestables)
|
if (idxHarvestable >= numHarvestables)
|
||||||
break;
|
break;
|
||||||
ecs_entity_t entity = it.entities[i];
|
ecs_entity_t entity = units[i];
|
||||||
|
|
||||||
EntityFloatPair harvestEntity = {0, 0};
|
EntityFloatPair harvestEntity = {0, 0};
|
||||||
while (idxHarvestable < numHarvestables) {
|
while (idxHarvestable < numHarvestables) {
|
||||||
@@ -192,7 +199,7 @@ void inputUnitAction(Game *game, InputState *input) {
|
|||||||
Worker *worker = ecs_get_mut(ECS, entity, Worker);
|
Worker *worker = ecs_get_mut(ECS, entity, Worker);
|
||||||
worker->carryRes = resource.type;
|
worker->carryRes = resource.type;
|
||||||
|
|
||||||
setAIBehaviour(entity, game->BTs.workerHarvest, &(AIBlackboard) {
|
setAIBehaviour(entity, game->BTs.worker, &(AIBlackboard) {
|
||||||
.as.worker = {
|
.as.worker = {
|
||||||
.harvestType = resource.type,
|
.harvestType = resource.type,
|
||||||
.harvestTarget = harvestEntity.entity,
|
.harvestTarget = harvestEntity.entity,
|
||||||
@@ -202,11 +209,13 @@ void inputUnitAction(Game *game, InputState *input) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ecs_defer_end(ECS);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((taskEntity = queryEntity(game->entityGrid, input->mouseWorld, ecs_id(Owner))) && ecs_get(ECS, taskEntity, Owner)->player != game->player) {
|
||||||
|
input->cursor = CURSOR_ATTACK;
|
||||||
|
}
|
||||||
|
|
||||||
// Unit place position
|
// Unit place position
|
||||||
Vector2 *positions = bzStackAlloc(&game->stackAlloc, sizeof(*positions) * numUnits);
|
Vector2 *positions = bzStackAlloc(&game->stackAlloc, sizeof(*positions) * numUnits);
|
||||||
Vector2 start = Vector2Zero();
|
Vector2 start = Vector2Zero();
|
||||||
@@ -254,13 +263,14 @@ void inputUnitAction(Game *game, InputState *input) {
|
|||||||
|
|
||||||
for (i32 i = 0; i < unitIdx; i++) {
|
for (i32 i = 0; i < unitIdx; i++) {
|
||||||
ecs_entity_t entity = entities[i].entity;
|
ecs_entity_t entity = entities[i].entity;
|
||||||
setAIBehaviour(entity, game->BTs.moveTo, &(AIBlackboard) {
|
setAIBehaviour(entity, game->BTs.unit, &(AIBlackboard) {
|
||||||
.moveToPos = positions[i],
|
.moveToPos = positions[i],
|
||||||
.proximity = 1.0f,
|
.proximity = 1.0f,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bzStackAllocFree(&game->stackAlloc, units);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updatePlayerInput() {
|
void updatePlayerInput() {
|
||||||
@@ -450,7 +460,7 @@ void drawPlayerInputUIGround() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input->unitPlacePos) {
|
if (input->unitPlacePos && input->cursor == CURSOR_NONE && input->numUnits >= 2) {
|
||||||
for (i32 i = 0; i < input->numUnits; i++) {
|
for (i32 i = 0; i < input->numUnits; i++) {
|
||||||
DrawCircleV(input->unitPlacePos[i], 2.0f, RED);
|
DrawCircleV(input->unitPlacePos[i], 2.0f, RED);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -406,11 +406,11 @@ void drawMainMenuUI(Game *game, f32 dt) {
|
|||||||
if (uiMainMenuButton("Play", true)) {
|
if (uiMainMenuButton("Play", true)) {
|
||||||
setScreen(game, SCREEN_GAME);
|
setScreen(game, SCREEN_GAME);
|
||||||
unloadMap(game);
|
unloadMap(game);
|
||||||
//loadMap(game, "assets/maps/tree_test.tmj");
|
//loadMap(game, "assets/maps/tree_test.tmj", false);
|
||||||
//loadMap(game, "assets/maps/entity_test.tmj");
|
//loadMap(game, "assets/maps/entity_test.tmj", false);
|
||||||
//loadMap(game, "assets/maps/worker_test.tmj");
|
//loadMap(game, "assets/maps/worker_test.tmj", false);
|
||||||
//loadMap(game, "assets/maps/battle_test.tmj");
|
loadMap(game, "assets/maps/battle_test.tmj", false);
|
||||||
loadMap(game, "assets/maps/map_01.tmj", false);
|
//loadMap(game, "assets/maps/map_01.tmj", false);
|
||||||
}
|
}
|
||||||
if (uiMainMenuButton("Settings", true)) {
|
if (uiMainMenuButton("Settings", true)) {
|
||||||
setScreen(game, SCREEN_SETTINGS);
|
setScreen(game, SCREEN_SETTINGS);
|
||||||
|
|||||||
Reference in New Issue
Block a user