123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- /*
- * I love Qt
- */
- #include "cell.h"
- #include "units/unit.h"
- #include "hotseatgame/gameproperties.h"
- #include <string>
- #include <queue>
- #include <vector>
- #include <map>
- #include <iostream>
- #include <cmath>
- #include <QPainter>
- #include <QPolygon>
- #include <QDebug>
- class EffectsForCell{
- public:
- void OperateOnCell(Cell*){}
- };
- Cell::Cell(QGraphicsItem* parent) : QGraphicsItem(parent)
- {
- leftUp_ = left_ = leftDown_ = nullptr;
- rightUp_ = right_ = rightDown_ = nullptr;
- clearCell_();
- AddedToQuery_ = true;
- col_ = row_ = 0;
- hovered_ = false;
- coor_x_ = coor_y_ = -1;
- setAcceptHoverEvents(true);
- }
- Cell * Cell::getleftUp() {
- return leftUp_;
- }
- void Cell::setleftUp(Cell * t) {
- leftUp_ = t;
- }
- Cell * Cell::getleft() {
- return left_;
- }
- void Cell::setleft(Cell * t) {
- left_ = t;
- }
- Cell * Cell::getleftDown() {
- return leftDown_;
- }
- void Cell::setleftDown(Cell * t) {
- leftDown_ = t;
- }
- Cell * Cell::getrightUp() {
- return rightUp_;
- }
- void Cell::setrightUp(Cell * t) {
- rightUp_ = t;
- }
- Cell * Cell::getright() {
- return right_;
- }
- void Cell::setright(Cell * t) {
- right_ = t;
- }
- Cell * Cell::getrightDown() {
- return rightDown_;
- }
- void Cell::setrightDown(Cell * t) {
- rightDown_ = t;
- }
- std::shared_ptr<Unit> Cell::getCharacter() {
- return character_;
- }
- void Cell::setCharacter(std::shared_ptr<Unit> t) {
- character_ = t;
- }
- double Cell::getXCoordinate()
- {
- return coor_x_;
- }
- void Cell::setXCoordinate(double coordinate)
- {
- coor_x_ = coordinate;
- }
- double Cell::getYCoordinate() {
- return coor_y_;
- }
- void Cell::setYCoordinate(double coordinate) {
- coor_y_ = coordinate;
- }
- int Cell::getdistance_barrier(){
- return distance_barrier_;
- }
- void Cell::setdistance_barrier(int distance_barrier){
- distance_barrier_ = distance_barrier;
- }
- int Cell::getdistance_through(){
- return distance_through_;
- }
- void Cell::setdistance_through(int distance_through){
- distance_through_ = distance_through;
- }
- bool Cell::getisMoveAble(){
- return isMoveAble_;
- }
- void Cell::setisMoveAble(bool isMoveAble){
- isMoveAble_ = isMoveAble;
- }
- bool Cell::getisMeleeAttackAble(){
- return isMeleeAttackAble_;
- }
- void Cell::setisMeleeAttackAble(bool isMeleeAttackAble){
- isMeleeAttackAble_ = isMeleeAttackAble;
- }
- bool Cell::getisRangeAttackAble(){
- return isRangeAttackAble_;
- }
- void Cell::setisRangeAttackAble(bool isRangeAttackAble){
- isRangeAttackAble_ = isRangeAttackAble;
- }
- bool Cell::isEmpty() {
- return character_ == nullptr;
- }
- void Cell::recalculateAllEffectsList(){
- for(std::vector<EffectsForCell*>::iterator it = beginIteratorEffectsList();
- it != endIteratorEffectsList();++it){
- (*it)->OperateOnCell(this);
- }
- }
- void Cell::add(EffectsForCell* effect){
- if(effect == nullptr)
- throw new int(228);
- effects_list_.push_back(effect);
- }
- void Cell::remove(std::vector<EffectsForCell*>::iterator it){
- if(beginIteratorEffectsList() <= it && it < endIteratorEffectsList()){
- effects_list_.erase(it);
- }
- }
- void Cell::remove(EffectsForCell* effect){
- for(std::vector<EffectsForCell*>::iterator it = beginIteratorEffectsList();
- it != endIteratorEffectsList();++it){
- if((*it) == effect){
- remove(it);
- return;
- }
- }
- }
- std::vector<EffectsForCell*>::iterator Cell::beginIteratorEffectsList(){
- return effects_list_.begin();
- }
- std::vector<EffectsForCell*>::iterator Cell::endIteratorEffectsList(){
- return effects_list_.end();
- }
- void Cell::RecalculateTableWithCenterThisPoint() {
- clearTable_();
- std::queue<Cell*> qWithUnMoveable;
- updateMoveableCells_(qWithUnMoveable);
- updateUnMovealeCells_(qWithUnMoveable);
- }
- std::vector <Cell*> Cell::actualPath(Cell* to) {
- if (!to || !to->getisMoveAble())return std::vector<Cell*>();
- auto ret = std::vector<Cell*>(1, to);
- while (to != this) {
- Cell * parent = nullptr;
- auto f = [&parent](Cell * TestParent, Cell * Now) {
- if (TestParent && TestParent->getdistance_barrier() + 1 == Now->getdistance_barrier()
- && TestParent->getisMoveAble()) {
- parent = TestParent;
- }
- };
- if(parent == nullptr) throw std::string("Don`t recalculated");
- f(to->getleftUp(), to);
- f(to->getleft(), to);
- f(to->getleftDown(), to);
- f(to->getrightUp(), to);
- f(to->getright(), to);
- f(to->getrightDown(), to);
- to = parent;
- ret.push_back(to);
- }
- return ret;
- }
- void Cell::clearCell_() {
- setdistance_barrier(-1);
- setdistance_through(-1);
- setisMeleeAttackAble(false);
- setisMoveAble(false);
- setisRangeAttackAble(false);
- }
- QRectF Cell::boundingRect() const
- {
- return QRectF(polygon.boundingRect());
- }
- void Cell::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
- {
- polygon.clear();
- auto points = getPoints(GameProperties::CELL_MAX_RADIUS, 0);
- for (auto point : points) {
- polygon << QPoint(point.first, point.second);
- }
- polygon << QPoint(points[0].first, points[0].second);
- QPen pen = QPen(Qt::green, 2);
- painter->setPen(pen);
- painter->setBrush(Qt::green); // We set the brush, which will render the object
- painter->drawPolyline(polygon); // Draw a triangle on a polygonal model
- if (hovered_) {
- painter->setOpacity(0.4);
- painter->drawPolygon(polygon);
- }
- }
- bool Cell::contains(const QPointF &point) const
- {
- return polygon.contains(point.toPoint());
- }
- bool Cell::isHovered()
- {
- return hovered_;
- }
- void Cell::setHovered(bool hovered)
- {
- hovered_ = hovered;
- }
- void Cell::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
- {
- hovered_ = true;
- update();
- }
- void Cell::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
- {
- hovered_ = false;
- update();
- }
- void Cell::clearTable_() {
- std::queue<Cell*> q;
- q.push(this);
- clearCell_();
- setdistance_through(0);
- this->AddedToQuery_ = false;
- auto f = [&q](Cell * t, Cell * parent, int delta_col, int delta_row) {
- if (t && t->AddedToQuery_ == true) {
- q.push(t);
- t->col_ = parent->col_ + delta_col;
- t->row_ = parent->row_ + delta_row;
- t->setdistance_through(
- parent->getdistance_through() + 1
- );
- t->AddedToQuery_ = false;
- }
- };
- while (!q.empty()) {
- Cell * Now = q.front();
- q.pop();
- Now->clearCell_();
- f(Now->getleftUp(), Now, -1, 0);
- f(Now->getleft(), Now, 0, -1);
- f(Now->getleftDown(), Now, 1, -1);
- f(Now->getrightUp(), Now, -1, 1);
- f(Now->getright(), Now, 0, 1);
- f(Now->getrightDown(), Now, 1, 0);
- }
- }
- void Cell::recalcAttackable_(Cell * Now,bool isReached){
- if(Now == nullptr)return;
- if (!isEmpty() && !Now->isEmpty() &&
- getCharacter()->canAttackForDistance("Melee", Now->getdistance_barrier())
- ) {
- Now->setisMeleeAttackAble(isReached);
- }
- if (!isEmpty() && !Now->isEmpty() &&
- getCharacter()->canAttackForDistance("Range", Now->getdistance_barrier())
- ) {
- Now->setisRangeAttackAble(true);
- }
- return;
- }
- void Cell::recalcMoveable_(Cell * Now, bool isReached){
- if(Now == nullptr || Now->isEmpty() || isEmpty())return;
- if(!isEmpty() && Now->isEmpty() &&
- getCharacter()->canMoveForDistance(Now->getdistance_barrier())){
- Now->setisMoveAble(isReached);
- }
- }
- void Cell::updateMoveableCells_(std::queue<Cell*> & Q) {
- std::queue<Cell*> q;
- q.push(this);
- setdistance_barrier(0);
- auto f = [&q, &Q](Cell * t, Cell * parent) {
- if (t && !t->AddedToQuery_) {
- t->AddedToQuery_ = true;
- if (t->getCharacter() != NULL) {
- Q.push(t);
- return;
- }
- q.push(t);
- t->setdistance_barrier(
- parent->getdistance_barrier() + 1
- );
- }
- };
- while (!q.empty()) {
- Cell * Now = q.front();
- q.pop();
- recalcMoveable_(Now, true);
- recalcAttackable_(Now, true);
- f(Now->getleftUp(), Now);
- f(Now->getleft(), Now);
- f(Now->getleftDown(), Now);
- f(Now->getrightUp(), Now);
- f(Now->getright(), Now);
- f(Now->getrightDown(), Now);
- }
- }
- void Cell::updateUnMovealeCells_(std::queue<Cell*> & Q) {
- auto f = [&Q](Cell * t, Cell * parent) {
- if (t && !t->AddedToQuery_) {
- parent->getCharacter();
- t->AddedToQuery_ = true;
- Q.push(t);
- }
- };
- while (!Q.empty()) {
- Cell * Now = Q.front();
- recalcMoveable_(Now, false);
- recalcAttackable_(Now, false);
- Q.pop();
- f(Now->getleftUp(), Now);
- f(Now->getleft(), Now);
- f(Now->getleftDown(), Now);
- f(Now->getrightUp(), Now);
- f(Now->getright(), Now);
- f(Now->getrightDown(), Now);
- }
- }
- Cell* Cell::getRealShootTarget(Cell* next){
- if(next == this){
- return next;
- }
- int next_col = next->col_;
- int next_row = next->row_;
- if(next_col - col_ == next_row - row_){//GoMainDiagonal
- if(next_col > col_){
- return getrightDown()->getright();
- }
- if(next_col < col_){
- return getleftUp()->getleft();
- }
- throw std::string("Don`t recalculated");
- }
- if(-2 * (next_col - col_) == (next_row - row_)){//GoSecondaryDiagonal
- if(next_col < col_){
- return getrightUp()->getright();
- }
- if(next_col > col_){
- return getleftDown()->getleft();
- }
- throw std::string("Don`t recalculated");
- }
- if(next_col - col_ == -2 * (next_row - row_)){//GoUp
- if(next_col < col_){
- return (getleftUp() != nullptr ? getleftUp()->getrightUp() : getrightUp()->getleftUp());
- }
- if(next_col > col_){
- return (getleftDown() != nullptr ? getleftDown()->getrightDown() : getrightDown()->getleftDown());
- }
- throw std::string("Don`t recalculated");
- }
- int row_secondary_diag = row_ - 2 * (next_col - col_);
- int row_main_diag = row_ + next_col - col_;
- int twice_row_up_line = 2 * row_ + col_ - next_col;
- if(next_col > col_){
- if(next_row < row_main_diag)return getleft();
- if(2 * next_row < twice_row_up_line)return getleftUp();
- if(next_row < row_secondary_diag)return getrightUp();
- return getright();
- }
- else{
- if(next_row < row_secondary_diag)return getleft();
- if(2 * next_row < twice_row_up_line)return getleftDown();
- if(next_row < row_main_diag)return getrightDown();
- return getright();
- }
- }
- std::vector<std::pair<int, int> > Cell::getPoints(double radius, double start_angle) {
- const double delta_radians = M_PI / 180.0;
- std::vector<std::pair<int, int> > res;
- std::vector<double> angles = {0, 60, 120, 180, 240, 300};
- for(size_t i = 0; i < angles.size(); ++i){
- angles[i] += start_angle;
- res.push_back({std::round(radius * std::sin(angles[i] * delta_radians)),
- std::round(radius * std::cos(angles[i] * delta_radians))});
- }
- return res;
- }
|