summaryrefslogtreecommitdiffstats
path: root/demo
diff options
context:
space:
mode:
authorJérémy Zurcher <jeremy@asynk.ch>2020-07-20 12:26:48 +0200
committerJérémy Zurcher <jeremy@asynk.ch>2020-07-20 12:26:48 +0200
commit89723ca94bd21f1ae14592a682e9c0e5c5f04a74 (patch)
tree7b5c67f9d05f253abc961c901336780755543d6d /demo
parentf3c455fbfb8b28b095c161eb7769ed92f1acb862 (diff)
downloadgodot-hexgrid-89723ca94bd21f1ae14592a682e9c0e5c5f04a74.zip
godot-hexgrid-89723ca94bd21f1ae14592a682e9c0e5c5f04a74.tar.gz
move demo files into subdir demo
Diffstat (limited to 'demo')
-rw-r--r--demo/Camera.gd36
-rw-r--r--demo/Hex.gd80
-rw-r--r--demo/Los.gd21
-rw-r--r--demo/Main.gd65
-rw-r--r--demo/Main.tscn155
-rw-r--r--demo/Map.gd174
-rw-r--r--demo/Map.tscn4
-rw-r--r--demo/Unit.gd25
8 files changed, 560 insertions, 0 deletions
diff --git a/demo/Camera.gd b/demo/Camera.gd
new file mode 100644
index 0000000..0dc6074
--- /dev/null
+++ b/demo/Camera.gd
@@ -0,0 +1,36 @@
+extends Camera2D
+
+var margin :Vector2
+var window : Vector2
+var map_center : Vector2
+var texture_size : Vector2
+var zoom_boundaries : Vector2
+
+func _ready():
+ margin = Vector2(0, 0)
+
+func configure(w : Vector2, c : Vector2, ts : Vector2) -> void:
+ window = w
+ map_center = c
+ texture_size = ts
+ var zout : float = max((texture_size.x + margin.x) / window.x, (texture_size.y + margin.y) / window.y)
+ zoom_boundaries = Vector2(zout - 0.5, zout)
+ update_camera(0, 0, zoom_boundaries.y)
+
+func update_camera(x : float, y : float, z : float) -> void:
+ if z != 0:
+ zoom.x = clamp(zoom.x + z, zoom_boundaries.x, zoom_boundaries.y)
+ zoom.y = zoom.x
+ position.x += x
+ position.y += y
+ var delta = texture_size + margin - (window * zoom.x)
+ if (delta.x <= 0):
+ position.x = map_center.x
+ else:
+ var dx = int(delta.x / 2)
+ position.x = clamp(position.x, map_center.x - dx, map_center.x + dx)
+ if (delta.y <= 0):
+ position.y = map_center.y
+ else:
+ var dy = int(delta.y / 2)
+ position.y = clamp(position.y, map_center.y - dy, map_center.y + dy)
diff --git a/demo/Hex.gd b/demo/Hex.gd
new file mode 100644
index 0000000..99bdbd2
--- /dev/null
+++ b/demo/Hex.gd
@@ -0,0 +1,80 @@
+#warning-ignore-all:unused_argument
+extends Tile
+
+class_name Hex, "res://godot/Tile.png"
+
+var type : int = -1
+var roads : int = 0
+
+func _ready() -> void:
+ type = -1
+
+func inspect() -> String:
+ var s : String = 'plain'
+ if type == 0: s = 'city'
+ elif type == 1: s = 'wood'
+ elif type == 2: s = 'mountain'
+ elif type == 3: s = 'blocked'
+ return "[%d;%d]\n -> (%d;%d)\n -> %s\ne:%d h:%d c:%d r:%d" % [coords.x, coords.y, position.x, position.y, s, elevation(), height(), cost(), roads]
+
+func has_road(o : int) -> bool:
+ return (o & roads) > 0
+
+func change() -> void:
+ type = (type + 2) % 5 - 1
+ for i in range(4):
+ enable_overlay(i + 3, i == type)
+
+func cost() -> int:
+ if type == -1: return 1
+ elif type == 3: return -1
+ return type + 1
+
+func height() -> int:
+ if type == 0: return 2
+ elif type == 1: return 1
+ elif type == 2: return 0
+ return 0
+
+func elevation() -> int:
+ if type == 2: return 3
+ return 0
+
+func range_modifier(category : int) -> int:
+ return (1 if type == 2 else 0)
+
+func attack_modifier(category : int, orientation : int) -> int:
+ return (2 if type == 1 else 0)
+
+func defense_value(category : int, orientation : int) -> int:
+ if type == 0: return 2
+ elif type == 1: return 1
+ elif type == 2: return 1
+ return 0
+
+func block_los(from : Tile, to : Tile, d : float, dt : float) -> bool:
+ var h : int = height() + elevation()
+ if h == 0: return false
+ var e : int = from.elevation()
+ if e > h:
+ if to.elevation() > h: return false
+ return (h * dt / (e - h)) >= (d - dt)
+ h -= e
+ return ((h * d / dt) >= to.elevation() - e)
+
+func show_los(b) -> void:
+ if b: enable_overlay((2 if blocked else 1), true)
+ else:
+ enable_overlay(1, false)
+ enable_overlay(2, false)
+
+func show_move(b) -> void:
+ enable_overlay(7, b)
+
+func show_short(b) -> void:
+ enable_overlay(8, b)
+
+func show_influence(b) -> void:
+ var s : Sprite = get_child(0)
+ s.modulate = Color(f/10.0, 0, 0)
+ enable_overlay(0, b)
diff --git a/demo/Los.gd b/demo/Los.gd
new file mode 100644
index 0000000..324819a
--- /dev/null
+++ b/demo/Los.gd
@@ -0,0 +1,21 @@
+extends Node2D
+
+var p0 : Vector2
+var p1 : Vector2
+var p2 : Vector2
+
+func _ready():
+ pass
+
+func _draw() -> void:
+ if p2.x == -1:
+ draw_line(p0, p1, Color(0, 255, 0))
+ else:
+ draw_line(p0, p2, Color(0, 255, 0))
+ draw_line(p2, p1, Color(255, 0, 0))
+
+func setup(v0 :Vector2, v1 : Vector2, v2 : Vector2) -> void:
+ p0 = v0
+ p1 = v1
+ p2 = v2
+ update()
diff --git a/demo/Main.gd b/demo/Main.gd
new file mode 100644
index 0000000..42b52a9
--- /dev/null
+++ b/demo/Main.gd
@@ -0,0 +1,65 @@
+#warning-ignore-all:return_value_discarded
+extends Node2D
+
+var moved : int = 0
+var drag_map : bool = false
+
+onready var UI : Control = $CanvasLayer/HBOX/UI
+onready var Map : Sprite = $CanvasLayer/HBOX/ViewportContainer/Viewport/Map
+onready var Camera : Camera2D = $CanvasLayer/HBOX/ViewportContainer/Viewport/Camera
+
+func _ready():
+ UI.get_node("rotate").connect("pressed", self, "on_rotate")
+ UI.get_node("zin").connect("pressed", self, "on_zoom", [true])
+ UI.get_node("zout").connect("pressed", self, "on_zoom", [false])
+ UI.get_node("LOS").connect("pressed", self, "on_toggle")
+ UI.get_node("Move").connect("pressed", self, "on_toggle")
+ UI.get_node("Influence").connect("pressed", self, "on_toggle")
+ Map.connect("hex_touched", self, "on_hex_touched")
+ $CanvasLayer/HBOX/ViewportContainer.connect("resized", self, "on_viewport_resized")
+ on_toggle()
+ yield(get_tree().create_timer(.2), 'timeout')
+ on_viewport_resized()
+ UI.get_node("OSInfo").text = "screen\n%s\ndpi %d" % [OS.get_screen_size(), OS.get_screen_dpi()]
+
+func on_viewport_resized() -> void:
+ Camera.configure($CanvasLayer/HBOX/ViewportContainer/Viewport.size, Map.center(), Map.texture_size())
+
+func on_rotate() -> void:
+ Map.rotate_map()
+ on_viewport_resized()
+
+func on_zoom(b : bool) -> void:
+ Camera.update_camera(0, 0, -0.05 if b else 0.05)
+
+func on_toggle() -> void:
+ Map.set_mode(UI.get_node("LOS").pressed, UI.get_node("Move").pressed, UI.get_node("Influence").pressed)
+
+func on_hex_touched(pos : Vector2, hex : Hex, key : int) -> void:
+ var s : String = ("offmap" if key == -1 else hex.inspect())
+ UI.get_node("Info").set_text("\n(%d;%d)\n -> %s\n -> %d" % [int(pos.x), int(pos.y), s, key])
+
+func _unhandled_input(event : InputEvent) -> void:
+ if event is InputEventMouseMotion:
+ if drag_map:
+ var dv : Vector2 = event.relative * Camera.zoom
+ Camera.update_camera(-dv.x, -dv.y, 0)
+ moved += 1
+ else:
+ Map.on_mouse_move()
+ elif event is InputEventMouseButton:
+ if event.button_index == 1:
+ if moved < 5:
+ drag_map = Map.on_click(event.pressed)
+ else:
+ drag_map = false
+ moved = 0
+ elif event.button_index == 3:
+ drag_map = event.pressed
+ elif event.button_index == 4:
+ on_zoom(true)
+ elif event.button_index == 5:
+ on_zoom(false)
+ elif event is InputEventKey:
+ if event.scancode == KEY_ESCAPE:
+ get_tree().quit()
diff --git a/demo/Main.tscn b/demo/Main.tscn
new file mode 100644
index 0000000..6fa7f31
--- /dev/null
+++ b/demo/Main.tscn
@@ -0,0 +1,155 @@
+[gd_scene load_steps=10 format=2]
+
+[ext_resource path="res://demo/Camera.gd" type="Script" id=1]
+[ext_resource path="res://assets/Anke.otf" type="DynamicFontData" id=2]
+[ext_resource path="res://assets/target.png" type="Texture" id=3]
+[ext_resource path="res://demo/Map.gd" type="Script" id=4]
+[ext_resource path="res://demo/Los.gd" type="Script" id=5]
+[ext_resource path="res://assets/tank.png" type="Texture" id=6]
+[ext_resource path="res://demo/Main.gd" type="Script" id=7]
+
+[sub_resource type="DynamicFont" id=1]
+size = 35
+font_data = ExtResource( 2 )
+
+[sub_resource type="Theme" id=2]
+default_font = SubResource( 1 )
+
+[node name="Main" type="Node2D"]
+script = ExtResource( 7 )
+
+[node name="CanvasLayer" type="CanvasLayer" parent="."]
+
+[node name="HBOX" type="HBoxContainer" parent="CanvasLayer"]
+anchor_right = 1.0
+anchor_bottom = 1.0
+mouse_filter = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="ViewportContainer" type="ViewportContainer" parent="CanvasLayer/HBOX"]
+margin_right = 1666.0
+margin_bottom = 1080.0
+rect_min_size = Vector2( 100, 100 )
+mouse_filter = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+stretch = true
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="Viewport" type="Viewport" parent="CanvasLayer/HBOX/ViewportContainer"]
+size = Vector2( 1666, 1080 )
+handle_input_locally = false
+render_target_update_mode = 3
+
+[node name="Map" type="Sprite" parent="CanvasLayer/HBOX/ViewportContainer/Viewport"]
+script = ExtResource( 4 )
+
+[node name="Hexes" type="Node" parent="CanvasLayer/HBOX/ViewportContainer/Viewport/Map"]
+
+[node name="Target" type="Sprite" parent="CanvasLayer/HBOX/ViewportContainer/Viewport/Map"]
+z_index = 1
+texture = ExtResource( 3 )
+
+[node name="Tank" type="Sprite" parent="CanvasLayer/HBOX/ViewportContainer/Viewport/Map"]
+z_index = 1
+texture = ExtResource( 6 )
+
+[node name="Los" type="Node2D" parent="CanvasLayer/HBOX/ViewportContainer/Viewport/Map"]
+script = ExtResource( 5 )
+
+[node name="Camera" type="Camera2D" parent="CanvasLayer/HBOX/ViewportContainer/Viewport"]
+current = true
+script = ExtResource( 1 )
+
+[node name="UI" type="VBoxContainer" parent="CanvasLayer/HBOX"]
+margin_left = 1670.0
+margin_right = 1920.0
+margin_bottom = 1080.0
+rect_min_size = Vector2( 250, 0 )
+theme = SubResource( 2 )
+custom_constants/separation = 30
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="rotate" type="Button" parent="CanvasLayer/HBOX/UI"]
+margin_right = 250.0
+margin_bottom = 100.0
+rect_min_size = Vector2( 0, 100 )
+size_flags_horizontal = 3
+text = "Rotate"
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="zin" type="Button" parent="CanvasLayer/HBOX/UI"]
+margin_top = 130.0
+margin_right = 250.0
+margin_bottom = 230.0
+rect_min_size = Vector2( 0, 100 )
+size_flags_horizontal = 3
+text = "Z IN"
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="zout" type="Button" parent="CanvasLayer/HBOX/UI"]
+margin_top = 260.0
+margin_right = 250.0
+margin_bottom = 360.0
+rect_min_size = Vector2( 0, 100 )
+size_flags_horizontal = 3
+text = "Z OUT"
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="LOS" type="CheckBox" parent="CanvasLayer/HBOX/UI"]
+margin_top = 390.0
+margin_right = 250.0
+margin_bottom = 434.0
+pressed = true
+text = "LOS"
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="Move" type="CheckBox" parent="CanvasLayer/HBOX/UI"]
+margin_top = 464.0
+margin_right = 250.0
+margin_bottom = 508.0
+text = "Move"
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="Influence" type="CheckBox" parent="CanvasLayer/HBOX/UI"]
+margin_top = 538.0
+margin_right = 250.0
+margin_bottom = 582.0
+text = "Influence"
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="Info" type="Label" parent="CanvasLayer/HBOX/UI"]
+margin_top = 612.0
+margin_right = 250.0
+margin_bottom = 648.0
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="OSInfo" type="Label" parent="CanvasLayer/HBOX/UI"]
+margin_top = 678.0
+margin_right = 250.0
+margin_bottom = 714.0
+__meta__ = {
+"_edit_use_anchors_": false
+}
diff --git a/demo/Map.gd b/demo/Map.gd
new file mode 100644
index 0000000..81c5c36
--- /dev/null
+++ b/demo/Map.gd
@@ -0,0 +1,174 @@
+extends Sprite
+
+signal hex_touched(pos, hex, key)
+
+const MAPH : String = "res://assets/map-h.png"
+const MAPV : String = "res://assets/map-v.png"
+const BLOCK : String = "res://assets/block.png"
+const BLACK : String = "res://assets/black.png"
+const MOVE : String = "res://assets/move.png"
+const SHORT : String = "res://assets/short.png"
+const RED : String = "res://assets/red.png"
+const GREEN : String = "res://assets/green.png"
+const TREE : String = "res://assets/tree.png"
+const CITY : String = "res://assets/city.png"
+const MOUNT : String = "res://assets/mountain.png"
+
+var drag : Sprite
+
+var board : HexBoard
+var prev : Vector2
+var hexes : Dictionary
+var hex_rotation : int
+var p0 : Vector2
+var p1 : Vector2
+var los : Array
+var move : Array
+var short : Array
+var influence : Array
+var unit : Unit
+var show_los : bool
+var show_move : bool
+var show_influence : bool
+
+func _ready():
+ drag = null
+ unit = Unit.new()
+ board = HexBoard.new()
+ board.tile_factory_fct = funcref(self, "get_tile")
+ board.v = false
+ rotate_map()
+
+func reset() -> void:
+ los.clear()
+ move.clear()
+ short.clear()
+ influence.clear()
+ hexes.clear()
+ hexes[-1] = Hex.new() # off map
+ p0 = Vector2(0, 0)
+ p1 = Vector2(3, 3)
+ $Tank.position = board.center_of(p0)
+ $Target.position = board.center_of(p1)
+ for hex in $Hexes.get_children():
+ $Hexes.remove_child(hex)
+ hex.queue_free()
+ compute()
+
+func rotate_map() -> void:
+ texture = load(MAPH if board.v else MAPV)
+ configure()
+ reset()
+
+func set_mode(l : bool, m : bool, i : bool) -> void:
+ show_los = l
+ show_move = m
+ show_influence = i
+ compute()
+
+func configure() -> void:
+ var v0 : Vector2 = Vector2(50, 100)
+ if centered:
+ var ts : Vector2 = texture.get_size()
+ if board.v:
+ v0.x -= ts.y / 2
+ v0.y -= ts.x / 2
+ else:
+ v0 -= ts / 2
+ if board.v:
+ hex_rotation = 30
+ board.configure(10, 4, 100, v0, false)
+ else:
+ hex_rotation = 0
+ board.configure(10, 7, 100, v0, true)
+
+func texture_size() -> Vector2:
+ return texture.get_size()
+
+func center() -> Vector2:
+ return Vector2(0, 0) if centered else texture.get_size() / 2
+
+func on_mouse_move() -> void:
+ if drag != null:
+ drag.position = get_local_mouse_position()
+
+func on_click(pressed : bool) -> bool:
+ var pos : Vector2 = get_local_mouse_position()
+ var coords : Vector2 = board.to_map(pos)
+ if pressed:
+ notify(pos, coords)
+ prev = coords
+ if board.to_map($Tank.position) == coords:
+ drag = $Tank
+ elif board.to_map($Target.position) == coords:
+ drag = $Target
+ else:
+ return true
+ else:
+ if drag:
+ if board.is_on_map(coords):
+ drag.position = board.center_of(coords)
+ if drag == $Tank: p0 = coords
+ else: p1 = coords
+ notify(pos, coords)
+ compute()
+ else:
+ drag.position = board.center_of(prev)
+ drag = null
+ else:
+ if coords == prev and board.is_on_map(coords):
+ change_tile(coords, pos)
+ return false
+
+func change_tile(coords : Vector2, pos : Vector2) -> void:
+ var hex : Hex = board.get_tile(coords)
+ hex.change()
+ notify(pos, coords)
+ compute()
+
+func get_tile(coords : Vector2, k : int) -> Tile:
+ if hexes.has(k): return hexes[k]
+ var hex : Hex = Hex.new()
+ hex.roads = get_road(k)
+ hex.rotation_degrees = hex_rotation
+ hex.configure(board.center_of(coords), coords, [RED, GREEN, BLACK, CITY, TREE, MOUNT, BLOCK, MOVE, SHORT])
+ hexes[k] = hex
+ $Hexes.add_child(hex)
+ return hex
+
+func get_road(k : int) -> int:
+ if not board.v: return 0
+ var v : int = 0
+ v += (HexBoard.Orientation.E if k in [19,20,21,23,24,42,43,44,45,46,47] else 0)
+ v += (HexBoard.Orientation.W if k in [19,20,21,22,24,25,43,44,45,46,47] else 0)
+ v += (HexBoard.Orientation.SE if k in [22,32,42,52,62] else 0)
+ v += (HexBoard.Orientation.NW if k in [32,42,52,62] else 0)
+ v += (HexBoard.Orientation.NE if k in [7,16,25,32] else 0)
+ v += (HexBoard.Orientation.SW if k in [7,16,23] else 0)
+ return v
+
+func notify(pos : Vector2, coords : Vector2) -> void:
+ emit_signal("hex_touched", pos, board.get_tile(coords), (board.key(coords) if board.is_on_map(coords) else -1))
+
+func compute() -> void:
+ $Los.visible = false
+ for hex in los: hex.show_los(false)
+ if show_los:
+ $Los.visible = true
+ var ct : Vector2 = board.line_of_sight(p0, p1, los)
+ $Los.setup($Tank.position, $Target.position, ct)
+ for hex in los: hex.show_los(true)
+ for hex in move: hex.show_move(false)
+ for hex in short: hex.show_short(false)
+ if show_move:
+ # warning-ignore:return_value_discarded
+ board.possible_moves(unit, board.get_tile(p0), move)
+ # warning-ignore:return_value_discarded
+ board.shortest_path(unit, board.get_tile(p0), board.get_tile(p1), short)
+ for hex in move: hex.show_move(true)
+ for i in range(1, short.size() -1): short[i].show_short(true)
+ for hex in influence: hex.show_influence(false)
+ if show_influence:
+ # warning-ignore:return_value_discarded
+ board.range_of_influence(unit, board.get_tile(p0), 0, influence)
+ for hex in influence: hex.show_influence(true)
diff --git a/demo/Map.tscn b/demo/Map.tscn
new file mode 100644
index 0000000..7ebb23c
--- /dev/null
+++ b/demo/Map.tscn
@@ -0,0 +1,4 @@
+[gd_scene format=2]
+
+[node name="Map" type="Sprite"]
+centered = false
diff --git a/demo/Unit.gd b/demo/Unit.gd
new file mode 100644
index 0000000..0b67053
--- /dev/null
+++ b/demo/Unit.gd
@@ -0,0 +1,25 @@
+#warning-ignore-all:unused_argument
+extends Piece
+
+class_name Unit, "res://godot/Piece.png"
+
+func get_mp() -> int:
+ return 2
+
+func road_march_bonus() -> int:
+ return 2
+
+func move_cost(src : Tile, dst : Tile, orientation : int) -> int:
+ return (1 if (src.has_road(orientation) and dst.type != 3) else dst.cost())
+
+func max_range_of_fire(category : int, from : Tile) -> int:
+ return 6 + from.range_modifier(category)
+
+func volume_of_fire(category : int, distance : int, src : Tile, src_o : int, dst : Tile, dst_o : int) -> int:
+ var fp : int = 10
+ if distance > 6: return -1
+ elif distance > 4: fp = 4
+ elif distance > 2: fp = 7
+ fp -= src.attack_modifier(category, src_o)
+ fp -= dst.defense_value(category, dst_o)
+ return fp