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 + -
显示快捷键?