diff options
author | Jérémy Zurcher <jeremy@asynk.ch> | 2020-07-20 12:26:48 +0200 |
---|---|---|
committer | Jérémy Zurcher <jeremy@asynk.ch> | 2020-07-20 12:26:48 +0200 |
commit | 89723ca94bd21f1ae14592a682e9c0e5c5f04a74 (patch) | |
tree | 7b5c67f9d05f253abc961c901336780755543d6d /demo | |
parent | f3c455fbfb8b28b095c161eb7769ed92f1acb862 (diff) | |
download | godot-hexgrid-89723ca94bd21f1ae14592a682e9c0e5c5f04a74.zip godot-hexgrid-89723ca94bd21f1ae14592a682e9c0e5c5f04a74.tar.gz |
move demo files into subdir demo
Diffstat (limited to 'demo')
-rw-r--r-- | demo/Camera.gd | 36 | ||||
-rw-r--r-- | demo/Hex.gd | 80 | ||||
-rw-r--r-- | demo/Los.gd | 21 | ||||
-rw-r--r-- | demo/Main.gd | 65 | ||||
-rw-r--r-- | demo/Main.tscn | 155 | ||||
-rw-r--r-- | demo/Map.gd | 174 | ||||
-rw-r--r-- | demo/Map.tscn | 4 | ||||
-rw-r--r-- | demo/Unit.gd | 25 |
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 |