cell.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. /*
  2. * I love Qt
  3. */
  4. #include "cell.h"
  5. #include "units/unit.h"
  6. #include "hotseatgame/gameproperties.h"
  7. #include <string>
  8. #include <queue>
  9. #include <vector>
  10. #include <map>
  11. #include <iostream>
  12. #include <cmath>
  13. #include <QPainter>
  14. #include <QPolygon>
  15. #include <QDebug>
  16. class EffectsForCell{
  17. public:
  18. void OperateOnCell(Cell*){}
  19. };
  20. Cell::Cell(QGraphicsItem* parent) : QGraphicsItem(parent)
  21. {
  22. leftUp_ = left_ = leftDown_ = nullptr;
  23. rightUp_ = right_ = rightDown_ = nullptr;
  24. clearCell_();
  25. AddedToQuery_ = true;
  26. col_ = row_ = 0;
  27. hovered_ = false;
  28. coor_x_ = coor_y_ = -1;
  29. setAcceptHoverEvents(true);
  30. }
  31. Cell * Cell::getleftUp() {
  32. return leftUp_;
  33. }
  34. void Cell::setleftUp(Cell * t) {
  35. leftUp_ = t;
  36. }
  37. Cell * Cell::getleft() {
  38. return left_;
  39. }
  40. void Cell::setleft(Cell * t) {
  41. left_ = t;
  42. }
  43. Cell * Cell::getleftDown() {
  44. return leftDown_;
  45. }
  46. void Cell::setleftDown(Cell * t) {
  47. leftDown_ = t;
  48. }
  49. Cell * Cell::getrightUp() {
  50. return rightUp_;
  51. }
  52. void Cell::setrightUp(Cell * t) {
  53. rightUp_ = t;
  54. }
  55. Cell * Cell::getright() {
  56. return right_;
  57. }
  58. void Cell::setright(Cell * t) {
  59. right_ = t;
  60. }
  61. Cell * Cell::getrightDown() {
  62. return rightDown_;
  63. }
  64. void Cell::setrightDown(Cell * t) {
  65. rightDown_ = t;
  66. }
  67. std::shared_ptr<Unit> Cell::getCharacter() {
  68. return character_;
  69. }
  70. void Cell::setCharacter(std::shared_ptr<Unit> t) {
  71. character_ = t;
  72. }
  73. double Cell::getXCoordinate()
  74. {
  75. return coor_x_;
  76. }
  77. void Cell::setXCoordinate(double coordinate)
  78. {
  79. coor_x_ = coordinate;
  80. }
  81. double Cell::getYCoordinate() {
  82. return coor_y_;
  83. }
  84. void Cell::setYCoordinate(double coordinate) {
  85. coor_y_ = coordinate;
  86. }
  87. int Cell::getdistance_barrier(){
  88. return distance_barrier_;
  89. }
  90. void Cell::setdistance_barrier(int distance_barrier){
  91. distance_barrier_ = distance_barrier;
  92. }
  93. int Cell::getdistance_through(){
  94. return distance_through_;
  95. }
  96. void Cell::setdistance_through(int distance_through){
  97. distance_through_ = distance_through;
  98. }
  99. bool Cell::getisMoveAble(){
  100. return isMoveAble_;
  101. }
  102. void Cell::setisMoveAble(bool isMoveAble){
  103. isMoveAble_ = isMoveAble;
  104. }
  105. bool Cell::getisMeleeAttackAble(){
  106. return isMeleeAttackAble_;
  107. }
  108. void Cell::setisMeleeAttackAble(bool isMeleeAttackAble){
  109. isMeleeAttackAble_ = isMeleeAttackAble;
  110. }
  111. bool Cell::getisRangeAttackAble(){
  112. return isRangeAttackAble_;
  113. }
  114. void Cell::setisRangeAttackAble(bool isRangeAttackAble){
  115. isRangeAttackAble_ = isRangeAttackAble;
  116. }
  117. bool Cell::isEmpty() {
  118. return character_ == nullptr;
  119. }
  120. void Cell::recalculateAllEffectsList(){
  121. for(std::vector<EffectsForCell*>::iterator it = beginIteratorEffectsList();
  122. it != endIteratorEffectsList();++it){
  123. (*it)->OperateOnCell(this);
  124. }
  125. }
  126. void Cell::add(EffectsForCell* effect){
  127. if(effect == nullptr)
  128. throw new int(228);
  129. effects_list_.push_back(effect);
  130. }
  131. void Cell::remove(std::vector<EffectsForCell*>::iterator it){
  132. if(beginIteratorEffectsList() <= it && it < endIteratorEffectsList()){
  133. effects_list_.erase(it);
  134. }
  135. }
  136. void Cell::remove(EffectsForCell* effect){
  137. for(std::vector<EffectsForCell*>::iterator it = beginIteratorEffectsList();
  138. it != endIteratorEffectsList();++it){
  139. if((*it) == effect){
  140. remove(it);
  141. return;
  142. }
  143. }
  144. }
  145. std::vector<EffectsForCell*>::iterator Cell::beginIteratorEffectsList(){
  146. return effects_list_.begin();
  147. }
  148. std::vector<EffectsForCell*>::iterator Cell::endIteratorEffectsList(){
  149. return effects_list_.end();
  150. }
  151. void Cell::RecalculateTableWithCenterThisPoint() {
  152. clearTable_();
  153. std::queue<Cell*> qWithUnMoveable;
  154. updateMoveableCells_(qWithUnMoveable);
  155. updateUnMovealeCells_(qWithUnMoveable);
  156. }
  157. std::vector <Cell*> Cell::actualPath(Cell* to) {
  158. if (!to || !to->getisMoveAble())return std::vector<Cell*>();
  159. auto ret = std::vector<Cell*>(1, to);
  160. while (to != this) {
  161. Cell * parent = nullptr;
  162. auto f = [&parent](Cell * TestParent, Cell * Now) {
  163. if (TestParent && TestParent->getdistance_barrier() + 1 == Now->getdistance_barrier()
  164. && TestParent->getisMoveAble()) {
  165. parent = TestParent;
  166. }
  167. };
  168. if(parent == nullptr) throw std::string("Don`t recalculated");
  169. f(to->getleftUp(), to);
  170. f(to->getleft(), to);
  171. f(to->getleftDown(), to);
  172. f(to->getrightUp(), to);
  173. f(to->getright(), to);
  174. f(to->getrightDown(), to);
  175. to = parent;
  176. ret.push_back(to);
  177. }
  178. return ret;
  179. }
  180. void Cell::clearCell_() {
  181. setdistance_barrier(-1);
  182. setdistance_through(-1);
  183. setisMeleeAttackAble(false);
  184. setisMoveAble(false);
  185. setisRangeAttackAble(false);
  186. }
  187. QRectF Cell::boundingRect() const
  188. {
  189. return QRectF(polygon.boundingRect());
  190. }
  191. void Cell::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
  192. {
  193. polygon.clear();
  194. auto points = getPoints(GameProperties::CELL_MAX_RADIUS, 0);
  195. for (auto point : points) {
  196. polygon << QPoint(point.first, point.second);
  197. }
  198. polygon << QPoint(points[0].first, points[0].second);
  199. QPen pen = QPen(Qt::green, 2);
  200. painter->setPen(pen);
  201. painter->setBrush(Qt::green); // We set the brush, which will render the object
  202. painter->drawPolyline(polygon); // Draw a triangle on a polygonal model
  203. if (hovered_) {
  204. painter->setOpacity(0.4);
  205. painter->drawPolygon(polygon);
  206. }
  207. }
  208. bool Cell::contains(const QPointF &point) const
  209. {
  210. return polygon.contains(point.toPoint());
  211. }
  212. bool Cell::isHovered()
  213. {
  214. return hovered_;
  215. }
  216. void Cell::setHovered(bool hovered)
  217. {
  218. hovered_ = hovered;
  219. }
  220. void Cell::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
  221. {
  222. hovered_ = true;
  223. update();
  224. }
  225. void Cell::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
  226. {
  227. hovered_ = false;
  228. update();
  229. }
  230. void Cell::clearTable_() {
  231. std::queue<Cell*> q;
  232. q.push(this);
  233. clearCell_();
  234. setdistance_through(0);
  235. this->AddedToQuery_ = false;
  236. auto f = [&q](Cell * t, Cell * parent, int delta_col, int delta_row) {
  237. if (t && t->AddedToQuery_ == true) {
  238. q.push(t);
  239. t->col_ = parent->col_ + delta_col;
  240. t->row_ = parent->row_ + delta_row;
  241. t->setdistance_through(
  242. parent->getdistance_through() + 1
  243. );
  244. t->AddedToQuery_ = false;
  245. }
  246. };
  247. while (!q.empty()) {
  248. Cell * Now = q.front();
  249. q.pop();
  250. Now->clearCell_();
  251. f(Now->getleftUp(), Now, -1, 0);
  252. f(Now->getleft(), Now, 0, -1);
  253. f(Now->getleftDown(), Now, 1, -1);
  254. f(Now->getrightUp(), Now, -1, 1);
  255. f(Now->getright(), Now, 0, 1);
  256. f(Now->getrightDown(), Now, 1, 0);
  257. }
  258. }
  259. void Cell::recalcAttackable_(Cell * Now,bool isReached){
  260. if(Now == nullptr)return;
  261. if (!isEmpty() && !Now->isEmpty() &&
  262. getCharacter()->canAttackForDistance("Melee", Now->getdistance_barrier())
  263. ) {
  264. Now->setisMeleeAttackAble(isReached);
  265. }
  266. if (!isEmpty() && !Now->isEmpty() &&
  267. getCharacter()->canAttackForDistance("Range", Now->getdistance_barrier())
  268. ) {
  269. Now->setisRangeAttackAble(true);
  270. }
  271. return;
  272. }
  273. void Cell::recalcMoveable_(Cell * Now, bool isReached){
  274. if(Now == nullptr || Now->isEmpty() || isEmpty())return;
  275. if(!isEmpty() && Now->isEmpty() &&
  276. getCharacter()->canMoveForDistance(Now->getdistance_barrier())){
  277. Now->setisMoveAble(isReached);
  278. }
  279. }
  280. void Cell::updateMoveableCells_(std::queue<Cell*> & Q) {
  281. std::queue<Cell*> q;
  282. q.push(this);
  283. setdistance_barrier(0);
  284. auto f = [&q, &Q](Cell * t, Cell * parent) {
  285. if (t && !t->AddedToQuery_) {
  286. t->AddedToQuery_ = true;
  287. if (t->getCharacter() != NULL) {
  288. Q.push(t);
  289. return;
  290. }
  291. q.push(t);
  292. t->setdistance_barrier(
  293. parent->getdistance_barrier() + 1
  294. );
  295. }
  296. };
  297. while (!q.empty()) {
  298. Cell * Now = q.front();
  299. q.pop();
  300. recalcMoveable_(Now, true);
  301. recalcAttackable_(Now, true);
  302. f(Now->getleftUp(), Now);
  303. f(Now->getleft(), Now);
  304. f(Now->getleftDown(), Now);
  305. f(Now->getrightUp(), Now);
  306. f(Now->getright(), Now);
  307. f(Now->getrightDown(), Now);
  308. }
  309. }
  310. void Cell::updateUnMovealeCells_(std::queue<Cell*> & Q) {
  311. auto f = [&Q](Cell * t, Cell * parent) {
  312. if (t && !t->AddedToQuery_) {
  313. parent->getCharacter();
  314. t->AddedToQuery_ = true;
  315. Q.push(t);
  316. }
  317. };
  318. while (!Q.empty()) {
  319. Cell * Now = Q.front();
  320. recalcMoveable_(Now, false);
  321. recalcAttackable_(Now, false);
  322. Q.pop();
  323. f(Now->getleftUp(), Now);
  324. f(Now->getleft(), Now);
  325. f(Now->getleftDown(), Now);
  326. f(Now->getrightUp(), Now);
  327. f(Now->getright(), Now);
  328. f(Now->getrightDown(), Now);
  329. }
  330. }
  331. Cell* Cell::getRealShootTarget(Cell* next){
  332. if(next == this){
  333. return next;
  334. }
  335. int next_col = next->col_;
  336. int next_row = next->row_;
  337. if(next_col - col_ == next_row - row_){//GoMainDiagonal
  338. if(next_col > col_){
  339. return getrightDown()->getright();
  340. }
  341. if(next_col < col_){
  342. return getleftUp()->getleft();
  343. }
  344. throw std::string("Don`t recalculated");
  345. }
  346. if(-2 * (next_col - col_) == (next_row - row_)){//GoSecondaryDiagonal
  347. if(next_col < col_){
  348. return getrightUp()->getright();
  349. }
  350. if(next_col > col_){
  351. return getleftDown()->getleft();
  352. }
  353. throw std::string("Don`t recalculated");
  354. }
  355. if(next_col - col_ == -2 * (next_row - row_)){//GoUp
  356. if(next_col < col_){
  357. return (getleftUp() != nullptr ? getleftUp()->getrightUp() : getrightUp()->getleftUp());
  358. }
  359. if(next_col > col_){
  360. return (getleftDown() != nullptr ? getleftDown()->getrightDown() : getrightDown()->getleftDown());
  361. }
  362. throw std::string("Don`t recalculated");
  363. }
  364. int row_secondary_diag = row_ - 2 * (next_col - col_);
  365. int row_main_diag = row_ + next_col - col_;
  366. int twice_row_up_line = 2 * row_ + col_ - next_col;
  367. if(next_col > col_){
  368. if(next_row < row_main_diag)return getleft();
  369. if(2 * next_row < twice_row_up_line)return getleftUp();
  370. if(next_row < row_secondary_diag)return getrightUp();
  371. return getright();
  372. }
  373. else{
  374. if(next_row < row_secondary_diag)return getleft();
  375. if(2 * next_row < twice_row_up_line)return getleftDown();
  376. if(next_row < row_main_diag)return getrightDown();
  377. return getright();
  378. }
  379. }
  380. std::vector<std::pair<int, int> > Cell::getPoints(double radius, double start_angle) {
  381. const double delta_radians = M_PI / 180.0;
  382. std::vector<std::pair<int, int> > res;
  383. std::vector<double> angles = {0, 60, 120, 180, 240, 300};
  384. for(size_t i = 0; i < angles.size(); ++i){
  385. angles[i] += start_angle;
  386. res.push_back({std::round(radius * std::sin(angles[i] * delta_radians)),
  387. std::round(radius * std::cos(angles[i] * delta_radians))});
  388. }
  389. return res;
  390. }