📄 aitankcontroller.cpp.svn-base
字号:
#include "common/collisionSpace.h"
#include "common/entityManager.h"
#include "gameDef.h"
#include "aiTankController.h"
#include "tank.h"
#include "map.h"
class AiSightEntityFilter : public EntityFilter
{
public:
AiSightEntityFilter(const Point2f &_pos, const Entity &_entity) : pos(_pos), entity(_entity)
{
boundingBox.leftTop = pos + Point2f(-300, -300);
boundingBox.rightBottom = pos + Point2f(300, 300);
}
const Rectf &getBoundingBox() const
{
return boundingBox;
}
bool filtrate(Entity &e) const
{
switch(e.getTypeId())
{
case ETI_Tank:
if (&e == &entity)
break;
// no break here
case ETI_Item:
{
Point2f ePos;
if (e.getStatus(Entity::ESI_Position, &ePos) && (ePos - pos).Length() < 300)
{
return true;
}
}
break;
}
return false;
}
protected:
Rectf boundingBox;
Point2f pos;
const Entity &entity;
};
AiTankController::AiTankController()
{
bForward = false;
bLeft = false;
bRight = false;
bBackward = false;
bFire = false;
bShoot = false;
bCheckMoveTo = false;
}
AiTankController::~AiTankController()
{
}
void AiTankController::attacheMap(Map *map)
{
((iAttacheeEntity*)map->getEntityInterface(Map::EII_QueryEntity))->attach(mapAttacher);
}
void AiTankController::scanAround()
{
if (!isAttached())
return;
vector<Entity *> entities;
Point2f posTank;
Entity &tankEntity = getTankEntity();
if (tankEntity.getStatus(Entity::ESI_Position, &posTank))
{
EntityManager::getSingleton().getEntities(entities, AiSightEntityFilter(posTank, tankEntity));
Point2f aimPos;
float aimDistance = 1000.f;
for (size_t i = 0; i < entities.size(); i++)
{
Entity *e = entities[i];
switch(e->getTypeId())
{
case ETI_Tank:
{
Point2f ePos;
if (e->getStatus(Entity::ESI_Position, &ePos))
{
float distance = (ePos - posTank).Length();
if (distance < aimDistance)
{
aimDistance = distance;
aimPos = ePos;
}
}
}
break;
case ETI_Item:
{
Point2f ePos;
if (e->getStatus(Entity::ESI_Position, &ePos))
{
Operate moveTo(Operate::CI_MoveTo);
if (findPathTo(ePos, moveTo.wayPoints))
{
operates.push(moveTo);
return;
}
else
{
// just give up the item
// moveTo(ePos);
}
}
}
break;
}
}
if (aimDistance < 1000.0f)
{
aimTo(aimPos);
}
}
}
void AiTankController::think()
{
if (!isAttached())
return;
// check for commands list
// query environments (for updating covers and enemies)
// determine the currently most important task(to track enemies or to escape from the enemies or go to the nearest supply zone, etc.)
// generate path
// attack or rest
int r = rand() % 1000;
if (r < 5)
{
sendCommand(Tank::TCI_Fire, (void *)(bFire = !bFire));
}
else if (r < 20)
{
sendCommand(Tank::TCI_Shoot, (void *)(bShoot = !bShoot));
}
if (!operates.empty())
{
Operate &op = operates.back();
switch(op.commond)
{
case Operate::CI_MoveTo:
if (!op.wayPoints.empty())
{
Point2f lastPos = moveToPos;
for (list<Point2f>::iterator ip = op.wayPoints.begin(); ip != op.wayPoints.end(); ++ip)
{
RenderQueue::getSingleton().render(*ip, lastPos, ARGB(255, 128, 0, 0));
lastPos = *ip;
}
}
break;
}
}
if (bCheckMoveTo)
{
stepMoveTo();
}
else if (!operates.empty())
{
Operate &op = operates.front();
switch(op.commond)
{
case Operate::CI_MoveTo:
if (!op.wayPoints.empty())
{
Point2f pos = op.wayPoints.front();
op.wayPoints.pop_front();
if (op.wayPoints.empty())
moveTo(pos, pos);
else
moveTo(pos, op.wayPoints.front());
}
else
{
operates.pop();
}
break;
}
}
else
{
/*
if (r < 10)
{
sendCommand(Tank::TCI_TurnLeft, (void *)(bLeft = !bLeft));
}
else if (r < 20)
{
sendCommand(Tank::TCI_TurnRight, (void *)(bRight = !bRight));
}
else if (r < 30)
{
sendCommand(Tank::TCI_Forward, (void *)(bForward = !bForward));
}
else if (r < 60)
{
aimTo(Point2f(float(rand() % 800), float(rand() % 600)));
}
else if (r < 65)
{
if (isAttached())
{
Point2f posTank;
Entity &e = entity->getEntity();
if (e.getStatus(Entity::ESI_Position, &posTank))
{
moveTo(posTank + Point2f(rand() % 201 - 100.f, rand() % 201 - 100.f));
}
}
}
else if (r < 70)
*/
if (r > 995)
{
scanAround();
}
}
}
void AiTankController::goTo(const Point2f &pos) // findPath and go
{
if (!isAttached())
return;
Operate moveTo(Operate::CI_MoveTo);
if (findPathTo(pos, moveTo.wayPoints))
{
operates.push(moveTo);
}
}
void AiTankController::resetOperates()
{
bCheckMoveTo = false;
while(!operates.empty())
operates.pop();
}
void AiTankController::moveTo(const Point2f &pos, const Point2f &nextPos)
{
if (!isAttached())
return;
turnTo(pos);
bCheckMoveTo = true;
moveToPos = pos;
nextMoveToPos = nextPos;
}
void AiTankController::turnTo(const Point2f &pos)
{
sendCommand(Tank::TCI_Turn, &pos);
}
void AiTankController::aimTo(const Point2f &pos)
{
sendCommand(Tank::TCI_Aim, &pos);
}
void AiTankController::stepMoveTo()
{
if (!isAttached())
{
bCheckMoveTo = false;
return;
}
Point2f posTank;
float orientionTank;
Entity &e = entity->getEntity();
if (e.getStatus(Entity::ESI_Position, &posTank) &&
e.getStatus(Entity::ESI_Orientation, &orientionTank))
{
//#ifndef NDEBUG
RenderQueue::getSingleton().render(moveToPos, posTank, ARGB(255, 0, 0, 0));
//#endif
Point2f dir = moveToPos - posTank;
float len = dir.Length();
float len2 = (nextMoveToPos - posTank).Length();
if (len < 10 || len > len2)
{
bCheckMoveTo = false;
bForward = false;
sendCommand(Tank::TCI_Forward, (void *)bForward);
return;
}
dir.Normalize();
if (fabs(dir ^ Point2f(cos(orientionTank), sin(orientionTank))) < 0.3f)
{
if (!bForward)
{
bForward = true;
sendCommand(Tank::TCI_Forward, (void *)bForward);
}
}
else
{
float lerpValue = (float)rand() / RAND_MAX;
lerpValue *= lerpValue;
turnTo(moveToPos);//lerp(moveToPos, nextMoveToPos, lerpValue));
if (bForward)
{
bForward = false;
sendCommand(Tank::TCI_Forward, (void *)bForward);
}
}
}
else
{
bCheckMoveTo = false;
}
}
bool AiTankController::findPathTo(const Point2f &pos, list<Point2f> &result)
{
// get map info,
// generate rough path to pos
// bla bla bla
Point2f posTank;
Entity &tankEntity = getTankEntity();
if (tankEntity.getStatus(Entity::ESI_Position, &posTank))
{
if (mapAttacher.isAttached())
{
const Map *map = (const Map *)mapAttacher.getEntity();
if (map)
{
map->findPath(result, posTank, pos);
return true;
}
}
}
return false;
}
void AiTankController::OnDettach(iAttacheeEntity &entity)
{
entity;
while(!operates.empty())
operates.pop();
bCheckMoveTo = false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -