Browse Source

Merge pull request #81267 from Chaosus/astargrid_isometric_mode

Add isometric cell shape mode to `AStarGrid2D`.
Rémi Verschelde 1 year ago
parent
commit
bbfcfe50da
3 changed files with 65 additions and 1 deletions
  1. 38 1
      core/math/a_star_grid_2d.cpp
  2. 12 0
      core/math/a_star_grid_2d.h
  3. 15 0
      doc/classes/AStarGrid2D.xml

+ 38 - 1
core/math/a_star_grid_2d.cpp

@@ -106,16 +106,45 @@ Size2 AStarGrid2D::get_cell_size() const {
 	return cell_size;
 }
 
+void AStarGrid2D::set_cell_shape(CellShape p_cell_shape) {
+	if (cell_shape == p_cell_shape) {
+		return;
+	}
+
+	ERR_FAIL_INDEX(p_cell_shape, CellShape::CELL_SHAPE_MAX);
+	cell_shape = p_cell_shape;
+	dirty = true;
+}
+
+AStarGrid2D::CellShape AStarGrid2D::get_cell_shape() const {
+	return cell_shape;
+}
+
 void AStarGrid2D::update() {
 	points.clear();
 
 	const int32_t end_x = region.get_end().x;
 	const int32_t end_y = region.get_end().y;
+	const Vector2 half_cell_size = cell_size / 2;
 
 	for (int32_t y = region.position.y; y < end_y; y++) {
 		LocalVector<Point> line;
 		for (int32_t x = region.position.x; x < end_x; x++) {
-			line.push_back(Point(Vector2i(x, y), offset + Vector2(x, y) * cell_size));
+			Vector2 v = offset;
+			switch (cell_shape) {
+				case CELL_SHAPE_ISOMETRIC_RIGHT:
+					v += half_cell_size + Vector2(x + y, y - x) * half_cell_size;
+					break;
+				case CELL_SHAPE_ISOMETRIC_DOWN:
+					v += half_cell_size + Vector2(x - y, x + y) * half_cell_size;
+					break;
+				case CELL_SHAPE_SQUARE:
+					v += Vector2(x, y) * cell_size;
+					break;
+				default:
+					break;
+			}
+			line.push_back(Point(Vector2i(x, y), v));
 		}
 		points.push_back(line);
 	}
@@ -620,6 +649,8 @@ void AStarGrid2D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_offset"), &AStarGrid2D::get_offset);
 	ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &AStarGrid2D::set_cell_size);
 	ClassDB::bind_method(D_METHOD("get_cell_size"), &AStarGrid2D::get_cell_size);
+	ClassDB::bind_method(D_METHOD("set_cell_shape", "cell_shape"), &AStarGrid2D::set_cell_shape);
+	ClassDB::bind_method(D_METHOD("get_cell_shape"), &AStarGrid2D::get_cell_shape);
 	ClassDB::bind_method(D_METHOD("is_in_bounds", "x", "y"), &AStarGrid2D::is_in_bounds);
 	ClassDB::bind_method(D_METHOD("is_in_boundsv", "id"), &AStarGrid2D::is_in_boundsv);
 	ClassDB::bind_method(D_METHOD("is_dirty"), &AStarGrid2D::is_dirty);
@@ -651,6 +682,7 @@ void AStarGrid2D::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size");
 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "cell_size"), "set_cell_size", "get_cell_size");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_shape", PROPERTY_HINT_ENUM, "Square,IsometricRight,IsometricDown"), "set_cell_shape", "get_cell_shape");
 
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "jumping_enabled"), "set_jumping_enabled", "is_jumping_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "default_compute_heuristic", PROPERTY_HINT_ENUM, "Euclidean,Manhattan,Octile,Chebyshev"), "set_default_compute_heuristic", "get_default_compute_heuristic");
@@ -668,4 +700,9 @@ void AStarGrid2D::_bind_methods() {
 	BIND_ENUM_CONSTANT(DIAGONAL_MODE_AT_LEAST_ONE_WALKABLE);
 	BIND_ENUM_CONSTANT(DIAGONAL_MODE_ONLY_IF_NO_OBSTACLES);
 	BIND_ENUM_CONSTANT(DIAGONAL_MODE_MAX);
+
+	BIND_ENUM_CONSTANT(CELL_SHAPE_SQUARE);
+	BIND_ENUM_CONSTANT(CELL_SHAPE_ISOMETRIC_RIGHT);
+	BIND_ENUM_CONSTANT(CELL_SHAPE_ISOMETRIC_DOWN);
+	BIND_ENUM_CONSTANT(CELL_SHAPE_MAX);
 }

