-
Notifications
You must be signed in to change notification settings - Fork 0
/
Entity.cpp
executable file
·114 lines (98 loc) · 2.83 KB
/
Entity.cpp
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
105
106
107
108
109
110
111
112
113
114
#include "Entity.h"
#include "Game.h"
Entity::Entity() : Object()
{
_curDir = UNKNOWN;
_nextDir = UNKNOWN;
_nodePrev = _nodeNext = -1;
_moving = true;
_speed = SPEED_GHOST_NORMAL;
}
void Entity::checkpointReached(bool canEnterHouse)
{
auto & neighbours = Level::instance()->neighbors();
_nodePrev = _nodeNext;
// check if next direction is feasible
if(neighbours[_nodePrev][_nextDir] >= 0 &&
(canEnterHouse || (canEnterHouse == false && neighbours[_nodeNext][_nextDir] != Level::instance()->houseEntranceNode())))
_curDir = _nextDir;
_nodeNext = neighbours[_nodePrev][_curDir];
// check if current direction is feasible
if(neighbours[_nodePrev][_curDir] < 0)
{
_moving = false;
_nodeNext = _nodePrev;
}
else
_moving = true;
}
void Entity::advance()
{
auto & nodes = Level::instance()->nodes();
if(nodes[_nodeNext] == centerPos())
checkpointReached();
if(_moving)
{
if(_curDir == RIGHT)
setX(x()+_speed/GAME_FPS);
else if(_curDir == UP)
setY(y()-_speed/GAME_FPS);
else if(_curDir == DOWN)
setY(y()+_speed/GAME_FPS);
else if(_curDir == LEFT)
setX(x()-_speed/GAME_FPS);
}
// detect derailment
if(_curDir == RIGHT && centerPos().x() > nodes[_nodeNext].x())
setX(nodes[_nodeNext].x()-pixmap().width()/2);
else if(_curDir == LEFT && centerPos().x() < nodes[_nodeNext].x())
setX(nodes[_nodeNext].x()-pixmap().width()/2);
else if(_curDir == UP && centerPos().y() < nodes[_nodeNext].y())
setY(nodes[_nodeNext].y()-pixmap().height()/2);
else if(_curDir == DOWN && centerPos().y() > nodes[_nodeNext].y())
setY(nodes[_nodeNext].y()-pixmap().height()/2);
}
void Entity::animate()
{
if(_curDir == UP)
setPixmap(_textureUp[(_animation_counter / _animation_divisor) %2]);
else if(_curDir == RIGHT)
setPixmap(_textureRight[(_animation_counter / _animation_divisor) %2]);
else if(_curDir == DOWN)
setPixmap(_textureDown[(_animation_counter / _animation_divisor) %2]);
else if(_curDir == LEFT)
setPixmap(_textureLeft[(_animation_counter / _animation_divisor) %2]);
else
setPixmap(_textureStand);
}
QPainterPath Entity::shape() const
{
// collider is 4 pixels smaller than the bounding rectangle (default collider)
QPainterPath path;
path.addRect(4, 4, boundingRect().width()-8, boundingRect().height()-8);
return path;
}
void Entity::solveCollisions()
{
// get collisions
QList<QGraphicsItem*> colliding_items = collidingItems();
// manage collisions
for(auto colliding : colliding_items)
{
// convert to game object, and skip if conversion
// does not work (should never happen)
Object *obj = dynamic_cast<Object*>(colliding);
if(!obj)
continue;
// the two objects hit each other
obj->hit(this);
this->hit(obj);
}
}
void Entity::invertDir()
{
int tmp = _nodeNext;
_nodeNext = _nodePrev;
_nodePrev = tmp;
_curDir = inverse(_curDir);
}