From 6b1e62dd38614d2c99e5ad5fcc7750d5d953adf7 Mon Sep 17 00:00:00 2001 From: Steve Date: Sun, 21 Feb 2016 07:48:22 +0000 Subject: [PATCH] Start of replacing grid with quadtree. --- common.mk | 3 +- src/battle/ai.c | 11 +- src/battle/battle.c | 6 +- src/battle/battle.h | 3 +- src/battle/capitalShips.c | 7 +- src/battle/entities.c | 27 ++- src/battle/entities.h | 5 +- src/battle/grid.c | 128 ------------- src/battle/player.c | 4 +- src/battle/quadtree.c | 306 ++++++++++++++++++++++++++++++ src/battle/{grid.h => quadtree.h} | 0 src/battle/radar.c | 8 +- src/defs.h | 13 +- src/galaxy/mission.c | 33 ++-- src/structs.h | 12 +- 15 files changed, 374 insertions(+), 192 deletions(-) delete mode 100644 src/battle/grid.c create mode 100644 src/battle/quadtree.c rename src/battle/{grid.h => quadtree.h} (100%) diff --git a/common.mk b/common.mk index e0ad765..8159a80 100644 --- a/common.mk +++ b/common.mk @@ -13,13 +13,14 @@ OBJS += capitalShips.o challenges.o cJSON.o OBJS += debris.o dev.o draw.o OBJS += effects.o entities.o extractionPoint.o OBJS += fighters.o -OBJS += galacticMap.o game.o grid.o +OBJS += galacticMap.o game.o OBJS += hud.o OBJS += init.o input.o io.o items.o OBJS += load.o locations.o lookup.o OBJS += main.o messageBox.o mission.o missionInfo.o OBJS += objectives.o options.o OBJS += player.o +OBJS += quadtree.o OBJS += radar.o rope.o OBJS += save.o script.o sound.o starfield.o starSystems.o stats.o OBJS += testMission.o textures.o text.o title.o transition.o diff --git a/src/battle/ai.c b/src/battle/ai.c index 494cc5e..bf54ca0 100644 --- a/src/battle/ai.c +++ b/src/battle/ai.c @@ -638,7 +638,7 @@ static int nearItems(void) closest = MAX_TARGET_RANGE; - candidates = getAllEntsWithin(self->x - (self->w / 2) - (GRID_CELL_WIDTH / 2), self->y - (self->h / 2) - (GRID_CELL_HEIGHT / 2), GRID_CELL_WIDTH, GRID_CELL_HEIGHT, self); + candidates = getAllEntsWithin(self->x - (self->w / 2) - (SCREEN_WIDTH / 4), self->y - (self->h / 2) - (SCREEN_HEIGHT / 4), SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, self); self->target = NULL; @@ -684,7 +684,7 @@ static int nearTowableCraft(void) long closest, distance; Entity *e, **candidates; - candidates = getAllEntsWithin(self->x - (self->w / 2) - (GRID_CELL_WIDTH / 2), self->y - (self->h / 2) - (GRID_CELL_HEIGHT / 2), GRID_CELL_WIDTH, GRID_CELL_HEIGHT, self); + candidates = getAllEntsWithin(self->x - (self->w / 2) - (SCREEN_WIDTH / 4), self->y - (self->h / 2) - (SCREEN_HEIGHT / 4), SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, self); closest = MAX_TARGET_RANGE; @@ -787,11 +787,8 @@ static void moveToLeader(void) static void doWander(void) { - self->targetLocation.x = 5 + (rand() % (GRID_SIZE - 10)); - self->targetLocation.x *= GRID_CELL_WIDTH; - - self->targetLocation.y = 5 + (rand() % (GRID_SIZE - 10)); - self->targetLocation.y *= GRID_CELL_HEIGHT; + self->targetLocation.x = 500 + (rand() % (BATTLE_AREA_WIDTH - 1000)); + self->targetLocation.y = 500 + (rand() % (BATTLE_AREA_HEIGHT - 1000)); self->aiActionTime = FPS * 15; diff --git a/src/battle/battle.c b/src/battle/battle.c index ff24465..fd2e869 100644 --- a/src/battle/battle.c +++ b/src/battle/battle.c @@ -52,6 +52,10 @@ void initBattle(void) app.delegate.draw = &draw; memset(&app.keyboard, 0, sizeof(int) * MAX_KEYBOARD_KEYS); + battle.quadtree.w = BATTLE_AREA_WIDTH; + battle.quadtree.h = BATTLE_AREA_HEIGHT; + initQuadtree(&battle.quadtree); + initBullets(); initEntities(); @@ -436,5 +440,5 @@ void destroyBattle(void) destroyScript(); - destroyGrid(); + destroyQuadtree(); } diff --git a/src/battle/battle.h b/src/battle/battle.h index b21496d..3aef3c5 100644 --- a/src/battle/battle.h +++ b/src/battle/battle.h @@ -64,7 +64,8 @@ extern void drawOptions(void); extern void playSound(int id); extern void resetWaypoints(void); extern void doPlayerSelect(void); -extern void destroyGrid(void); +extern void destroyQuadtree(void); +extern void initQuadtree(Quadtree *root); extern void completeMission(void); extern void initEffects(void); extern void doScript(void); diff --git a/src/battle/capitalShips.c b/src/battle/capitalShips.c index 9b5c37d..b9b2f8c 100644 --- a/src/battle/capitalShips.c +++ b/src/battle/capitalShips.c @@ -164,11 +164,8 @@ static void findAITarget(void) } else { - self->targetLocation.x = 5 + (rand() % (GRID_SIZE - 10)); - self->targetLocation.x *= GRID_CELL_WIDTH; - - self->targetLocation.y = 5 + (rand() % (GRID_SIZE - 10)); - self->targetLocation.y *= GRID_CELL_HEIGHT; + self->targetLocation.x = 500 + (rand() % (BATTLE_AREA_WIDTH - 1000)); + self->targetLocation.y = 500 + (rand() % (BATTLE_AREA_HEIGHT - 1000)); self->aiActionTime = FPS * (30 + (rand() % 120)); } diff --git a/src/battle/entities.c b/src/battle/entities.c index 25cc2a8..e50b059 100644 --- a/src/battle/entities.c +++ b/src/battle/entities.c @@ -69,14 +69,9 @@ void doEntities(void) numAllies = numEnemies = numActiveAllies = numActiveEnemies = 0; - destroyGrid(); - for (e = battle.entityHead.next ; e != NULL ; e = e->next) { - if (e->active && e->alive != ALIVE_DEAD) - { - addToGrid(e); - } + removeFromQuadtree(e, &battle.quadtree); } if (dev.playerImmortal) @@ -169,6 +164,8 @@ void doEntities(void) e->x += e->dx; e->y += e->dy; + + addToQuadtree(e, &battle.quadtree); } else { @@ -261,30 +258,30 @@ static void restrictToGrid(Entity *e) { float force; - if (e->x <= GRID_RESTRICTION_SIZE) + if (e->x <= BATTLE_AREA_EDGE) { - force = GRID_RESTRICTION_SIZE - e->x; + force = BATTLE_AREA_EDGE - e->x; e->dx += force * 0.001; e->dx *= 0.95; } - if (e->y <= GRID_RESTRICTION_SIZE) + if (e->y <= BATTLE_AREA_EDGE) { - force = GRID_RESTRICTION_SIZE - e->y; + force = BATTLE_AREA_EDGE - e->y; e->dy += force * 0.001; e->dy *= 0.95; } - if (e->x >= (GRID_SIZE * GRID_CELL_WIDTH) - GRID_RESTRICTION_SIZE) + if (e->x >= BATTLE_AREA_WIDTH - BATTLE_AREA_EDGE) { - force = e->x - ((GRID_SIZE * GRID_CELL_WIDTH) - GRID_RESTRICTION_SIZE); + force = e->x - (BATTLE_AREA_WIDTH - BATTLE_AREA_EDGE); e->dx -= force * 0.001; e->dx *= 0.95; } - if (e->y >= (GRID_SIZE * GRID_CELL_HEIGHT) - GRID_RESTRICTION_SIZE) + if (e->y >= BATTLE_AREA_HEIGHT - BATTLE_AREA_EDGE) { - force = e->y - ((GRID_SIZE * GRID_CELL_HEIGHT) - GRID_RESTRICTION_SIZE); + force = e->y - (BATTLE_AREA_HEIGHT - BATTLE_AREA_EDGE); e->dy -= force * 0.001; e->dy *= 0.95; } @@ -353,7 +350,7 @@ void drawEntities(void) { Entity *e, **candidates; int i; - + candidates = getAllEntsWithin(battle.camera.x, battle.camera.y, SCREEN_WIDTH, SCREEN_HEIGHT, NULL); /* count number of candidates for use with qsort */ diff --git a/src/battle/entities.h b/src/battle/entities.h index ee0ebe9..1383d07 100644 --- a/src/battle/entities.h +++ b/src/battle/entities.h @@ -27,14 +27,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern void blitRotated(SDL_Texture *texture, int x, int y, float angle); extern void doFighter(void); extern void doCapitalShip(void); -extern void addToGrid(Entity *e); -extern void removeFromGrid(Entity *e); extern Entity **getAllEntsWithin(int x, int y, int w, int h, Entity *ignore); extern void doRope(Entity *e); extern void drawRope(Entity *e); extern void cutRope(Entity *e); extern void drawShieldHitEffect(Entity *e); -extern void destroyGrid(void); +extern void removeFromQuadtree(Entity *e, Quadtree *root); +extern void addToQuadtree(Entity *e, Quadtree *root); extern void updateCapitalShipComponentProperties(Entity *parent); extern App app; diff --git a/src/battle/grid.c b/src/battle/grid.c deleted file mode 100644 index 25d4a5c..0000000 --- a/src/battle/grid.c +++ /dev/null @@ -1,128 +0,0 @@ -/* -Copyright (C) 2015 Parallel Realities - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "grid.h" - -static Entity *candidates[MAX_GRID_CANDIDATES]; -static void addCandidate(Entity *e); - -void addToGrid(Entity *e) -{ - GridCell *cell, *prev; - int x, y, x1, y1, x2, y2; - - x1 = (e->x - e->w / 2) / GRID_CELL_WIDTH; - y1 = (e->y - e->h / 2) / GRID_CELL_HEIGHT; - x2 = (e->x + e->w / 2) / GRID_CELL_WIDTH; - y2 = (e->y + e->h / 2) / GRID_CELL_HEIGHT; - - for (x = x1 ; x <= x2 ; x++) - { - for (y = y1 ; y <= y2 ; y++) - { - if (x >= 0 && y >= 0 && x < GRID_SIZE && y < GRID_SIZE) - { - prev = &battle.grid[x][y]; - - for (cell = battle.grid[x][y].next ; cell != NULL ; cell = cell->next) - { - prev = cell; - } - - cell = malloc(sizeof(GridCell)); - memset(cell, 0, sizeof(GridCell)); - prev->next = cell; - - cell->entity = e; - } - } - } -} - -Entity **getAllEntsWithin(int x, int y, int w, int h, Entity *ignore) -{ - GridCell *cell; - int x1, y1, x2, y2; - - memset(candidates, 0, sizeof(Entity*) * MAX_GRID_CANDIDATES); - - x1 = x / GRID_CELL_WIDTH; - y1 = y / GRID_CELL_HEIGHT; - x2 = (x + w) / GRID_CELL_WIDTH; - y2 = (y + h) / GRID_CELL_HEIGHT; - - for (x = x1 ; x <= x2 ; x++) - { - for (y = y1 ; y <= y2 ; y++) - { - if (x >= 0 && y >= 0 && x < GRID_SIZE && y < GRID_SIZE) - { - for (cell = battle.grid[x][y].next ; cell != NULL ; cell = cell->next) - { - if (cell->entity != ignore) - { - addCandidate(cell->entity); - } - } - } - } - } - - /* NULL terminate, to allow us to loop through them more easily */ - candidates[MAX_GRID_CANDIDATES - 1] = NULL; - - return candidates; -} - -static void addCandidate(Entity *e) -{ - int i = 0; - - for (i = 0 ; i < MAX_GRID_CANDIDATES ; i++) - { - if (candidates[i] == NULL || candidates[i] == e) - { - candidates[i] = e; - return; - } - } - - printf("Out of grid candidate space!"); - exit(1); -} - -void destroyGrid(void) -{ - int x, y; - GridCell *cell; - - for (x = 0 ; x < GRID_SIZE ; x++) - { - for (y = 0 ; y < GRID_SIZE ; y++) - { - while (battle.grid[x][y].next) - { - cell = battle.grid[x][y].next; - battle.grid[x][y].next = cell->next; - free(cell); - } - } - } -} diff --git a/src/battle/player.c b/src/battle/player.c index 39957d9..ba3fef1 100644 --- a/src/battle/player.c +++ b/src/battle/player.c @@ -247,14 +247,14 @@ static void handleMouse(void) if (app.mouse.button[SDL_BUTTON_X1]) { - cycleRadarZoom(); + switchGuns(); app.mouse.button[SDL_BUTTON_X1] = 0; } if (app.mouse.button[SDL_BUTTON_X2]) { - switchGuns(); + cycleRadarZoom(); app.mouse.button[SDL_BUTTON_X2] = 0; } diff --git a/src/battle/quadtree.c b/src/battle/quadtree.c new file mode 100644 index 0000000..15d4db8 --- /dev/null +++ b/src/battle/quadtree.c @@ -0,0 +1,306 @@ +/* +Copyright (C) 2015 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "quadtree.h" + +static Entity *candidates[QT_MAX_CANDIDATES]; +static int cIndex; +static int memory; + +static int getIndex(Quadtree *root, int x, int y, int w, int h); +static void removeEntity(Entity *e, Quadtree *root); +static void addCandidate(Entity *e); +static int candidatesComparator(const void *a, const void *b); +static void getAllEntsWithinNode(int x, int y, int w, int h, Entity *ignore, Quadtree *root); +static void destroyQuadtreeNode(Quadtree *root); + +void initQuadtree(Quadtree *root) +{ + Quadtree *node; + int i, w, h; + + if (root->depth == 0) + { + memory = 0; + } + + memory += sizeof(Quadtree); + + w = root->w / 2; + h = root->h / 2; + + if (root->depth + 1 < QT_MAX_DEPTH) + { + for (i = 0 ; i < 4 ; i++) + { + node = malloc(sizeof(Quadtree)); + memset(node, 0, sizeof(Quadtree)); + root->node[i] = node; + + node->depth = root->depth + 1; + + if (i == 0) + { + node->x = root->x; + node->y = root->y; + node->w = w; + node->h = h; + } + else if (i == 1) + { + node->x = root->x + w; + node->y = root->y; + node->w = w; + node->h = h; + } + else if (i == 2) + { + node->x = root->x; + node->y = root->y + h; + node->w = w; + node->h = h; + } + else + { + node->x = root->x + w; + node->y = root->y + h; + node->w = w; + node->h = h; + } + + initQuadtree(node); + } + } + + if (root->depth == 0) + { + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Quadtree memory footprint: %d bytes", memory); + } +} + +void addToQuadtree(Entity *e, Quadtree *root) +{ + int index; + + if (root->node[0]) + { + index = getIndex(root, e->x - (e->w / 2), e->y - (e->h / 2), e->w, e->h); + + if (index != -1) + { + addToQuadtree(e, root->node[index]); + return; + } + } + + if (root->numEnts < QT_MAX_ENTS) + { + root->ents[root->numEnts++] = e; + return; + } + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Couldn't add %s to quadtree - out of node ent space", e->name); +} + +static int getIndex(Quadtree *root, int x, int y, int w, int h) +{ + int index = -1; + + int verticalMidpoint = root->x + (root->w / 2); + int horizontalMidpoint = root->y + (root->h / 2); + int topQuadrant = (y < horizontalMidpoint && y + h < horizontalMidpoint); + int bottomQuadrant = (y > horizontalMidpoint); + + if (x < verticalMidpoint && x + w < verticalMidpoint) + { + if (topQuadrant) + { + index = 1; + } + else if (bottomQuadrant) + { + index = 2; + } + } + else if (x > verticalMidpoint) + { + if (topQuadrant) + { + index = 0; + } + else if (bottomQuadrant) + { + index = 3; + } + } + + return index; +} + +void removeFromQuadtree(Entity *e, Quadtree *root) +{ + int index, i; + + index = getIndex(root, e->x - (e->w / 2), e->y - (e->h / 2), e->w, e->h); + + removeEntity(e, root); + + if (root->node[0]) + { + if (index != -1) + { + removeFromQuadtree(e, root->node[index]); + } + else + { + for (i = 0; i < 4; i++) + { + removeFromQuadtree(e, root->node[i]); + } + } + } +} + +static void removeEntity(Entity *e, Quadtree *root) +{ + int i, n; + + n = root->numEnts; + + for (i = 0 ; i < QT_MAX_ENTS ; i++) + { + if (root->ents[i] == e) + { + root->ents[i] = NULL; + root->numEnts--; + } + } + + qsort(root->ents, n, sizeof(Entity*), candidatesComparator); +} + +Entity **getAllEntsWithin(int x, int y, int w, int h, Entity *ignore) +{ + cIndex = 0; + memset(candidates, 0, sizeof(Entity*) * QT_MAX_CANDIDATES); + + getAllEntsWithinNode(x, y, w, h, ignore, &battle.quadtree); + + /* NULL terminate, to allow us to loop through them more easily */ + candidates[QT_MAX_CANDIDATES - 1] = NULL; + + return candidates; +} + +static void getAllEntsWithinNode(int x, int y, int w, int h, Entity *ignore, Quadtree *root) +{ + Quadtree *node; + int index, i; + + for (i = 0 ; i < root->numEnts ; i++) + { + addCandidate(root->ents[i]); + } + + index = getIndex(root, x, y, w, h); + + if (root->node[0]) + { + if (index != -1) + { + node = root->node[index]; + + getAllEntsWithinNode(node->x, node->y, node->w, node->h, ignore, node); + } + else + { + for (i = 0; i < 4; i++) + { + node = root->node[i]; + + getAllEntsWithinNode(node->x, node->y, node->w, node->h, ignore, node); + } + } + } +} + +static void addCandidate(Entity *e) +{ + int i; + + for (i = 0 ; i <= cIndex ; i++) + { + /* already added */ + if (candidates[i] == e) + { + return; + } + + if (!candidates[i]) + { + candidates[cIndex++] = e; + return; + } + } + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "Out of quadtree candidate space"); + exit(1); +} + +void destroyQuadtree(void) +{ + destroyQuadtreeNode(&battle.quadtree); +} + +static void destroyQuadtreeNode(Quadtree *root) +{ + int i; + + if (root->node[0]) + { + for (i = 0 ; i < 4 ; i++) + { + destroyQuadtreeNode(root->node[i]); + + free(root->node[i]); + + root->node[i] = NULL; + } + } +} + +static int candidatesComparator(const void *a, const void *b) +{ + Entity *e1 = *((Entity**)a); + Entity *e2 = *((Entity**)b); + + if (!e1) + { + return 1; + } + else if (!e2) + { + return -1; + } + else + { + return 0; + } +} diff --git a/src/battle/grid.h b/src/battle/quadtree.h similarity index 100% rename from src/battle/grid.h rename to src/battle/quadtree.h diff --git a/src/battle/radar.c b/src/battle/radar.c index a2c1113..2b3c383 100644 --- a/src/battle/radar.c +++ b/src/battle/radar.c @@ -90,8 +90,8 @@ void drawRadarRangeWarning(void) { int x, y, leaving; - x = (int)player->x / GRID_CELL_WIDTH; - y = (int)player->y / GRID_CELL_HEIGHT; + x = (int)player->x / (SCREEN_WIDTH / 2); + y = (int)player->y / (SCREEN_HEIGHT / 2); leaving = 0; if (x <= 2 && player->dx < 0) @@ -108,14 +108,14 @@ void drawRadarRangeWarning(void) leaving = 1; } - if (x >= GRID_SIZE - 2 && player->dx > 0) + if (x >= (SCREEN_WIDTH / 2) - 2 && player->dx > 0) { blitRotated(radarWarningTexture, SCREEN_WIDTH - 85, SCREEN_HEIGHT - 85, 90); leaving = 1; } - if (y >= GRID_SIZE - 2 && player->dy > 0) + if (y >= (SCREEN_HEIGHT / 2) - 2 && player->dy > 0) { blitRotated(radarWarningTexture, SCREEN_WIDTH - 85, SCREEN_HEIGHT - 85, 180); diff --git a/src/defs.h b/src/defs.h index aee7edf..cbe47e7 100644 --- a/src/defs.h +++ b/src/defs.h @@ -60,11 +60,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MAX_FIGHTER_GUNS 12 #define MAX_TARGET_RANGE 65536 -#define GRID_CELL_WIDTH 640 -#define GRID_CELL_HEIGHT 360 -#define GRID_SIZE 50 -#define MAX_GRID_CANDIDATES 256 -#define GRID_RESTRICTION_SIZE 250 +#define QT_MAX_DEPTH 5 +#define QT_MAX_ENTS 96 +#define QT_MAX_CANDIDATES 256 + +#define BATTLE_AREA_CELLS 50 +#define BATTLE_AREA_WIDTH (640 * BATTLE_AREA_CELLS) +#define BATTLE_AREA_HEIGHT (360 * BATTLE_AREA_CELLS) +#define BATTLE_AREA_EDGE 250 #define BF_NONE 0 #define BF_ENGINE (2 << 0) diff --git a/src/galaxy/mission.c b/src/galaxy/mission.c index 705c35c..f8b7453 100644 --- a/src/galaxy/mission.c +++ b/src/galaxy/mission.c @@ -192,13 +192,13 @@ static void loadPlayer(cJSON *node) side = lookup(cJSON_GetObjectItem(node, "side")->valuestring); player = spawnFighter(type, 0, 0, side); - player->x = (GRID_SIZE * GRID_CELL_WIDTH) / 2; - player->y = (GRID_SIZE * GRID_CELL_HEIGHT) / 2; + player->x = BATTLE_AREA_WIDTH / 2; + player->y = BATTLE_AREA_HEIGHT / 2; if (cJSON_GetObjectItem(node, "x")) { - player->x = (cJSON_GetObjectItem(node, "x")->valueint * GRID_CELL_WIDTH); - player->y = (cJSON_GetObjectItem(node, "y")->valueint * GRID_CELL_HEIGHT); + player->x = (cJSON_GetObjectItem(node, "x")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_WIDTH; + player->y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT; } if (strcmp(type, "Tug") == 0) @@ -237,8 +237,8 @@ static void loadFighters(cJSON *node) types = toTypeArray(cJSON_GetObjectItem(node, "types")->valuestring, &numTypes); side = lookup(cJSON_GetObjectItem(node, "side")->valuestring); - x = cJSON_GetObjectItem(node, "x")->valuedouble * GRID_CELL_WIDTH; - y = cJSON_GetObjectItem(node, "y")->valuedouble * GRID_CELL_HEIGHT; + x = (cJSON_GetObjectItem(node, "x")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_WIDTH; + y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT; if (cJSON_GetObjectItem(node, "name")) { @@ -364,8 +364,8 @@ static void loadCapitalShips(cJSON *node) types = toTypeArray(cJSON_GetObjectItem(node, "types")->valuestring, &numTypes); side = lookup(cJSON_GetObjectItem(node, "side")->valuestring); - x = cJSON_GetObjectItem(node, "x")->valuedouble * GRID_CELL_WIDTH; - y = cJSON_GetObjectItem(node, "y")->valuedouble * GRID_CELL_HEIGHT; + x = (cJSON_GetObjectItem(node, "x")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_WIDTH; + y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT; if (cJSON_GetObjectItem(node, "name")) { @@ -465,8 +465,8 @@ static void loadEntities(cJSON *node) { e = NULL; type = lookup(cJSON_GetObjectItem(node, "type")->valuestring); - x = cJSON_GetObjectItem(node, "x")->valuedouble * GRID_CELL_WIDTH; - y = cJSON_GetObjectItem(node, "y")->valuedouble * GRID_CELL_HEIGHT; + x = (cJSON_GetObjectItem(node, "x")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_WIDTH; + y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT; name = NULL; groupName = NULL; number = 1; @@ -563,8 +563,8 @@ static void loadItems(cJSON *node) while (node) { type = cJSON_GetObjectItem(node, "type")->valuestring; - x = cJSON_GetObjectItem(node, "x")->valuedouble * GRID_CELL_WIDTH; - y = cJSON_GetObjectItem(node, "y")->valuedouble * GRID_CELL_HEIGHT; + x = (cJSON_GetObjectItem(node, "x")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_WIDTH; + y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT; name = NULL; groupName = NULL; number = 1; @@ -665,8 +665,9 @@ static void loadLocations(cJSON *node) battle.locationTail = l; STRNCPY(l->name, cJSON_GetObjectItem(node, "name")->valuestring, MAX_NAME_LENGTH); - l->x = cJSON_GetObjectItem(node, "x")->valueint * GRID_CELL_WIDTH; - l->y = cJSON_GetObjectItem(node, "y")->valueint * GRID_CELL_HEIGHT; + l->x = (cJSON_GetObjectItem(node, "x")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_WIDTH; + l->y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT; + l->size = cJSON_GetObjectItem(node, "size")->valueint; if (cJSON_GetObjectItem(node, "active")) @@ -674,8 +675,8 @@ static void loadLocations(cJSON *node) active = cJSON_GetObjectItem(node, "active")->valueint; } - l->x += (GRID_CELL_WIDTH / 2); - l->y += (GRID_CELL_HEIGHT / 2); + l->x += (SCREEN_WIDTH / 2); + l->y += (SCREEN_HEIGHT / 2); l->active = active; node = node->next; diff --git a/src/structs.h b/src/structs.h index ce6753a..3dfc49b 100644 --- a/src/structs.h +++ b/src/structs.h @@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. typedef struct Texture Texture; typedef struct Lookup Lookup; typedef struct Weapon Weapon; +typedef struct Quadtree Quadtree; typedef struct Entity Entity; typedef struct Bullet Bullet; typedef struct Debris Debris; @@ -263,9 +264,12 @@ struct StarSystem { StarSystem *next; }; -struct GridCell { - Entity *entity; - GridCell *next; +struct Quadtree { + int depth; + int x, y, w, h; + Entity *ents[QT_MAX_ENTS]; + int numEnts; + Quadtree *node[4]; }; typedef struct { @@ -298,7 +302,7 @@ typedef struct { Location locationHead, *locationTail; struct cJSON *missionJSON; unsigned int stats[STAT_MAX]; - GridCell grid[GRID_SIZE][GRID_SIZE]; + Quadtree quadtree; } Battle; struct ScriptRunner {