+ 12 - 0
core/math/a_star_grid_2d.h

@@ -56,11 +56,19 @@ public:
 		HEURISTIC_MAX,
 	};
 
+	enum CellShape {
+		CELL_SHAPE_SQUARE,
+		CELL_SHAPE_ISOMETRIC_RIGHT,
+		CELL_SHAPE_ISOMETRIC_DOWN,
+		CELL_SHAPE_MAX,
+	};
+
 private:
 	Rect2i region;
 	Vector2 offset;
 	Size2 cell_size = Size2(1, 1);
 	bool dirty = false;
+	CellShape cell_shape = CELL_SHAPE_SQUARE;
 
 	bool jumping_enabled = false;
 	DiagonalMode diagonal_mode = DIAGONAL_MODE_ALWAYS;
@@ -157,6 +165,9 @@ public:
 	void set_cell_size(const Size2 &p_cell_size);
 	Size2 get_cell_size() const;
 
+	void set_cell_shape(CellShape p_cell_shape);
+	CellShape get_cell_shape() const;
+
 	void update();
 
 	bool is_in_bounds(int32_t p_x, int32_t p_y) const;
@@ -193,5 +204,6 @@ public:
 
 VARIANT_ENUM_CAST(AStarGrid2D::DiagonalMode);
 VARIANT_ENUM_CAST(AStarGrid2D::Heuristic);
+VARIANT_ENUM_CAST(AStarGrid2D::CellShape)
 
 #endif // A_STAR_GRID_2D_H

+ 15 - 0
doc/classes/AStarGrid2D.xml

@@ -157,6 +157,9 @@
 		</method>
 	</methods>
 	<members>
+		<member name="cell_shape" type="int" setter="set_cell_shape" getter="get_cell_shape" enum="AStarGrid2D.CellShape" default="0">
+			The cell shape. Affects how the positions are placed in the grid. If changed, [method update] needs to be called before finding the next path.
+		</member>
 		<member name="cell_size" type="Vector2" setter="set_cell_size" getter="get_cell_size" default="Vector2(1, 1)">
 			The size of the point cell which will be applied to calculate the resulting point position returned by [method get_point_path]. If changed, [method update] needs to be called before finding the next path.
 		</member>
@@ -238,5 +241,17 @@
 		<constant name="DIAGONAL_MODE_MAX" value="4" enum="DiagonalMode">
 			Represents the size of the [enum DiagonalMode] enum.
 		</constant>
+		<constant name="CELL_SHAPE_SQUARE" value="0" enum="CellShape">
+			Rectangular cell shape.
+		</constant>
+		<constant name="CELL_SHAPE_ISOMETRIC_RIGHT" value="1" enum="CellShape">
+			Diamond cell shape (for isometric look). Cell coordinates layout where the horizontal axis goes up-right, and the vertical one goes down-right.
+		</constant>
+		<constant name="CELL_SHAPE_ISOMETRIC_DOWN" value="2" enum="CellShape">
+			Diamond cell shape (for isometric look). Cell coordinates layout where the horizontal axis goes down-right, and the vertical one goes down-left.
+		</constant>
+		<constant name="CELL_SHAPE_MAX" value="3" enum="CellShape">
+			Represents the size of the [enum CellShape] enum.
+		</constant>
 	</constants>
 </class>