Start of replacing grid with quadtree.
This commit is contained in:
parent
7337460853
commit
6b1e62dd38
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
13
src/defs.h
13
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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue