ICT290 / src / scene / AIController / AITest.cpp
AITest.cpp
Raw
#include "AITest.h"
#include <random>

//#include <BotEngine.h>
//#include <BasicEntity.h>
#include "Attacks/TestProjectile.h"
#include "Goals/Goal.h"
#include "SteeringBehaviours.h"

GameWorld* AITest::world;

glm::vec3 AITest::mouseTarget(0.0);

void AITest::drawTarget() {
    // grey target
    glColor3f(0.5, 0.5, 0.5);
    glBegin(GL_LINE_LOOP);
    glVertex3d(mouseTarget.x + 0.2, mouseTarget.y, mouseTarget.z);
    glVertex3d(mouseTarget.x - 0.2, mouseTarget.y, mouseTarget.z);
    glEnd();
    glBegin(GL_LINE_LOOP);
    glVertex3d(mouseTarget.x, mouseTarget.y, mouseTarget.z + 0.2);
    glVertex3d(mouseTarget.x, mouseTarget.y, mouseTarget.z - 0.2);
    glEnd();
}

void AITest::loadPlayer(int health) {
    auto playerBot = new Vehicle((AITest::world),
                                 glm::vec2(28.0, 28.0),
                                 glm::vec2(0.01, 0.01),
                                 0.2f,
                                 glm::vec2(1.0, 0.0),
                                 glm::vec2(0.01f, 0.0f),
                                 0.1f,
                                 2.5f,
                                 1.0f,
                                 1.0f,
                                 health);
    playerBot->takePossession();
    world->m_Vehicles.push_back(playerBot);
}

void AITest::loadBots(float spawnPercent, int seed) {
    auto& rooms = world->currentLevel.getRooms();
    bool spawn{true};
    for (std::size_t i = 0; i < world->currentLevel.getNumOfRooms(); ++i) {
        if (spawn) {
            spawn = false;
            continue;
        }
        auto& room = rooms[i];
        // percent of a rooms area
        auto numberOfBots = (std::size_t)((room.max.x - room.min.x)
                                          * (room.max.y - room.min.y)
                                          * spawnPercent);

        for (std::size_t j = 0; j < numberOfBots; ++j) {
            auto bot = new Vehicle((AITest::world),
                                   world->currentLevel.getRandomSpawn(room,
                                                                      seed++),
                                   glm::vec2(0.01, 0.01),
                                   0.2f,
                                   glm::vec2(1.0, 0.0),
                                   glm::vec2(0.01f, 0.0f),
                                   0.1f,
                                   2.5f,
                                   1.0f,
                                   0.1f,
                                   100);
            world->m_Vehicles.push_back(bot);
        }
    }
}

void AITest::setAllBehaviours(int behaviour) {
    switch (behaviour) {
        case 1: {
            if (world->m_Vehicles.front()->getSteering()->isArriveOn()) {
                world->m_Vehicles.front()->getSteering()->ArriveOff();
                std::cout << "ArriveOff" << std::endl;
            } else {
                world->m_Vehicles.front()->getSteering()->ArriveOn();
                std::cout << "ArriveOn" << std::endl;
            }
            break;
        }
        case 2: {
            if (world->m_Vehicles.front()->getSteering()->isSeekOn()) {
                world->m_Vehicles.front()->getSteering()->SeekOff();
                std::cout << "SeekOff" << std::endl;
            } else {
                world->m_Vehicles.front()->getSteering()->SeekOn();
                std::cout << "SeekOn" << std::endl;
            }
            break;
        }
        case 3: {
            std::cout << "size of vehicles vec = " << world->m_Vehicles.size()
                      << std::endl;
            for (auto vehicle : world->m_Vehicles) {
                if (vehicle->getSteering()->isWallAvoidanceOn()) {
                    vehicle->getSteering()->WallAvoidanceOff();
                    std::cout << "WallAvoidanceOff" << std::endl;
                } else {
                    vehicle->getSteering()->WallAvoidanceOn();
                    std::cout << "WallAvoidanceOn" << std::endl;
                }
            }
            break;
        }
        case 4: {
            for (auto vehicle : world->m_Vehicles) {
                if (vehicle->getSteering()->isObstacleAvoidanceOn()) {
                    vehicle->getSteering()->ObstacleAvoidanceOff();
                    std::cout << "ObstacleAvoidanceOff" << std::endl;
                } else {
                    vehicle->getSteering()->ObstacleAvoidanceOn();
                    std::cout << "ObstacleAvoidanceOn" << std::endl;
                }
            }
            break;
        }
        case 5: {
            for (auto vehicle : world->m_Vehicles) {
                if (vehicle->getSteering()->isWanderOn()) {
                    vehicle->getSteering()->WanderOff();
                    std::cout << "WanderOff" << std::endl;
                } else {
                    vehicle->getSteering()->WanderOn();
                    std::cout << "WanderOn" << std::endl;
                }
            }
            break;
        }
        default:
            break;
    }
}

void AITest::spawnDefaultBot() {
    if (!world->currentLevel.getRooms().empty()) {
        auto bot = new Vehicle((AITest::world),
                               world->currentLevel.getRandomSpawn(),
                               glm::vec2(0.01, 0.01),
                               0.2f,
                               glm::vec2(1.0, 0.0),
                               glm::vec2(0.01f, 0.0f),
                               0.1f,
                               2.5f,
                               1.0f,
                               0.1f,
                               100);
        world->m_Vehicles.push_back(bot);
    }
}

void AITest::loadObstacles() {
    glm::vec3 scale(0.15f);
    glm::vec2 posOne(0.333f, 0.333f);
    glm::vec2 posTwo(0.666f, 0.666f);
}

void AITest::botEngineInit() {
    // addWalls();

    // loadBots();
    //  loadObstacles();
}

void AITest::Init(GameWorld* GW) {
    glPushAttrib(GL_CURRENT_BIT);
    world = GW;
    // botEngineInit();
    glLineWidth(5.0);
    glPopAttrib();
}

void AITest::drawWalls() {
    glLineWidth(50.0);
    glColor3f(1.0, 1.0, 1.0);
    for (auto& wall : world->currentLevel.getAllWalls()) {
        glPushMatrix();
        glBegin(GL_LINE_LOOP);
        glVertex3f(wall.getOriginPoint().x, 1.0f, wall.getOriginPoint().y);
        glVertex3f(wall.getEndPoint().x, 1.0f, wall.getEndPoint().y);
        glEnd();

        glBegin(GL_LINE);
        glVertex3f(wall.getCentre().x, 1.0f, wall.getCentre().y);
        glVertex3f(wall.getCentre().x + wall.getNormal().x,
                   0.2f,
                   wall.getCentre().y + wall.getNormal().y);
        glEnd();
        glPopMatrix();
    }
    glColor3f(1.0, 0.0, 0.0);
    for (auto& intersections : world->currentLevel.debugIntersections) {
        glPushMatrix();
        glTranslatef(intersections.x, 1.0f, intersections.y);
        glRotated(90, 1.0, 0.0, 0.0);
        drawCircle(0.0f, 0.0f, 0.5f, 16);
        glPopMatrix();
    }
}

// copied from stackoverflow
void AITest::drawCircle(float cx, float cy, float r, int num_segments) {
    glBegin(GL_LINE_LOOP);
    for (int ii = 0; ii < num_segments; ii++) {
        float theta = 2.0f * 3.1415926f * float(ii)
                      / float(num_segments);  // get the current angle
        float x = r * cosf(theta);            // calculate the x component
        float y = r * sinf(theta);            // calculate the y component
        glVertex2f(x + cx, y + cy);           // output vertex
    }
    glEnd();
}
void AITest::drawCylinder(float halfLength, float radius, int slices) {
    for (int i = 0; i < slices; i++) {
        auto theta = (float)((float)i * 2.0f * M_PI);
        auto nextTheta = (float)(((float)i + 1.f) * 2.0f * M_PI);
        glBegin(GL_TRIANGLE_STRIP);
        /*vertex at middle of end */ glVertex3f(0.0f, halfLength, 0.0f);
        /*vertices at edges of circle*/ glVertex3f(radius * cos(theta),
                                                   halfLength,
                                                   radius * sin(theta));
        glVertex3f(radius * cos(nextTheta),
                   halfLength,
                   radius * sin(nextTheta));
        /* the same vertices at the bottom of the cylinder*/
        glVertex3f(radius * cos(nextTheta),
                   -halfLength,
                   radius * sin(nextTheta));
        glVertex3f(radius * cos(theta), -halfLength, radius * sin(theta));
        glVertex3f(0.0f, -halfLength, 0.0f);
        glEnd();
    }
}

void AITest::setTarget(glm::vec3 target) {
    // cast vec3 to dvec3?
    mouseTarget = target;
    glm::vec2 xyTarget = glm::vec2(target.x, target.z);
    world->m_Vehicles.front()->getSteering()->setTarget(xyTarget);
}

void AITest::shootTarget(glm::vec3 target) {
    // cast vec3 to dvec3?
    // fireWeapon
    glm::vec2 xyTarget = glm::vec2(target.x, target.z);
    world->m_Vehicles.front()->fireWeapon(xyTarget);
    /*
    glm::vec2 xyTarget = glm::vec2(target.x, target.z);
    TestProjectile* bolt = new TestProjectile(world->m_Vehicles.front(),
                                              xyTarget);
    world->m_Projectiles.push_back(bolt);
    */
}

