loshandler.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 630 行 · 第 1/2 页
CPP
630 行
#include "StdAfx.h"
// LosHandler.cpp: implementation of the CLosHandler class.
//
//////////////////////////////////////////////////////////////////////
#include "LosHandler.h"
#include "Sim/Units/Unit.h"
#include <list>
#include "Map/ReadMap.h"
#include "TimeProfiler.h"
#include "LogOutput.h"
#include "Platform/errorhandler.h"
#include "Sim/Misc/SensorHandler.h"
#include "creg/STL_Deque.h"
#include "creg/STL_List.h"
#include "mmgr.h"
CR_BIND(LosInstance, );
CR_BIND(CLosHandler, );
CR_BIND(CLosHandler::DelayedInstance, );
CR_BIND(CLosHandler::CPoint, );
CR_REG_METADATA(LosInstance,(
// CR_MEMBER(losSquares),
CR_MEMBER(losSize),
CR_MEMBER(airLosSize),
CR_MEMBER(refCount),
CR_MEMBER(allyteam),
CR_MEMBER(baseX),
CR_MEMBER(baseY),
CR_MEMBER(baseSquare),
CR_MEMBER(baseAirSquare),
CR_MEMBER(hashNum),
CR_MEMBER(baseHeight),
CR_MEMBER(toBeDeleted),
CR_RESERVED(16)
));
void CLosHandler::PostLoad()
{
for (int a = 0; a < 2309; ++a)
for (std::list<LosInstance*>::iterator li = instanceHash[a].begin(); li != instanceHash[a].end(); ++li)
if ((*li)->refCount) {
if ((*li)->baseX-(*li)->losSize<0 || (*li)->baseX+(*li)->losSize>=losSizeX ||
(*li)->baseY-(*li)->losSize<0 || (*li)->baseY+(*li)->losSize>=losSizeY)
SafeLosAdd(*li,(*li)->baseX,(*li)->baseY);
else
LosAdd(*li);
}
}
CR_REG_METADATA(CLosHandler,(
CR_MEMBER(losMipLevel),
CR_MEMBER(airMipLevel),
CR_MEMBER(invLosDiv),
CR_MEMBER(invAirDiv),
CR_MEMBER(airSizeX),
CR_MEMBER(airSizeY),
CR_MEMBER(losSizeX),
CR_MEMBER(losSizeY),
CR_MEMBER(instanceHash),
CR_MEMBER(toBeDeleted),
CR_MEMBER(delayQue),
// CR_MEMBER(Points),
CR_MEMBER(terrainHeight),
// CR_MEMBER(lostables)
CR_RESERVED(32),
CR_POSTLOAD(PostLoad)
));
CR_REG_METADATA_SUB(CLosHandler,DelayedInstance,(
CR_MEMBER(instance),
CR_MEMBER(timeoutTime)));
/*
CR_REG_METADATA_SUB(CLosHandler,CPoint,(
CR_MEMBER(x),
CR_MEMBER(y)));
*/
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
using namespace std;
CLosHandler* loshandler;
CLosHandler::CLosHandler()
{
losMipLevel = sensorHandler->losMipLevel;
airMipLevel = sensorHandler->airMipLevel;
airSizeX = std::max(1, gs->mapx >> airMipLevel);
airSizeY = std::max(1, gs->mapy >> airMipLevel);
losSizeX = std::max(1, gs->mapx >> losMipLevel);
losSizeY = std::max(1, gs->mapy >> losMipLevel);
invLosDiv = 1 / ((float)SQUARE_SIZE * (1 << losMipLevel));
invAirDiv = 1 / ((float)SQUARE_SIZE * (1 << airMipLevel));
for(int a=0;a<gs->activeAllyTeams;++a){
losMap[a].resize(losSizeX*losSizeY,0);
airLosMap[a].resize(airSizeX*airSizeY,0);
}
for(int a=1;a<=MAX_LOS_TABLE;++a)
OutputTable(a);
for(int a=0;a<256;++a)
terrainHeight[a]=-15;
terrainHeight[6]=30;
terrainHeight[7]=30;
terrainHeight[8]=30;
terrainHeight[26]=30;
terrainHeight[27]=30;
terrainHeight[28]=30;
terrainHeight[29]=30;
terrainHeight[31]=30;
for(int a=32;a<64;++a)
terrainHeight[a]=10;
}
CLosHandler::~CLosHandler()
{
std::list<LosInstance*>::iterator li;
for(int a=0;a<2309;++a){
for(li=instanceHash[a].begin();li!=instanceHash[a].end();++li){
LosInstance* i = *li;
i->_DestructInstance(i);
mempool.Free(i, sizeof(LosInstance));
}
}
}
void CLosHandler::MoveUnit(CUnit *unit,bool redoCurrent)
{
SCOPED_TIMER("Los");
float3 losPos=unit->pos;
losPos.CheckInBounds();
const int allyteam=unit->allyteam;
unit->lastLosUpdate=gs->frameNum;
if(unit->losRadius<=0){
return;
}
const int xmap=(int)(losPos.x*invLosDiv);
const int ymap=(int)(losPos.z*invLosDiv);
const int baseSquare=max(0,min(losSizeY-1,(ymap)))*losSizeX + max(0,min(losSizeX-1,xmap));
const int baseX=max(0,min(losSizeX-1,xmap));
const int baseY=max(0,min(losSizeY-1,(ymap)));
LosInstance* instance;
if(redoCurrent){
if(!unit->los){
return;
}
instance=unit->los;
CleanupInstance(instance);
instance->losSquares.clear();
instance->baseX=baseX;
instance->baseY=baseY;
instance->baseSquare=baseSquare; //this could be a problem if several units are sharing the same instance
int baseAirSquare=max(0,min(airSizeY-1,((int)(losPos.z*invAirDiv))))*airSizeX + max(0,min(airSizeX-1,(int)(losPos.x*invAirDiv)));
instance->baseAirSquare=baseAirSquare;
} else {
if(unit->los && unit->los->baseSquare==baseSquare){
return;
}
FreeInstance(unit->los);
int hash=GetHashNum(unit);
std::list<LosInstance*>::iterator lii;
for(lii=instanceHash[hash].begin();lii!=instanceHash[hash].end();++lii){
if((*lii)->baseSquare==baseSquare && (*lii)->losSize==unit->losRadius && (*lii)->airLosSize==unit->airLosRadius && (*lii)->baseHeight==unit->losHeight && (*lii)->allyteam==allyteam){
AllocInstance(*lii);
unit->los=*lii;
return;
}
}
int baseAirSquare=max(0,min(airSizeY-1,((int)(losPos.z*invAirDiv))))*airSizeX + max(0,min(airSizeX-1,(int)(losPos.x*invAirDiv)));
instance=new(mempool.Alloc(sizeof(LosInstance))) LosInstance(unit->losRadius,allyteam,baseX,baseY,baseSquare,baseAirSquare,hash,unit->losHeight,unit->airLosRadius);
instanceHash[hash].push_back(instance);
unit->los=instance;
}
if(xmap-unit->losRadius<0 || xmap+unit->losRadius>=losSizeX || ymap-unit->losRadius<0 || ymap+unit->losRadius>=losSizeY)
SafeLosAdd(instance,xmap,ymap);
else
LosAdd(instance);
}
void CLosHandler::LosAdd(LosInstance* instance)
{
assert(instance);
assert(instance->allyteam < gs->activeAllyTeams);
assert(instance->allyteam >= 0);
const int allyteam=instance->allyteam;
const int mapSquare=instance->baseSquare;
LosAddAir(instance);
int tablenum=instance->losSize;
if(tablenum>MAX_LOS_TABLE){
tablenum=MAX_LOS_TABLE;
}
LosTable& table=lostables[tablenum-1];
instance->losSquares.push_back(mapSquare);
losMap[allyteam][mapSquare]++;
for(LosTable::iterator li=table.begin();li!=table.end();++li){
LosLine& line=*li;
const float baseHeight=readmap->mipHeightmap[losMipLevel][mapSquare]+instance->baseHeight-15;
float maxAng1=-1000;
float maxAng2=-1000;
float maxAng3=-1000;
float maxAng4=-1000;
float r=1;
for(LosLine::iterator linei=line.begin();linei!=line.end();++linei){
float invR=1.0f/r;
int square=mapSquare+linei->x+linei->y*losSizeX;
float dh=readmap->mipHeightmap[losMipLevel][square]-baseHeight;
float ang=dh*invR;
if(ang>maxAng1){
instance->losSquares.push_back(square);
losMap[allyteam][square]++;
}
dh+=terrainHeight[0];
ang=dh*invR;
if(ang>maxAng1){
maxAng1=ang;
}
square=mapSquare-linei->x-linei->y*losSizeX;
dh=readmap->mipHeightmap[losMipLevel][square]-baseHeight;
ang=dh*invR;
if(ang>maxAng2){
instance->losSquares.push_back(square);
losMap[allyteam][square]++;
}
dh+=terrainHeight[0];
ang=dh*invR;
if(ang>maxAng2){
maxAng2=ang;
}
square=mapSquare-linei->x*losSizeX+linei->y;
dh=readmap->mipHeightmap[losMipLevel][square]-baseHeight;
ang=dh*invR;
if(ang>maxAng3){
instance->losSquares.push_back(square);
losMap[allyteam][square]++;
}
dh+=terrainHeight[0];
ang=dh*invR;
if(ang>maxAng3){
maxAng3=ang;
}
square=mapSquare+linei->x*losSizeX-linei->y;
dh=readmap->mipHeightmap[losMipLevel][square]-baseHeight;
ang=dh*invR;
if(ang>maxAng4){
instance->losSquares.push_back(square);
losMap[allyteam][square]++;
}
dh+=terrainHeight[0];
ang=dh*invR;
if(ang>maxAng4){
maxAng4=ang;
}
r++;
}
}
}
void CLosHandler::SafeLosAdd(LosInstance* instance,int xm,int ym)
{
int xmap=xm;
int ymap=ym;
int allyteam=instance->allyteam;
int mapSquare=instance->baseSquare;
LosAddAir(instance);
int tablenum=instance->losSize;
if(tablenum>MAX_LOS_TABLE){
tablenum=MAX_LOS_TABLE;
}
LosTable& table=lostables[tablenum-1];
for(LosTable::iterator li=table.begin();li!=table.end();++li){
LosLine& line=*li;
float baseHeight=readmap->mipHeightmap[losMipLevel][mapSquare]+instance->baseHeight-15;
float maxAng1=-1000;
float maxAng2=-1000;
float maxAng3=-1000;
float maxAng4=-1000;
float r=1;
instance->losSquares.push_back(mapSquare);
losMap[allyteam][mapSquare]++;
for(LosLine::iterator linei=line.begin();linei!=line.end();++linei){
if(xmap+linei->x<losSizeX && ymap+linei->y<losSizeY){
int square=mapSquare+linei->x+linei->y*losSizeX;
float dh=readmap->mipHeightmap[losMipLevel][square]-baseHeight;
float ang=dh/r;
if(ang>maxAng1){
instance->losSquares.push_back(square);
losMap[allyteam][square]++;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?