Grid wip
This commit is contained in:
parent
f816a8b886
commit
090de86455
14 changed files with 294 additions and 12 deletions
11
debug/debug_highlight_tester.gd
Normal file
11
debug/debug_highlight_tester.gd
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
extends Node2D
|
||||||
|
|
||||||
|
@export var grid: Grid
|
||||||
|
|
||||||
|
|
||||||
|
func _on_timer_timeout() -> void:
|
||||||
|
GameplaySignalBus.highlight_empty.emit(grid.raycast_empty(global_position,transform.x))
|
||||||
|
rotation_degrees += 5
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
global_position = get_global_mouse_position()
|
||||||
1
debug/debug_highlight_tester.gd.uid
Normal file
1
debug/debug_highlight_tester.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://c7i44ghoo4kqo
|
||||||
|
|
@ -15,6 +15,20 @@ run/main_scene="uid://bxt4kgs6px3t8"
|
||||||
config/features=PackedStringArray("4.6", "GL Compatibility")
|
config/features=PackedStringArray("4.6", "GL Compatibility")
|
||||||
config/icon="res://icon.svg"
|
config/icon="res://icon.svg"
|
||||||
|
|
||||||
|
[autoload]
|
||||||
|
|
||||||
|
GameplaySignalBus="*uid://cqh0t2i1slf8u"
|
||||||
|
|
||||||
|
[debug]
|
||||||
|
|
||||||
|
gdscript/warnings/integer_division=0
|
||||||
|
|
||||||
|
[display]
|
||||||
|
|
||||||
|
window/size/viewport_width=1920
|
||||||
|
window/size/viewport_height=1080
|
||||||
|
window/stretch/mode="canvas_items"
|
||||||
|
|
||||||
[internationalization]
|
[internationalization]
|
||||||
|
|
||||||
locale/translations=PackedStringArray("res://translations/units.ru.translation", "res://translations/units.en.translation")
|
locale/translations=PackedStringArray("res://translations/units.ru.translation", "res://translations/units.en.translation")
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,10 @@
|
||||||
[ext_resource type="Resource" uid="uid://e7kiu3wcf0ff" path="res://cards/resources/fosma.tres" id="3_u5sy4"]
|
[ext_resource type="Resource" uid="uid://e7kiu3wcf0ff" path="res://cards/resources/fosma.tres" id="3_u5sy4"]
|
||||||
[ext_resource type="Resource" uid="uid://djqlx7bmcs5gj" path="res://cards/resources/doh.tres" id="4_gee14"]
|
[ext_resource type="Resource" uid="uid://djqlx7bmcs5gj" path="res://cards/resources/doh.tres" id="4_gee14"]
|
||||||
[ext_resource type="Resource" uid="uid://b6kiwb0marpng" path="res://cards/resources/zlosma.tres" id="5_0tnpc"]
|
[ext_resource type="Resource" uid="uid://b6kiwb0marpng" path="res://cards/resources/zlosma.tres" id="5_0tnpc"]
|
||||||
|
[ext_resource type="Script" uid="uid://rt6mxr30u8tp" path="res://systems/grid.gd" id="7_u5sy4"]
|
||||||
|
[ext_resource type="Script" uid="uid://bmy5djjmiljhl" path="res://systems/grid_highlighter.gd" id="8_gee14"]
|
||||||
|
[ext_resource type="Script" uid="uid://c7i44ghoo4kqo" path="res://debug/debug_highlight_tester.gd" id="9_0tnpc"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://du3h8ou2sxh6s" path="res://units/fosma/fosma.png" id="10_vtaks"]
|
||||||
|
|
||||||
[node name="Game" type="Node2D" unique_id=619820575]
|
[node name="Game" type="Node2D" unique_id=619820575]
|
||||||
|
|
||||||
|
|
@ -13,9 +17,14 @@
|
||||||
texture = ExtResource("1_iywne")
|
texture = ExtResource("1_iywne")
|
||||||
centered = false
|
centered = false
|
||||||
|
|
||||||
|
[node name="Fosma" type="Sprite2D" parent="." unique_id=128278442]
|
||||||
|
position = Vector2(511, 278)
|
||||||
|
texture = ExtResource("10_vtaks")
|
||||||
|
|
||||||
[node name="PlayerInterface" type="CanvasLayer" parent="." unique_id=269857956]
|
[node name="PlayerInterface" type="CanvasLayer" parent="." unique_id=269857956]
|
||||||
|
|
||||||
[node name="Hand" type="Control" parent="PlayerInterface" unique_id=403305026]
|
[node name="Hand" type="Control" parent="PlayerInterface" unique_id=403305026]
|
||||||
|
visible = false
|
||||||
layout_mode = 3
|
layout_mode = 3
|
||||||
anchors_preset = 12
|
anchors_preset = 12
|
||||||
anchor_top = 1.0
|
anchor_top = 1.0
|
||||||
|
|
@ -31,9 +40,10 @@ layout_mode = 0
|
||||||
anchors_preset = 0
|
anchors_preset = 0
|
||||||
anchor_right = 0.0
|
anchor_right = 0.0
|
||||||
anchor_bottom = 0.0
|
anchor_bottom = 0.0
|
||||||
offset_left = 402.0
|
offset_left = 733.9999
|
||||||
offset_right = 515.0
|
offset_top = -168.99997
|
||||||
offset_bottom = 169.0
|
offset_right = 846.9999
|
||||||
|
offset_bottom = 3.0517578e-05
|
||||||
card_resource = ExtResource("3_u5sy4")
|
card_resource = ExtResource("3_u5sy4")
|
||||||
|
|
||||||
[node name="Card2" parent="PlayerInterface/Hand" unique_id=1229293312 instance=ExtResource("2_p57ef")]
|
[node name="Card2" parent="PlayerInterface/Hand" unique_id=1229293312 instance=ExtResource("2_p57ef")]
|
||||||
|
|
@ -41,9 +51,10 @@ layout_mode = 0
|
||||||
anchors_preset = 0
|
anchors_preset = 0
|
||||||
anchor_right = 0.0
|
anchor_right = 0.0
|
||||||
anchor_bottom = 0.0
|
anchor_bottom = 0.0
|
||||||
offset_left = 519.0
|
offset_left = 846.9999
|
||||||
offset_right = 632.0
|
offset_top = -168.99997
|
||||||
offset_bottom = 169.0
|
offset_right = 959.99994
|
||||||
|
offset_bottom = 3.0517578e-05
|
||||||
card_resource = ExtResource("4_gee14")
|
card_resource = ExtResource("4_gee14")
|
||||||
|
|
||||||
[node name="Card4" parent="PlayerInterface/Hand" unique_id=1427311772 instance=ExtResource("2_p57ef")]
|
[node name="Card4" parent="PlayerInterface/Hand" unique_id=1427311772 instance=ExtResource("2_p57ef")]
|
||||||
|
|
@ -51,9 +62,10 @@ layout_mode = 0
|
||||||
anchors_preset = 0
|
anchors_preset = 0
|
||||||
anchor_right = 0.0
|
anchor_right = 0.0
|
||||||
anchor_bottom = 0.0
|
anchor_bottom = 0.0
|
||||||
offset_left = 804.0
|
offset_left = 959.9999
|
||||||
offset_right = 917.0
|
offset_top = -168.99997
|
||||||
offset_bottom = 169.0
|
offset_right = 1072.9999
|
||||||
|
offset_bottom = 3.0517578e-05
|
||||||
card_resource = ExtResource("3_u5sy4")
|
card_resource = ExtResource("3_u5sy4")
|
||||||
|
|
||||||
[node name="Card3" parent="PlayerInterface/Hand" unique_id=1907397406 instance=ExtResource("2_p57ef")]
|
[node name="Card3" parent="PlayerInterface/Hand" unique_id=1907397406 instance=ExtResource("2_p57ef")]
|
||||||
|
|
@ -61,7 +73,38 @@ layout_mode = 0
|
||||||
anchors_preset = 0
|
anchors_preset = 0
|
||||||
anchor_right = 0.0
|
anchor_right = 0.0
|
||||||
anchor_bottom = 0.0
|
anchor_bottom = 0.0
|
||||||
offset_left = 636.0
|
offset_left = 1072.9998
|
||||||
offset_right = 749.0
|
offset_top = -168.99997
|
||||||
offset_bottom = 169.0
|
offset_right = 1185.9998
|
||||||
|
offset_bottom = 3.0517578e-05
|
||||||
card_resource = ExtResource("5_0tnpc")
|
card_resource = ExtResource("5_0tnpc")
|
||||||
|
|
||||||
|
[node name="Grid" type="Node2D" parent="." unique_id=1478060666 node_paths=PackedStringArray("right_border_marker")]
|
||||||
|
position = Vector2(398, 162)
|
||||||
|
script = ExtResource("7_u5sy4")
|
||||||
|
rows = 5
|
||||||
|
columns = 5
|
||||||
|
right_border_marker = NodePath("../GridMarker")
|
||||||
|
metadata/_custom_type_script = "uid://rt6mxr30u8tp"
|
||||||
|
|
||||||
|
[node name="Highlighter" type="Node2D" parent="Grid" unique_id=69750982]
|
||||||
|
script = ExtResource("8_gee14")
|
||||||
|
|
||||||
|
[node name="GridMarker" type="Marker2D" parent="." unique_id=1656515901]
|
||||||
|
position = Vector2(801, 567)
|
||||||
|
|
||||||
|
[node name="Camera2D" type="Camera2D" parent="." unique_id=1988509991]
|
||||||
|
position = Vector2(0, 142)
|
||||||
|
anchor_mode = 0
|
||||||
|
zoom = Vector2(1.5, 1.5)
|
||||||
|
|
||||||
|
[node name="HighlightTester" type="Node2D" parent="." unique_id=729091083 node_paths=PackedStringArray("grid")]
|
||||||
|
position = Vector2(602, 362)
|
||||||
|
script = ExtResource("9_0tnpc")
|
||||||
|
grid = NodePath("../Grid")
|
||||||
|
|
||||||
|
[node name="Timer" type="Timer" parent="HighlightTester" unique_id=1589504194]
|
||||||
|
wait_time = 0.1
|
||||||
|
autostart = true
|
||||||
|
|
||||||
|
[connection signal="timeout" from="HighlightTester/Timer" to="HighlightTester" method="_on_timer_timeout"]
|
||||||
|
|
|
||||||
6
systems/gameplay_signal_bus.gd
Normal file
6
systems/gameplay_signal_bus.gd
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
@warning_ignore_start("unused_signal")
|
||||||
|
|
||||||
|
signal highlight_empty(empty: Array[int])
|
||||||
|
signal highlight_units(unit: Array[int])
|
||||||
1
systems/gameplay_signal_bus.gd.uid
Normal file
1
systems/gameplay_signal_bus.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://cqh0t2i1slf8u
|
||||||
169
systems/grid.gd
Normal file
169
systems/grid.gd
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
extends Node2D
|
||||||
|
|
||||||
|
|
||||||
|
## Grid with cells in it
|
||||||
|
class_name Grid
|
||||||
|
|
||||||
|
## Out of bounds return value
|
||||||
|
const OUT_OF_BOUNDS: int = -1
|
||||||
|
|
||||||
|
## Amount of rows (max Y value)
|
||||||
|
@export var rows: int = 1
|
||||||
|
## Amount of columns (max X value)
|
||||||
|
@export var columns: int = 1
|
||||||
|
|
||||||
|
## Node that marks right down position of grid
|
||||||
|
@export var right_border_marker: Node2D
|
||||||
|
|
||||||
|
## Computed size of one cell
|
||||||
|
@onready var cell_size = (right_border_marker.global_position - global_position) / Vector2(columns,rows)
|
||||||
|
## Computed rect of grid
|
||||||
|
@onready var rect: Rect2 = Rect2(global_position,(right_border_marker.global_position - global_position))
|
||||||
|
|
||||||
|
## Array that holds units
|
||||||
|
var grid: Array[Unit] = []
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
grid.resize(rows*columns)
|
||||||
|
|
||||||
|
## Returns true if position is in bounds else returns false.
|
||||||
|
func is_position_valid(pos: Vector2) -> bool:
|
||||||
|
return rect.has_point(pos)
|
||||||
|
|
||||||
|
## Turns position into internal array index. Returns -1 if position is incorrect
|
||||||
|
func to_index(pos: Vector2) -> int:
|
||||||
|
if is_position_valid(pos) == false: return OUT_OF_BOUNDS
|
||||||
|
var snapped_position: Vector2 = (pos - global_position)/cell_size
|
||||||
|
return int(snapped_position.x) + columns * int(snapped_position.y)
|
||||||
|
|
||||||
|
## Turns index into global world position
|
||||||
|
func from_index(index: int, centered: bool = false) -> Vector2:
|
||||||
|
if index < 0 or index >= columns * rows:
|
||||||
|
return Vector2.ZERO
|
||||||
|
return Vector2(index % columns, index / columns) * cell_size + (cell_size/2.0 if centered else Vector2.ZERO)
|
||||||
|
|
||||||
|
## Snaps position through grid
|
||||||
|
func snap_position(pos: Vector2, centered: bool = false) -> Vector2:
|
||||||
|
return global_position + (pos - global_position).snapped(cell_size) + (cell_size / 2) if centered else Vector2.ZERO
|
||||||
|
|
||||||
|
## Returns position as grid snapped local coordinates
|
||||||
|
func to_snapped(pos: Vector2) -> Vector2:
|
||||||
|
if is_position_valid(pos) == false: return Vector2.ZERO
|
||||||
|
var snapped_position: Vector2 = (pos - global_position)/cell_size
|
||||||
|
return Vector2(floor(snapped_position.x),floor(snapped_position.y))
|
||||||
|
|
||||||
|
## Tries to set unit at position and returns false if unit already exists or out of bounds
|
||||||
|
func try_set_unit(pos: Vector2, unit: Unit) -> bool:
|
||||||
|
var index: int = to_index(pos)
|
||||||
|
if index == OUT_OF_BOUNDS:
|
||||||
|
return false
|
||||||
|
|
||||||
|
if grid[index] != null:
|
||||||
|
return false
|
||||||
|
|
||||||
|
grid[index] = unit
|
||||||
|
return true
|
||||||
|
|
||||||
|
## Returns true if cell is occupied or out of bounds and false if cell is empty.
|
||||||
|
func is_occupied(pos: Vector2) -> bool:
|
||||||
|
var index: int = to_index(pos)
|
||||||
|
if index == OUT_OF_BOUNDS:
|
||||||
|
return true
|
||||||
|
|
||||||
|
return grid[index] != null
|
||||||
|
|
||||||
|
## Returns units with given rule predicate.[br]
|
||||||
|
## rule - predicate with signature [code](x,y,source_x,source_y)[/code] -> bool
|
||||||
|
## that needs to return true if cell needs to be checked.[br]
|
||||||
|
## unit - source unit.
|
||||||
|
func get_units(rule: Callable,unit: Unit) -> Array[Unit]:
|
||||||
|
var unit_pos = to_snapped(unit.global_position)
|
||||||
|
var result: Array[Unit] = []
|
||||||
|
for i in range(columns * rows):
|
||||||
|
if rule.call(i%columns,i/columns,int(unit_pos.x),int(unit_pos.y)) and grid[i] != null:
|
||||||
|
result.append(grid[i])
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
## WIP[br]
|
||||||
|
## Returns units with given rule predicate. Checks from source unit with rays and stops only when ray failed.[br]
|
||||||
|
## rule - predicate with signature [code](x,y,source_x,source_y)[/code] -> bool
|
||||||
|
## that needs to return true if cell needs to be checked.[br]
|
||||||
|
## unit - source unit.[br]
|
||||||
|
## rays - amount of rays to check from unit.
|
||||||
|
func get_units_stoppable(rule: Callable, unit: Unit, rays: int = 8) -> Array[Unit]:
|
||||||
|
return []
|
||||||
|
|
||||||
|
## Returns empty cells with given rule predicate.[br]
|
||||||
|
## rule - predicate with signature [code](x,y,source_x,source_y)[/code] -> bool
|
||||||
|
## that needs to return true if cell needs to be checked.[br]
|
||||||
|
## unit - source unit.
|
||||||
|
func get_empty(rule: Callable, unit: Unit) -> Array[int]:
|
||||||
|
var unit_pos = to_snapped(unit.global_position)
|
||||||
|
var result: Array[int] = []
|
||||||
|
for i: int in range(columns * rows):
|
||||||
|
if rule.call(i%columns,i/columns,int(unit_pos.x),int(unit_pos.y)) and grid[i] == null:
|
||||||
|
result.append(i)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
## WIP[br]
|
||||||
|
## Returns empty with given rule predicate. Checks from source unit with rays and stops only when ray failed.[br]
|
||||||
|
## rule - predicate with signature [code](x,y,source_x,source_y)[/code] -> bool
|
||||||
|
## that needs to return true if cell needs to be checked.[br]
|
||||||
|
## unit - source unit.[br]
|
||||||
|
## rays - amount of rays to check from unit.
|
||||||
|
func get_empty_stoppable(rule: Callable, unit: Unit, rays: int = 8) -> Array[int]:
|
||||||
|
return []
|
||||||
|
|
||||||
|
## Casts a ray along [code]direction[/code] from [code]from[/code] to find unit. If distance is given, restricts lookup to [code]distance[/code] cells.
|
||||||
|
func raycast_unit(from: Vector2,direction: Vector2,distance: float = -1) -> Unit:
|
||||||
|
if not direction.is_normalized():
|
||||||
|
direction = direction.normalized()
|
||||||
|
var result = null
|
||||||
|
|
||||||
|
var to: Vector2 = from + direction * rows * columns
|
||||||
|
var dv: Vector2 = to.floor() - from.floor()
|
||||||
|
var step = abs(dv.x) + 1 if abs(dv.x) > abs(dv.y) else abs(dv.y) + 1
|
||||||
|
var check_pos = from
|
||||||
|
|
||||||
|
while is_position_valid(check_pos) and distance != 0:
|
||||||
|
check_pos += dv/step
|
||||||
|
distance -= 1
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
## Casts a ray along [code]direction[/code] from [code]from[/code] to find all empty cells. If distance is given, restricts lookup to [code]distance[/code] cells.
|
||||||
|
func raycast_empty(from: Vector2,direction: Vector2,distance: float = -1) -> Array[int]:
|
||||||
|
if not direction.is_normalized():
|
||||||
|
direction = direction.normalized()
|
||||||
|
var result: Array[int] = []
|
||||||
|
|
||||||
|
var dv: Vector2 = (Vector2.ONE/direction).round()
|
||||||
|
var steps_y: int = int(abs(dv.y))
|
||||||
|
var steps_x: int = int(abs(dv.x))
|
||||||
|
var check_pos = from.floor()
|
||||||
|
var change_y: bool = true if abs(dv.y) > abs(dv.x) else false
|
||||||
|
|
||||||
|
while is_position_valid(check_pos) and distance != 0:
|
||||||
|
if steps_x == 0:
|
||||||
|
steps_x = int(abs(dv.x))
|
||||||
|
change_y = true
|
||||||
|
elif steps_y == 0:
|
||||||
|
steps_y = int(abs(dv.y))
|
||||||
|
change_y = false
|
||||||
|
|
||||||
|
if change_y:
|
||||||
|
check_pos += Vector2(0,sign(dv.y)) * cell_size
|
||||||
|
steps_y-=1
|
||||||
|
else:
|
||||||
|
check_pos += Vector2(sign(dv.x),0) * cell_size
|
||||||
|
steps_x -= 1
|
||||||
|
|
||||||
|
var index = to_index(check_pos)
|
||||||
|
if index == -1:
|
||||||
|
break
|
||||||
|
if grid[index] == null:
|
||||||
|
result.append(index)
|
||||||
|
|
||||||
|
return result
|
||||||
1
systems/grid.gd.uid
Normal file
1
systems/grid.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://rt6mxr30u8tp
|
||||||
29
systems/grid_highlighter.gd
Normal file
29
systems/grid_highlighter.gd
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
extends Node2D
|
||||||
|
|
||||||
|
@onready var grid: Grid = get_parent()
|
||||||
|
|
||||||
|
const UNIT_COLOR = Color.CHOCOLATE
|
||||||
|
const EMPTY_COLOR = Color(Color.CORNFLOWER_BLUE,1.0)
|
||||||
|
|
||||||
|
var units: Array[Vector2]
|
||||||
|
var empty: Array[Vector2]
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
GameplaySignalBus.highlight_empty.connect(on_highlight_empty)
|
||||||
|
GameplaySignalBus.highlight_units.connect(on_highlight_units)
|
||||||
|
|
||||||
|
func _draw() -> void:
|
||||||
|
for unit in units:
|
||||||
|
draw_rect(Rect2(unit,grid.cell_size),UNIT_COLOR)
|
||||||
|
for empty_cell in empty:
|
||||||
|
draw_rect(Rect2(empty_cell,grid.cell_size),EMPTY_COLOR)
|
||||||
|
|
||||||
|
func on_highlight_units(new_units: Array[Unit]):
|
||||||
|
units.clear()
|
||||||
|
units.assign(new_units.map(func(unit : Unit): return grid.snap_position(unit.global_position)))
|
||||||
|
queue_redraw()
|
||||||
|
|
||||||
|
func on_highlight_empty(new_empty: Array[int]):
|
||||||
|
empty.clear()
|
||||||
|
empty.assign(new_empty.map(func(cell: int): return grid.from_index(cell)))
|
||||||
|
queue_redraw()
|
||||||
1
systems/grid_highlighter.gd.uid
Normal file
1
systems/grid_highlighter.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://bmy5djjmiljhl
|
||||||
Binary file not shown.
Binary file not shown.
5
units/unit.gd
Normal file
5
units/unit.gd
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
extends Node2D
|
||||||
|
|
||||||
|
class_name Unit
|
||||||
|
|
||||||
|
signal on_death
|
||||||
1
units/unit.gd.uid
Normal file
1
units/unit.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://db7simgenakts
|
||||||
Loading…
Add table
Add a link
Reference in a new issue