void AITest::drawOrigin() {
    glPushMatrix();

    glColor3f(1.0, 1.0, 1.0);
    glTranslated(0.0, 0.0, 0.0);
    glRotated(90, 1.0, 0.0, 0.0);
    drawCircle(0.0f, 0.0f, 0.1f, 16);
    glPopMatrix();
}

void AITest::drawPlayer() {
    glPushMatrix();
    // world->player.

    glm::vec3 pos = glm::vec3(world->player->getPosition().x,
                              0.0,
                              world->player->getPosition().y);
    glm::vec3 scaledHeading = glm::vec3(world->player->getHeadingVec().x,
                                        0.0,
                                        world->player->getHeadingVec().y);
    scaledHeading *= glm::vec3(0.2f);
    glColor3f(0.0, 1.0, 0.0);
    glBegin(GL_LINE_LOOP);
    glVertex3d(pos.x, pos.y, pos.z);
    glVertex3d(scaledHeading.x + pos.x,
               scaledHeading.y + pos.y,
               scaledHeading.z + pos.z);
    glEnd();
    glRotated(90, 1.0, 0.0, 0.0);
    drawCircle(world->player->getPosition().x,
               world->player->getPosition().y,
               world->player->getBoundingRadius(),
               16);
    glPopMatrix();
}

void AITest::setBotColour(int goal) {
    switch (goal) {
        case 11:  // wander
            glColor3f(0.0f, 1.0f, 0.0f);
            break;
        case 13:  // attack target
            glColor3f(1.0f, 0.0f, 0.0f);
            break;
        case 14:  // hunt target
            glColor3f(1.0f, 0.647f, 0.0f);
            break;
        case 15:  // strafe target
            glColor3f(1.0f, 0.412f, 0.0f);
            break;
        default:  // hunt target
            glColor3f(0.0f, 0.0f, 1.0f);
            break;
    }
}

void AITest::drawBots() {
    for (auto& bot : world->m_Vehicles) {
        glPushMatrix();
        glTranslatef(0, 0.1f, 0);
        glColor3f(0.0f, 0.0f, 1.0f);
        // draw feelers
        glBegin(GL_LINE_LOOP);
        glVertex3d(bot->getPosition().x, 0.0f, bot->getPosition().y);
        glVertex3d(bot->getSteering()->getFeelers().at(0).x,
                   0.0f,
                   bot->getSteering()->getFeelers().at(0).y);
        glEnd();
        setBotColour(bot->getBrain()->getType());
        glRotated(90, 1.0f, 0.0f, 0.0f);
        drawCircle(bot->getPosition().x,
                   bot->getPosition().y,
                   bot->getBoundingRadius(),
                   16);
        glColor3f(1.0f, 0.0f, 0.0f);
        drawCircle(bot->getPosition().x,
                   bot->getPosition().y,
                   bot->getSteering()->getDBoxLength(),
                   16);
        glPopMatrix();
        glColor3f(1.0f, 0.5f, 0.0f);  // Orange
        for (auto& opponents :
             bot->getSensoryMem()->getListOfRecentlySensedOpponents()) {
            glm::vec3 oppCentre(opponents->getPosition().x,
                                0.2f,
                                opponents->getPosition().y);
            glBegin(GL_LINE_LOOP);
            glVertex3d(oppCentre.x - 0.5f, oppCentre.y, oppCentre.z - 0.5f);
            glVertex3d(oppCentre.x - 0.5f, oppCentre.y, oppCentre.z + 0.5f);
            glVertex3d(oppCentre.x + 0.5f, oppCentre.y, oppCentre.z + 0.5f);
            glVertex3d(oppCentre.x + 0.5f, oppCentre.y, oppCentre.z - 0.5f);
            glEnd();
        }
    }
}

/*    glPushAttrib(GL_POLYGON_BIT | GL_LIGHTING_BIT);
    glDisable(GL_LIGHTING);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    for (auto& debug : m_debugObjects) {
        debug.draw();
    }
    glPopAttrib();*/

void AITest::drawObstacles() {
    auto& allObstacles = world->currentLevel.getAllObstacles();
    for (auto& obstacle : allObstacles) {
        glPushMatrix();
        if (obstacle->getFlag())
            glColor3f(1.0f, 0.0f, 0.0f);
        else
            glColor3f(1.0f, 1.0f, 1.0f);
        glTranslated(obstacle->getPosition().x,
                     0.0f,
                     obstacle->getPosition().y);
        glRotated(90, 1.0f, 0.0f, 0.0f);
        drawCircle(0.0f, 0.0f, obstacle->getBoundingRadius(), 16);
        glPopMatrix();
    }
}

void AITest::drawProjectiles() {
    glColor3f(1.0f, 1.0f, 0.0f);
    for (auto& projectile : world->m_Projectiles) {
        glPushMatrix();
        glTranslated(projectile->getPosition().x,
                     0.2f,
                     projectile->getPosition().y);
        glRotated(90, 1.0f, 0.0f, 0.0f);
        drawCircle(0.0f, 0.0f, 0.005f, 16);
        glPopMatrix();
    }
}

