⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aitankcontroller.cpp.svn-base

📁 坦克大战游戏完整全套源代码
💻 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 + -