1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2024-12-03 00:15:46 +00:00
Aquaria/Aquaria/FlockEntity.cpp

155 lines
3.6 KiB
C++

/*
Copyright (C) 2007, 2010 - Bit-Blot
This file is part of Aquaria.
Aquaria 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 "FlockEntity.h"
const int DEFAULT_MAX_FLOCKS = 20; // Will be increased as needed
std::vector<Flock*> flocks(DEFAULT_MAX_FLOCKS);
FlockEntity::FlockEntity() : CollideEntity()
{
flockType = FLOCK_FISH;
flock = 0;
nextInFlock = prevInFlock = 0;
nearestFlockMate = 0;
nearestDistance = HUGE_VALF;
angle = 0;
collideRadius = 8;
}
void FlockEntity::addToFlock(int id)
{
if (id >= flocks.size())
{
int curSize = flocks.size();
flocks.resize(id+1);
for (int i = curSize; i < id+1; i++)
flocks[i] = 0;
}
if (!flocks[id])
{
flocks[id] = new Flock(id);
}
flock = flocks[id];
nextInFlock = flock->firstEntity;
prevInFlock = 0;
if (flock->firstEntity)
flock->firstEntity->prevInFlock = this;
flock->firstEntity = this;
nearestFlockMate = 0;
nearestDistance = HUGE_VALF;
int numEntities = 1;
for (FlockEntity *e = nextInFlock; e; e = e->nextInFlock)
{
numEntities++;
const float distance = (e->position - position).getLength2D();
if (distance < nearestDistance)
{
nearestFlockMate = e;
nearestDistance = distance;
}
}
if (numEntities == 1)
{
flock->center = position;
flock->heading = vel;
}
else
{
flock->center = (flock->center*(numEntities-1) + position) / numEntities;
flock->heading = (flock->heading*(numEntities-1) + vel) / numEntities;
}
}
void FlockEntity::removeFromFlock()
{
if (flock)
{
if (nextInFlock)
nextInFlock->prevInFlock = prevInFlock;
if (prevInFlock)
prevInFlock->nextInFlock = nextInFlock;
else
flock->firstEntity = nextInFlock;
if (!flock->firstEntity)
{
flocks[flock->flockID] = 0;
delete flock;
}
}
flock = 0;
nextInFlock = prevInFlock = 0;
nearestFlockMate = 0;
nearestDistance = HUGE_VALF;
}
void FlockEntity::destroy()
{
removeFromFlock();
CollideEntity::destroy();
}
void FlockEntity::updateFlockData(void)
{
for (int flockID = 0; flockID < flocks.size(); flockID++)
{
Flock *flock = flocks[flockID];
if (flock)
{
flock->center = Vector(0,0,0);
flock->heading = Vector(0,0,0);
int numEntities = 0;
for (FlockEntity *e = flock->firstEntity; e; e = e->nextInFlock)
{
flock->center += e->position;
flock->heading += e->vel;
e->nearestFlockMate = 0;
e->nearestDistance = HUGE_VALF;
for (FlockEntity *e2 = flock->firstEntity; e2 != e; e2 = e2->nextInFlock)
{
const float distanceSqr = (e2->position - e->position).getSquaredLength2D();
if (distanceSqr < e->nearestDistance)
{
e->nearestFlockMate = e2;
// Record the square for now (we'll sqrt it later)
e->nearestDistance = distanceSqr;
}
if (distanceSqr < e2->nearestDistance)
{
e2->nearestFlockMate = e;
e2->nearestDistance = distanceSqr;
}
}
numEntities++;
}
for (FlockEntity *e = flock->firstEntity; e; e = e->nextInFlock)
{
e->nearestDistance = sqrtf(e->nearestDistance);
}
flock->center /= numEntities;
flock->heading /= numEntities;
}
}
}