void AITest::draw() {
    // std::cout << "redraw" << std::endl;
    // glClear(GL_COLOR_BUFFER_BIT);  // clear window to background color
    // drawTriangle();

    drawWalls();
    drawObstacles();
    // drawPlayer();
    drawBots();
    drawTarget();
    drawProjectiles();

    // glFlush();
}

void AITest::drawDebug() {
    // drawCylinder(5.0f, 1.0, 16);
    glPushAttrib(GL_POLYGON_BIT | GL_LIGHTING_BIT | GL_CURRENT_BIT);
    glDisable(GL_LIGHTING);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glLineWidth(20.0f);
    // drawWalls();
    drawTarget3D();
    drawObstacles3D();
    drawWalls();
    drawBots3D();
    // drawProjectiles3D();
    drawProjectiles();
    glPopAttrib();
}

void AITest::drawTarget3D() {
    // purple target
    // Want to make a thick circle later
    glColor3f(1.0f, 0.5f, 1.0f);

    glPushMatrix();
    // glLineWidth(20.0);
    glTranslatef(0, 0.2f, 0);
    glRotatef(90, 1.0f, 0.0f, 0.0f);
    drawCircle(mouseTarget.x, mouseTarget.z, 0.5f, 16);
    glColor3f(1.0f, 0.0f, 0.0f);
    glPopMatrix();
}

void AITest::drawBots3D() {
    for (auto& bot : world->m_Vehicles) {
        glPushMatrix();
        glTranslatef(0.0f, 0.2f, 0.0f);
        glColor3f(0.0f, 0.0f, 1.0f);
        // draw feelers
        if (bot->getSteering()->isWallAvoidanceOn()) {
            for (auto& feeler : bot->getSteering()->getFeelers()) {
                glBegin(GL_LINE_LOOP);
                glVertex3f(bot->getPosition().x, 0.0f, bot->getPosition().y);
                glVertex3f(feeler.x, 0.0f, feeler.y);
                glEnd();
            }
        }

        glColor3f(1.0f, 0.0f, 0.0f);
        glRotatef(90, 1.0f, 0.0f, 0.0f);
        if (bot->getSteering()->isObstacleAvoidanceOn()) {
            drawCircle(bot->getPosition().x,
                       bot->getPosition().y,
                       bot->getSteering()->getDBoxLength(),
                       16);
        }
        glColor3f(0.0f, 0.0f, 1.0f);

        // setBotColour(bot->m_Goal);
        drawCircle(bot->getPosition().x,
                   bot->getPosition().y,
                   bot->getBoundingRadius(),
                   16);
        glPopMatrix();
        glColor3f(1.0f, 0.5f, 0.0f);  // Orange
        for (auto& opponent :
             bot->getSensoryMem()->getListOfRecentlySensedOpponents()) {
            glm::vec2 oppPos = bot->getSensoryMem()
                                   ->getLastRecordedPositionOfOpponent(
                                       opponent);
            glm::vec3 oppCentre(oppPos.x, 0.2, oppPos.y);
            glBegin(GL_LINE_LOOP);
            glVertex3d(oppCentre.x - 0.5f, oppCentre.y, oppCentre.z - 0.5f);
            glVertex3d(oppCentre.x - 0.5f, oppCentre.y, oppCentre.z + 0.5f);
            glVertex3d(oppCentre.x + 0.5f, oppCentre.y, oppCentre.z + 0.5f);
            glVertex3d(oppCentre.x + 0.5f, oppCentre.y, oppCentre.z - 0.5f);
            glEnd();
        }
    }
}

void AITest::drawObstacles3D() {
    auto allObstacles = world->currentLevel.getAllObstacles();
    for (auto& obstacle : allObstacles) {
        glPushMatrix();
        if (obstacle->getFlag())
            glColor3f(1.0f, 0.0f, 0.0f);
        else
            glColor3f(1.0f, 1.0f, 1.0f);
        glTranslated(obstacle->getPosition().x, 0.2, obstacle->getPosition().y);
        glRotatef(90, 1.0f, 0.0f, 0.0f);
        drawCircle(0.0f, 0.0f, obstacle->getBoundingRadius(), 16);
        glPopMatrix();
    }
}

void AITest::drawProjectiles3D() {
    glColor3f(1.0f, 1.0f, 1.0f);
    for (auto& projectile : world->m_Projectiles) {
        glPushMatrix();
        glTranslated(projectile->getPosition().x,
                     0.0f,
                     projectile->getPosition().y);
        glRotated(90, 1.0f, 0.0f, 0.0f);
        drawCircle(0.0f, 0.0f, 0.005f, 16);
        glPopMatrix();
    }
}