summaryrefslogtreecommitdiff
path: root/source/logic/EnemyCar.cpp
blob: ce455a6da23e0f5ba6ab468f4147283ffccd3cfa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include "EnemyCar.h"

EnemyCar::EnemyCar(double x, double y)
    :Car(x,y,BitmapStore::ENEMY,Maze::UP),
    _state(CHASING),
    _targetX(x),
    _targetY(y)
{
}

void EnemyCar::update(const Maze& maze, const list<PlayerCar>& players, const list<Rock>& rocks)
{
    if (!players.empty()) checkFacing(maze, players.front().x(), players.front().y(), rocks);

    if (_state!=BLINDED)
    {
        move(maze);
    }
    else
    {
        _state = CHASING;
        _speed = _baseSpeed;
    }
}

void EnemyCar::checkFacing(const Maze& maze, double chasingX, double chasingY, const list<Rock>& rocks)
{
    if (abs(_x - _targetX)>_speed || abs(_y - _targetY)>_speed) return;

    map<Maze::Direction, pair<double, double> > adjacentBlocks;
    pair<double, double> evaluatingTarget;

    adjacentBlocks[Maze::LEFT] = make_pair(MazeMath::round(_x-1), MazeMath::round(_y));
    adjacentBlocks[Maze::RIGHT] = make_pair(MazeMath::round(_x+1), MazeMath::round(_y));
    adjacentBlocks[Maze::UP] = make_pair(MazeMath::round(_x), MazeMath::round(_y-1));
    adjacentBlocks[Maze::DOWN] = make_pair(MazeMath::round(_x), MazeMath::round(_y+1));

    //remove adjacent blocks that would result in crashing into a rock or a wall
    for (map<Maze::Direction, pair<double, double> >::iterator iter=adjacentBlocks.begin(); iter!=adjacentBlocks.end(); )
    {
        if (rockAtLocation(iter->second.first, iter->second.second, rocks) || maze.getSolid(static_cast<int>(iter->second.first),static_cast<int>(iter->second.second)))
        {
            adjacentBlocks.erase(iter);
            iter = adjacentBlocks.begin();
        }
        else
        {
            ++iter;
        }
    }

    if (adjacentBlocks.empty())
    {
        _speed = 0;
        return;
    }
    else
    {
        _speed = _baseSpeed;
    }

    map<Maze::Direction, pair<double, double> >::iterator reverseFacing = adjacentBlocks.find(Maze::backwards(_facing));
    if ((reverseFacing != adjacentBlocks.end()) && (adjacentBlocks.size()>1))
    {
        adjacentBlocks.erase(reverseFacing);
    }

    map<Maze::Direction, pair<double, double> >::const_iterator closestAdjacent = adjacentBlocks.begin();
    double closestDistance = MazeMath::distance(closestAdjacent->second.first, closestAdjacent->second.second, chasingX, chasingY);

    for (map<Maze::Direction, pair<double, double> >::const_iterator iter = ++adjacentBlocks.begin(); iter!=adjacentBlocks.end(); ++iter)
    {
        double newDistance = MazeMath::distance(iter->second.first, iter->second.second, chasingX, chasingY);
        if (newDistance < closestDistance)
        {
            closestDistance = newDistance;
            closestAdjacent = iter;
        }
    }

    _targetX = closestAdjacent->second.first;
    _targetY = closestAdjacent->second.second;
    _facing = closestAdjacent->first;
}

bool EnemyCar::rockAtLocation(double x, double y, const list<Rock>& rocks)
{
    for (list<Rock>::const_iterator iter = rocks.begin(); iter!=rocks.end(); ++iter)
    {
        if (abs(x - iter->x())<1 && abs(y - iter->y())<1) return true;
    }
    return false;
}

void EnemyCar::crash()
{
    _destroyed = true;
}

void EnemyCar::blind()
{
    _state = BLINDED;
    _speed = 0;
}