Ver Fonte

Merge branch 'cell' of GooseHouse/game-client into dev

Ivan Arkhipov há 6 anos atrás
pai
commit
c0812ca1b0
5 ficheiros alterados com 425 adições e 272 exclusões
  1. 1 1
      .gitignore
  2. 0 201
      Cell.cpp
  3. 0 70
      Cell.h
  4. 140 0
      include/Cell.h
  5. 284 0
      source/Cell.cpp

+ 1 - 1
.gitignore

@@ -105,4 +105,4 @@ CMakeScripts
 Makefile
 cmake_install.cmake
 install_manifest.txt
-
+TestCellProject

+ 0 - 201
Cell.cpp

@@ -1,201 +0,0 @@
-#include "Cell.h"
-#include "unit.h"
-#include <queue>
-#include <vector>
-
-Cell::Cell(Unit * character) {
-	leftUp_ = left_ = leftDown_ = nullptr;
-	rightUp_ = right_ = rightDown_ = nullptr;
-	character_ = &character;
-	clearCell_();
-	AddedToQuery_ = 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;
-}
-
-Unit * Cell::getCharacter() {
-	return character_;
-}
-void Cell::setCharacter(Unit * t) {
-	character_ = t;
-}
-
-bool Cell::getisMoveable() {
-	return isMoveable_;
-}
-void Cell::setisMoveable(bool t) {
-	isMoveable_ = t;
-}
-
-bool Cell::getisAttackable() {
-	return isAttackable_;
-}
-void Cell::setisAttackable(bool t) {
-	isAttackable_ = t;
-}
-
-int Cell::getDistance() {
-	return distance_;
-}
-void Cell::setDistance(int t) {
-	distance_ = t;
-}
-
-bool Cell::isEmpty() {
-	return character_ == NULL;
-}
-
-void Cell::clearCell_() {
-	setisMoveable(false);
-	setisAttackable(false);
-	setDistance(-1);
-}
-
-void Cell::clearTable_() {
-	std::queue<Cell*> q;
-	q.push(this);
-	clearCell_();
-	this->AddedToQuery_ = false;
-	auto f = [&q](Cell * t) {
-		if (t && t->AddedToQuery_ == true) {
-			q.push(t);
-			t->AddedToQuery_ = false;
-		}
-	};
-	while (!q.empty()) {
-		Cell * Now = q.front();
-		q.pop();
-		Now->clearCell_();
-		f(Now->getleftUp());
-		f(Now->getleft());
-		f(Now->getleftDown());
-		f(Now->getrightUp());
-		f(Now->getright());
-		f(Now->getrightDown());
-	}
-}
-
-void Cell::handleAllMoveableCellsAndUnmoveableCells_(std::queue<Cell*> & Q) {
-	std::queue<Cell*> q;
-	q.push(this);
-	setDistance(0);
-	auto f = [&q, &Q](Cell * t, Cell * parent) {
-		if (t && !t->AddedToQuery_) {
-			t->AddedToQuery_ = true;
-			if (t->getCharacter() != NULL) {
-				t->setisMoveable(false);
-				Q.push(t);
-				return;
-			}
-			q.push(t);
-			t->setDistance(parent->getDistance() + 1);
-		}
-	};
-	while (!q.empty()) {
-		Cell * Now = q.front();
-		Now->setisMoveable(true);
-		if (getCharacter() != NULL && getCharacter()->СanAttack(Now->getDistance())) {
-			Now->setisAttackable(true);
-		}
-		else {
-			Now->setisAttackable(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);
-	}
-}
-
-void Cell::handleAllUnmoveableCells_(std::queue<Cell*> & Q) {
-	auto f = [&Q](Cell * t, Cell * parent) {
-		if (t && !t->AddedToQuery_) {
-			t->AddedToQuery_ = true;
-			Q.push(t);
-		}
-	};
-	while (!Q.empty()) {
-		Cell * Now = Q.front();
-		Now->setisMoveable(false);
-		Now->setisAttackable(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);
-	}
-}
-
-void Cell::RecalculateTableWithCenterThisPoint() {
-	clearTable_();
-	std::queue<Cell*> qWithoutMoveable;
-	handleAllMoveableCellsAndUnmoveableCells_(qWithoutMoveable);
-	handleAllUnmoveableCells_(qWithoutMoveable);
-}
-
-std::vector <Cell*> Cell::actualPath(Cell* to) {//std::vector<Cell*> âêëþ÷àåòñÿ â ñåáÿ è this, è end
-	if (!to || !to->getisMoveable())return std::vector<Cell*>();
-	auto ret = std::vector<Cell*>(1, to);
-	while (to != this) {
-		Cell * parent = NULL;
-		auto f = [&parent](Cell * TestParent, Cell * Now) {
-			if (TestParent && TestParent->getDistance() + 1 == Now->getDistance() && TestParent->getisMoveable()) {
-				parent = TestParent;
-			}
-		};
-		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;
-}

+ 0 - 70
Cell.h

@@ -1,70 +0,0 @@
-#pragma once
-#include <queue>
-#include <vector>
-
-class Unit;
-
-class Cell {
-
-private:
-	Cell * leftUp_;
-	Cell *left_;
-	Cell * leftDown_;
-
-	Cell *rightUp_;
-	Cell *right_;
-	Cell *rightDown_;
-
-	Unit *character_;
-
-	bool isMoveable_;
-	bool  isAttackable_;
-
-	int distance_;
-	bool AddedToQuery_;
-
-	void clearTable_();
-	void clearCell_();
-
-	void handleAllMoveableCellsAndUnmoveableCells_(std::queue<Cell*> & Q);
-	void handleAllUnmoveableCells_(std::queue<Cell*> & Q);
-
-public:
-
-	explicit Cell(Unit * character);
-
-	Cell * getleftUp();
-	void setleftUp(Cell *);
-
-	Cell * getleft();
-	void setleft(Cell *);
-	
-	Cell * getleftDown();
-	void setleftDown(Cell *);
-	
-	Cell * getrightUp();
-	void setrightUp(Cell *);
-	
-	Cell * getright();
-	void setright(Cell *);
-	
-	Cell * getrightDown();
-	void setrightDown(Cell *);
-	
-	Unit * getCharacter();
-	void setCharacter(Unit *);
-	
-	bool getisMoveable();
-	void setisMoveable(bool);
-	
-	bool getisAttackable();
-	void setisAttackable(bool);
-	
-	int getDistance();
-	void setDistance(int);
-	
-	bool isEmpty();
-
-	void RecalculateTableWithCenterThisPoint();
-	std::vector <Cell*> actualPath(Cell*);
-};

+ 140 - 0
include/Cell.h

@@ -0,0 +1,140 @@
+#pragma once
+#include <queue>
+#include <vector>
+/*
+ * Решили, что метод canAttackForDistance(int) имеет шаблон, который обозначает тип атаки
+ * Melee - без учёта препятствий
+ * Range - с учётом препятствий
+ * Шаблон - строка. При такой реализации можно добавить новый вид атаки
+ * Необходимо в Unit добавить метод bool isCharacter() - является ли данный юнит персонажем
+ */
+class Unit;
+/*
+ * Этот класс Игоря ждёт своей реализации
+ * (Название неточное)
+ * Необходимо добавить методы:
+ * OperateOnCell(Cell*)
+ * OperateOnUnit(Unit*)
+ */
+class EffectsForCell;
+
+class Cell {
+private:
+	/*
+	 * Соседние клетки к текущей
+	 * nullptr, если ее не существует
+	*/
+	Cell* leftUp_;
+	Cell* left_;
+	Cell* leftDown_;
+	Cell* rightUp_;
+	Cell* right_;
+	Cell* rightDown_;
+	/*
+	 * Ссылка на любую дичь, который находится на клетке
+	 * nullptr, клетка пустая
+	 */
+	Unit* character_;
+	/*
+	 * Список всех эффектов, применённых к этой клетке
+	 * Работа с этим списком в методах ниже
+	 * Добавление, удаление, указатель на начало и конец
+	 */
+	std::vector<EffectsForCell*> effects_list_;
+	/*
+	 * isMoveAble - Можно ли попасть в данную клетку из точки пересчета
+	 * переходя только по клеткам без юнитов
+	 * isMeleeAttackAble - Можно ли атаковать данную клетку
+	 * isRangeAttackAble_;
+	 */
+	bool isMoveAble_;
+	bool isMeleeAttackAble_;
+	bool isRangeAttackAble_;
+	/*
+	 * Расстояние от точки пересчёта до текущей точки
+	 * distance_barrier - расстояние с учетом других препятствий
+	 * distance_through - расстояние без учета препятствий
+	 * -1, если недостижимо
+	 */
+	int distance_barrier_;
+	int distance_through_;
+private:
+    /*
+     * Локальные методы и переменные
+     */
+	bool AddedToQuery_;
+	void clearTable_();
+	void clearCell_();
+	void recalcAttackable_();
+	void recalcMoveable_();
+	/*
+	 * BFS Moveable Cells And Find Unmoveable Cells
+	 */
+	void updateMoveableCells_(std::queue<Cell *> &Q);
+	/*
+	 * BFS UnMoveable Cells
+	 */
+	void updateUnMovealeCells_(std::queue<Cell *> &Q);
+
+public:
+
+	explicit Cell(Unit * character);
+	/*
+	 * Геттеры и сеттеры соседних клеток и персонажа
+	 */
+	Cell* getleftUp();
+	void setleftUp(Cell*);
+	Cell* getleft();
+	void setleft(Cell*);
+	Cell* getleftDown();
+	void setleftDown(Cell*);
+	Cell* getrightUp();
+	void setrightUp(Cell*);
+	Cell* getright();
+	void setright(Cell*);
+	Cell* getrightDown();
+	void setrightDown(Cell *);
+	Unit* getCharacter();
+	void setCharacter(Unit *);
+	/*
+	 * Ещё геттеры и сеттеры
+	 */
+    int getdistance_barrier();
+    void setdistance_barrier(int);
+    int getdistance_through();
+    void setdistance_through(int);
+    /*
+     * Нужно больше геттеров и сеттеров
+     */
+    bool getisMoveAble();
+	void setisMoveAble(bool);
+	bool getisMeleeAttackAble();
+	void setisMeleeAttackAble(bool);
+	bool getisRangeAttackAble();
+	void setisRangeAttackAble(bool);
+	/*
+	 * Содержит ли текущая клетка unit
+	 */
+	bool isEmpty();
+	/*
+	 * Методы для работы с эффектами
+	 */
+	void recalculateAllEffectsList();
+	void add(EffectsForCell*);
+	void remove(std::vector<EffectsForCell*>::iterator);
+	void remove(EffectsForCell*);
+	std::vector<EffectsForCell*>::iterator beginIteratorEffectsList();
+	std::vector<EffectsForCell*>::iterator endIteratorEffectsList();
+	/*
+	 * Пересчитывает ВСЁ поле, делая текущую клетку - точкой пересчета
+	 */
+	void RecalculateTableWithCenterThisPoint();
+	/*
+	 * Работает корректно только в случае, если текущая - точка пересчета
+	 * Возвращает список всех клеток от параметра до точки пересчета
+	 * Включает в себя и начало, и конец
+	 * При этом список составлен в порядке прохода, начиная с последнего
+	 * Если пути нету, то вернется пустой список
+	 */
+	std::vector <Cell*> actualPath(Cell*);
+};

+ 284 - 0
source/Cell.cpp

@@ -0,0 +1,284 @@
+#include "Cell.h"
+#include <assert.h>
+#include <string>
+#include <string.h>
+//#include "unit.h"
+#include <queue>
+#include <vector>
+
+class Unit{
+public:
+    bool CanMoveForDistance(int distance){
+        return true;
+    }
+    /*
+    template<std::string AttackType>
+    bool CanAttackForDistance(int distance){
+        return true;
+    }
+    bool CanAttackForDistance<"Melee">(int distance){
+        return true;
+    }
+    bool CanAttackForDistance<"Range">(int distance){
+        return true;
+    }*/
+};
+
+class EffectsForCell{
+public:
+	void OperateOnCell(Cell*){}
+};
+
+Cell::Cell(Unit* character) {
+	leftUp_ = left_ = leftDown_ = nullptr;
+	rightUp_ = right_ = rightDown_ = nullptr;
+	character_ = character;
+	clearCell_();
+	AddedToQuery_ = 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;
+}
+Unit * Cell::getCharacter() {
+	return character_;
+}
+void Cell::setCharacter(Unit * t) {
+	character_ = t;
+}
+
+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_ == NULL;
+}
+
+void Cell::recalculateAllEffectsList(){
+    for(std::vector<EffectsForCell*>::iterator it = beginIteratorEffectsList();
+            it != endIteratorEffectsList();++it){
+        (*it)->OperateOnCell(this);
+    }
+}
+void Cell::add(EffectsForCell* effect){
+    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*> qWithoutMoveable;
+    updateMoveableCells_(qWithoutMoveable);
+    updateUnMovealeCells_(qWithoutMoveable);
+}
+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;
+            }
+        };
+        assert(parent != nullptr);
+        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);
+}
+
+void Cell::clearTable_() {
+	std::queue<Cell*> q;
+	q.push(this);
+	clearCell_();
+	setdistance_through(0);
+	this->AddedToQuery_ = false;
+	auto f = [&q](Cell * t, Cell * parent) {
+		if (t && t->AddedToQuery_ == true) {
+			q.push(t);
+			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);
+		f(Now->getleft(), Now);
+		f(Now->getleftDown(), Now);
+		f(Now->getrightUp(), Now);
+		f(Now->getright(), Now);
+		f(Now->getrightDown(), Now);
+	}
+}
+
+void Cell::recalcAttackable_(Cell * Now){
+    if(Now == nullptr)return;
+    if (!isEmpty() && !Now->isEmpty() &&
+        getCharacter()->CanAttackForDistance<"Melee">(Now->getdistance_barrier())
+            ) {
+        Now->setisMeleeAttackAble(true);
+    }
+    if (!isEmpty() && !Now->isEmpty() &&
+        getCharacter()->CanAttackForDistance<"Range">(Now->getdistance_barrier())
+            ) {
+        Now->setisRangeAttackAble(true);
+    }
+}
+
+void Cell::recalcMoveable_(Cell * Now){
+    if(Now == nullptr || Now->isEmpty() || isEmpty())return;
+    getCharacter()->CanMoveForDistance()
+}
+
+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();
+		Now->setisMoveAble();
+		recalcAttackable_(Now);
+		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);
+	}
+}
+
+void Cell::updateUnMovealeCells_(std::queue<Cell*> & Q) {
+	auto f = [&Q](Cell * t, Cell * parent) {
+		if (t && !t->AddedToQuery_) {
+			t->AddedToQuery_ = true;
+			Q.push(t);
+		}
+	};
+	while (!Q.empty()) {
+		Cell * Now = Q.front();
+		Now->setisMoveable(false);
+		Now->setisAttackable(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);
+	}
+}