summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--HexBoard.gd51
-rw-r--r--Piece.gd8
-rw-r--r--Tile.gd5
-rw-r--r--Unit.gd4
4 files changed, 47 insertions, 21 deletions
diff --git a/HexBoard.gd b/HexBoard.gd
index 373bda5..993776d 100644
--- a/HexBoard.gd
+++ b/HexBoard.gd
@@ -6,6 +6,7 @@ class_name HexBoard, "res://godot/HexBoard.png"
enum Orientation { E=1, NE=2, N=4, NW=8, W=16, SW=32, S=64, SE=128 }
const IMAX : int = 9999999999
+const DEGREE_ADJ : int = 2
var bt : Vector2 # bottom corner
var cr : Vector2 # column, row
@@ -61,30 +62,37 @@ func configure(cols : int, rows : int, side : float, v0 : Vector2, vertical : bo
angles[Orientation.N] = 270
angles[Orientation.NE] = 330
+# the number of Tile
func size() -> int:
return int(cr.y) / 2 * tl + int(cr.y) % 2 * int(cr.x)
+# fetch a Tile given it's col;row coordinates
func get_tile(coords : Vector2) -> Tile:
return tile_factory_fct.call_func(coords, key(coords))
-func to_angle(o : int) -> int:
+# Orientation to degrees
+func to_degrees(o : int) -> int:
return angles.get(o, -1)
+# convert the given angle between 2 adjacent Tiles into an Orientation
func to_orientation(a : float) -> int:
for k in angles.keys():
if angles[k] == a:
return k
return -1
+# compute the angle between 2 adjacent Tiles
func angle(from : Tile, to : Tile) -> int:
- var a : float = rad2deg((to.position - from.position).angle()) + 2
+ var a : float = rad2deg((to.position - from.position).angle()) + DEGREE_ADJ
if a < 0: a += 360
return int(a / 10) * 10
+# return the opposite of a given Orientation
func opposite(o : int) -> int:
if o <= Orientation.NW: return o << 4
return o >> 4
+# return the key of a given col;row coordinate
func key(coords : Vector2) -> int:
if not is_on_map(coords): return -1
if v: return _key(int(coords.x), int(coords.y))
@@ -97,6 +105,7 @@ func _key(x : int, y : int) -> int:
i += (int(cr.x) - 1)
return i
+# build the 6 adjacent Tiles of a Tile given by it's col;row coordinates
func build_adjacents(coords : Vector2) -> Array:
adjacents.clear()
coords.x += 1
@@ -114,6 +123,7 @@ func build_adjacents(coords : Vector2) -> Array:
adjacents.append(get_tile(coords))
return adjacents
+# return true if the Tile is on the map
func is_on_map(coords : Vector2) -> bool:
if v: return _is_on_map(int(coords.x), int(coords.y))
else: return _is_on_map(int(coords.y), int(coords.x))
@@ -123,10 +133,12 @@ func _is_on_map(x : int, y : int) -> bool:
if (x < ((y + 1) / 2)) || (x >= (int(cr.x) + (y / 2))): return false
return true
+# compute the center of a Tile given by it's col;row coordinates
func center_of(coords : Vector2) -> Vector2:
if v: return Vector2(bt.x + dw + (coords.x * w) - (coords.y * dw), bt.y + dh + (coords.y * h))
else: return Vector2(bt.y + dh + (coords.x * h), bt.x + dw + (coords.y * w) - (coords.x * dw))
+# compute the col;row coordinates of a Tile given it's real coordinates
func to_map(r : Vector2) -> Vector2:
if v: return _to_map(r.x, r.y, false)
else: return _to_map(r.y, r.x, true)
@@ -161,6 +173,7 @@ func _to_map(x : float, y : float, swap : bool) -> Vector2:
if swap: return Vector2(row, col)
else: return Vector2(col, row)
+# compute the distance between 2 Tiles given by their col;row coordinates
func distance(p0 : Vector2, p1 : Vector2, euclidean : bool = true) -> float:
var dx : int = int(p1.x - p0.x)
var dy : int = int(p1.y - p0.y)
@@ -180,6 +193,8 @@ func distance(p0 : Vector2, p1 : Vector2, euclidean : bool = true) -> float:
# http://zvold.blogspot.com/2010/01/bresenhams-line-drawing-algorithm-on_26.html
# http://zvold.blogspot.com/2010/02/line-of-sight-on-hexagonal-grid.html
+# compute as an Array, the line of sight between 2 Tiles given by their col;row coordinates
+# return the point after which the line of sight is blocked
func line_of_sight(p0 : Vector2, p1 : Vector2, tiles : Array) -> Vector2:
tiles.clear()
# orthogonal projection
@@ -201,7 +216,7 @@ func line_of_sight(p0 : Vector2, p1 : Vector2, tiles : Array) -> Vector2:
var dy3 : int = 3 * dy
# check for diagonals
if dx == 0 || dx == dy3:
- return diagonal_los(p0, p1, (dx == 0), q13, tiles)
+ return _diagonal_los(p0, p1, (dx == 0), q13, tiles)
# angle is less than 45°
var flat : bool = dx > dy3
var x : int = int(p0.x)
@@ -242,14 +257,14 @@ func line_of_sight(p0 : Vector2, p1 : Vector2, tiles : Array) -> Vector2:
if los_blocked and not contact:
var prev : Tile = tiles[tiles.size() - 1]
var o : int = to_orientation(angle(prev, t))
- ret = compute_contact(from.position, to.position, prev.position, o)
+ ret = _compute_contact(from.position, to.position, prev.position, o)
contact = true
tiles.append(t)
t.blocked = los_blocked
los_blocked = los_blocked or t.block_los(from, to, d, distance(p0, q))
return ret
-func diagonal_los(p0 : Vector2, p1 : Vector2, flat : bool, q13 : bool, tiles : Array) -> Vector2:
+func _diagonal_los(p0 : Vector2, p1 : Vector2, flat : bool, q13 : bool, tiles : Array) -> Vector2:
var dy : int = 1 if p1.y > p0.y else -1
var dx : int = 1 if p1.x > p0.x else -1
var x : int = int(p0.x)
@@ -300,16 +315,16 @@ func diagonal_los(p0 : Vector2, p1 : Vector2, flat : bool, q13 : bool, tiles : A
tiles.append(t)
t.blocked = los_blocked || blocked == 0x03
if t.blocked and not contact:
- var o : int = compute_orientation(dx, dy, flat)
+ var o : int = _compute_orientation(dx, dy, flat)
if not los_blocked and blocked == 0x03:
- ret = compute_contact(from.position, to.position, t.position, opposite(o))
+ ret = _compute_contact(from.position, to.position, t.position, opposite(o))
else:
- ret = compute_contact(from.position, to.position, tiles[tiles.size() - idx].position, o)
+ ret = _compute_contact(from.position, to.position, tiles[tiles.size() - idx].position, o)
contact = true;
los_blocked = t.blocked || t.block_los(from, to, d, distance(p0, q))
return ret
-func compute_orientation(dx :int, dy :int, flat : bool) -> int:
+func _compute_orientation(dx :int, dy :int, flat : bool) -> int:
if flat:
if v: return Orientation.S if dy == 1 else Orientation.N
else: return Orientation.S if dx == 1 else Orientation.N
@@ -320,7 +335,7 @@ func compute_orientation(dx :int, dy :int, flat : bool) -> int:
if dy == 1: return Orientation.W if v else Orientation.S
else: return Orientation.W
-func compute_contact(from : Vector2, to : Vector2, t : Vector2, o : int) -> Vector2:
+func _compute_contact(from : Vector2, to : Vector2, t : Vector2, o : int) -> Vector2:
var dx : float = to.x - from.x
var dy : float = to.y - from.y
var n : float = float(IMAX) if dx == 0 else (dy / dx)
@@ -358,14 +373,16 @@ func compute_contact(from : Vector2, to : Vector2, t : Vector2, o : int) -> Vect
var x : float = (k - c) / (n - p)
return Vector2(x, n * x + c);
+# compute as an Array, the Tiles that can be reached by a given Piece from a Tile given by it's col;row coordinates
+# return the size of the built Array
func possible_moves(piece : Piece, from : Tile, tiles : Array) -> int:
tiles.clear()
+ if piece.get_mp() <= 0 or not is_on_map(from.coords): return 0
+ var road_march_bonus : int = piece.road_march_bonus()
search_count += 1
- from.acc = piece.get_mp()
from.parent = null
+ from.acc = piece.get_mp()
from.search_count = search_count
- if from.acc <= 0 or not is_on_map(from.coords): return 0
- var road_march_bonus : int = piece.road_march_bonus()
from.road_march = road_march_bonus > 0
stack.push_back(from)
while(not stack.empty()):
@@ -381,7 +398,7 @@ func possible_moves(piece : Piece, from : Tile, tiles : Array) -> int:
var r : int = src.acc - cost
var rm : bool = src.road_march and src.has_road(o)
# not enough MP even with RM, maybe first move allowed
- if ((r + (road_march_bonus if rm else 0)) < 0 and not (src == from and piece.at_least_one_tile())): continue
+ if ((r + (road_march_bonus if rm else 0)) < 0 and not (src == from and piece.at_least_one_tile(dst))): continue
if dst.search_count != search_count:
dst.search_count = search_count
dst.acc = r
@@ -396,14 +413,16 @@ func possible_moves(piece : Piece, from : Tile, tiles : Array) -> int:
stack.push_back(dst)
return tiles.size()
+# compute as an Array, the shortest path for a given Piece from a Tile to another given by there col;row coordinates
+# return the size of the built Array
func shortest_path(piece : Piece, from : Tile, to : Tile, tiles : Array) -> int:
tiles.clear()
+ if from == to or not is_on_map(from.coords) or not is_on_map(to.coords): return tiles.size()
+ var road_march_bonus : int = piece.road_march_bonus()
search_count += 1
from.acc = 0
from.parent = null
from.search_count = search_count
- if from == to or not is_on_map(from.coords) or not is_on_map(to.coords): return tiles.size()
- var road_march_bonus : int = piece.road_march_bonus()
from.road_march = road_march_bonus > 0
stack.push_back(from)
while(not stack.empty()):
diff --git a/Piece.gd b/Piece.gd
index 50baa43..1a9e357 100644
--- a/Piece.gd
+++ b/Piece.gd
@@ -3,18 +3,22 @@ extends Node2D
class_name Piece, "res://godot/Piece.png"
+# movement points
func get_mp() -> int:
print("Piece#get_mp() must be overriden in a subclass")
return 0
+# movement point bonus if you start your movement on a road and follow it
func road_march_bonus() -> int:
print("Piece#road_march_bonus() must be overriden in a subclass")
return 0
-func move_cost(src : Tile, dst : Tile, a : int) -> int:
+# movement cost from a Tile to another adjacent Tile
+func move_cost(src : Tile, dst : Tile, orientation : int) -> int:
print("Piece#move_cost() must be overriden in a subclass")
return -1 # impracticable
-func at_least_one_tile() -> bool:
+# are you allowed to move into that Tile as only move even if you don't have enough movement points
+func at_least_one_tile(dst : Tile) -> bool:
print("Piece#at_least_one_tile() must be overriden in a subclass")
return true
diff --git a/Tile.gd b/Tile.gd
index 0aaa0de..a3285e5 100644
--- a/Tile.gd
+++ b/Tile.gd
@@ -24,10 +24,13 @@ func configure(p : Vector2, c: Vector2, o :Array) -> void:
add_child(s)
visible = false
-func has_road(a) -> bool:
+# is there a road with given orientation that drives out of that Tile
+func has_road(orientation : int) -> bool:
print("Tile#has_road() must be overriden in a subclass")
return false
+# is the line of sight blocked from a Tile to another, d beeing the distance between from and to,
+# dt beeing the distance between from and this Tile
func block_los(from : Tile, to : Tile, d : float, dt : float) -> bool:
print("Tile#block_los() must be overriden in a subclass")
return false
diff --git a/Unit.gd b/Unit.gd
index cda26c8..e699f61 100644
--- a/Unit.gd
+++ b/Unit.gd
@@ -9,5 +9,5 @@ func get_mp() -> int:
func road_march_bonus() -> int:
return 2
-func move_cost(src : Tile, dst : Tile, o : int) -> int:
- return (1 if (src.has_road(o) and dst.type != 3) else dst.cost())
+func move_cost(src : Tile, dst : Tile, orientation : int) -> int:
+ return (1 if (src.has_road(orientation) and dst.type != 3) else dst.cost())