Trying new stuff with the camera and grid. I want to be able to move a unit but there is a problem with the grid at the moment. I am now trying to implement a new way of handling the camera, maybe then I can move on to moving units...
This commit is contained in:
75
Scenes/Main/cursor.gd
Normal file
75
Scenes/Main/cursor.gd
Normal file
@@ -0,0 +1,75 @@
|
||||
## Player-controlled cursor. Allows them to navigate the game grid, select units, and move them.
|
||||
## Supports both keyboard and mouse (or touch) input.
|
||||
@tool
|
||||
class_name Cursor
|
||||
extends Node2D
|
||||
|
||||
## Emitted when clicking on the currently hovered cell or when pressing "ui_accept".
|
||||
signal accept_pressed(cell)
|
||||
## Emitted when the cursor moved to a new cell.
|
||||
signal moved(new_cell)
|
||||
|
||||
## Grid resource, giving the node access to the grid size, and more.
|
||||
@export var grid: Resource
|
||||
## Time before the cursor can move again in seconds.
|
||||
@export var ui_cooldown := 0.1
|
||||
|
||||
## Coordinates of the current cell the cursor is hovering.
|
||||
var cell := Vector2.ZERO:
|
||||
set(value):
|
||||
print("Setting cell to: ", value)
|
||||
# We first clamp the cell coordinates and ensure that we aren't
|
||||
# trying to move outside the grid boundaries
|
||||
var new_cell: Vector2 = grid.clamp(value)
|
||||
print("New cell: ", new_cell)
|
||||
if new_cell.is_equal_approx(cell):
|
||||
return
|
||||
|
||||
cell = new_cell
|
||||
print("Cell is ", cell)
|
||||
# If we move to a new cell, we update the cursor's position, emit
|
||||
# a signal, and start the cooldown timer that will limit the rate
|
||||
# at which the cursor moves when we keep the direction key held
|
||||
# down
|
||||
position = grid.calculateMapPosition(cell)
|
||||
print("Position is ", position)
|
||||
emit_signal("moved", cell)
|
||||
_timer.start()
|
||||
|
||||
@onready var _timer: Timer = $Timer
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_timer.wait_time = ui_cooldown
|
||||
position = grid.calculateMapPosition(cell)
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
# Navigating cells with the mouse.
|
||||
if event is InputEventMouseMotion:
|
||||
cell = grid.calculateGridCoordinates(event.position)
|
||||
# Trying to select something in a cell.
|
||||
elif event.is_action_pressed("Select") or event.is_action_pressed("ui_accept"):
|
||||
emit_signal("accept_pressed", cell)
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
var should_move := event.is_pressed()
|
||||
if event.is_echo():
|
||||
should_move = should_move and _timer.is_stopped()
|
||||
|
||||
if not should_move:
|
||||
return
|
||||
|
||||
# Moves the cursor by one grid cell.
|
||||
if event.is_action("ui_right"):
|
||||
cell += Vector2.RIGHT
|
||||
elif event.is_action("ui_up"):
|
||||
cell += Vector2.UP
|
||||
elif event.is_action("ui_left"):
|
||||
cell += Vector2.LEFT
|
||||
elif event.is_action("ui_down"):
|
||||
cell += Vector2.DOWN
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
draw_rect(Rect2(-grid.cellSize / 2, grid.cellSize), Color.ALICE_BLUE, false, 2.0)
|
||||
1
Scenes/Main/cursor.gd.uid
Normal file
1
Scenes/Main/cursor.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cidjtc27oj1gn
|
||||
142
Scenes/Main/game_board.gd
Normal file
142
Scenes/Main/game_board.gd
Normal file
@@ -0,0 +1,142 @@
|
||||
## Represents and manages the game board. Stores references to entities that are in each cell and
|
||||
## tells whether cells are occupied or not.
|
||||
## Units can only move around the grid one at a time.
|
||||
class_name GameBoard
|
||||
extends Node2D
|
||||
|
||||
const DIRECTIONS = [Vector2.LEFT, Vector2.RIGHT, Vector2.UP, Vector2.DOWN]
|
||||
|
||||
## Resource of type Grid.
|
||||
@export var grid: Resource
|
||||
|
||||
## Mapping of coordinates of a cell to a reference to the unit it contains.
|
||||
var _units := {}
|
||||
var _active_unit: Unit
|
||||
var _walkable_cells := []
|
||||
|
||||
#@onready var _unit_overlay: UnitOverlay = $UnitOverlay
|
||||
#@onready var _unit_path: UnitPath = $UnitPath
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_reinitialize()
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if _active_unit and event.is_action_pressed("ui_cancel"):
|
||||
_deselect_active_unit()
|
||||
_clear_active_unit()
|
||||
|
||||
|
||||
func _get_configuration_warning() -> String:
|
||||
var warning := ""
|
||||
if not grid:
|
||||
warning = "You need a Grid resource for this node to work."
|
||||
return warning
|
||||
|
||||
|
||||
## Returns `true` if the cell is occupied by a unit.
|
||||
func is_occupied(cell: Vector2) -> bool:
|
||||
return _units.has(cell)
|
||||
|
||||
|
||||
## Returns an array of cells a given unit can walk using the flood fill algorithm.
|
||||
func get_walkable_cells(unit: Unit) -> Array:
|
||||
return _flood_fill(unit.cell, unit.move_range)
|
||||
|
||||
|
||||
## Clears, and refills the `_units` dictionary with game objects that are on the board.
|
||||
func _reinitialize() -> void:
|
||||
_units.clear()
|
||||
|
||||
for child in get_children():
|
||||
var unit := child as Unit
|
||||
if not unit:
|
||||
continue
|
||||
_units[unit.cell] = unit
|
||||
|
||||
|
||||
## Returns an array with all the coordinates of walkable cells based on the `max_distance`.
|
||||
func _flood_fill(cell: Vector2, max_distance: int) -> Array:
|
||||
var array := []
|
||||
var stack := [cell]
|
||||
while not stack.size() == 0:
|
||||
var current = stack.pop_back()
|
||||
if not grid.is_within_bounds(current):
|
||||
continue
|
||||
if current in array:
|
||||
continue
|
||||
|
||||
var difference: Vector2 = (current - cell).abs()
|
||||
var distance := int(difference.x + difference.y)
|
||||
if distance > max_distance:
|
||||
continue
|
||||
|
||||
array.append(current)
|
||||
for direction in DIRECTIONS:
|
||||
var coordinates: Vector2 = current + direction
|
||||
if is_occupied(coordinates):
|
||||
continue
|
||||
if coordinates in array:
|
||||
continue
|
||||
# Minor optimization: If this neighbor is already queued
|
||||
# to be checked, we don't need to queue it again
|
||||
if coordinates in stack:
|
||||
continue
|
||||
|
||||
stack.append(coordinates)
|
||||
return array
|
||||
|
||||
|
||||
## Updates the _units dictionary with the target position for the unit and asks the _active_unit to walk to it.
|
||||
func _move_active_unit(new_cell: Vector2) -> void:
|
||||
if is_occupied(new_cell) or not new_cell in _walkable_cells:
|
||||
return
|
||||
# warning-ignore:return_value_discarded
|
||||
_units.erase(_active_unit.cell)
|
||||
_units[new_cell] = _active_unit
|
||||
_deselect_active_unit()
|
||||
# _active_unit.walk_along(_unit_path.current_path)
|
||||
await _active_unit.walk_finished
|
||||
_clear_active_unit()
|
||||
|
||||
|
||||
## Selects the unit in the `cell` if there's one there.
|
||||
## Sets it as the `_active_unit` and draws its walkable cells and interactive move path.
|
||||
func _select_unit(cell: Vector2) -> void:
|
||||
if not _units.has(cell):
|
||||
return
|
||||
|
||||
_active_unit = _units[cell]
|
||||
_active_unit.is_selected = true
|
||||
_walkable_cells = get_walkable_cells(_active_unit)
|
||||
# _unit_overlay.draw(_walkable_cells)
|
||||
# _unit_path.initialize(_walkable_cells)
|
||||
|
||||
|
||||
## Deselects the active unit, clearing the cells overlay and interactive path drawing.
|
||||
func _deselect_active_unit() -> void:
|
||||
_active_unit.is_selected = false
|
||||
# _unit_overlay.clear()
|
||||
# _unit_path.stop()
|
||||
|
||||
|
||||
## Clears the reference to the _active_unit and the corresponding walkable cells.
|
||||
func _clear_active_unit() -> void:
|
||||
_active_unit = null
|
||||
_walkable_cells.clear()
|
||||
|
||||
|
||||
## Selects or moves a unit based on where the cursor is.
|
||||
func _on_Cursor_accept_pressed(cell: Vector2) -> void:
|
||||
if not _active_unit:
|
||||
_select_unit(cell)
|
||||
elif _active_unit.is_selected:
|
||||
_move_active_unit(cell)
|
||||
|
||||
|
||||
## Updates the interactive path's drawing if there's an active and selected unit.
|
||||
func _on_Cursor_moved(new_cell: Vector2) -> void:
|
||||
# if _active_unit and _active_unit.is_selected:
|
||||
# _unit_path.draw(_active_unit.cell, new_cell)
|
||||
pass
|
||||
1
Scenes/Main/game_board.gd.uid
Normal file
1
Scenes/Main/game_board.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://14cwbxcvt5dx
|
||||
@@ -15,12 +15,14 @@ var _MovingMarker: Node2D = _MovingMarkerScene.instantiate()
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
add_child(_MovingMarker)
|
||||
_MovingMarker.hide()
|
||||
|
||||
_createUnit(Vector2i(10,10))
|
||||
for unit in _Units:
|
||||
add_child(unit)
|
||||
# add_child(_MovingMarker)
|
||||
# _MovingMarker.hide()
|
||||
#
|
||||
# _createUnit(Vector2i(10,10))
|
||||
# for unit in _Units:
|
||||
# add_child(unit)
|
||||
|
||||
$CameraController.position = get_viewport().get_camera_2d().get_screen_center_position()
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://d05j5yuhlsxp0"]
|
||||
[gd_scene load_steps=9 format=3 uid="uid://d05j5yuhlsxp0"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://cywuuce71rmgb" path="res://Scenes/Map/map.tscn" id="1_1r6ip"]
|
||||
[ext_resource type="Script" uid="uid://btdvxp8ckmeb3" path="res://Scenes/Main/main.gd" id="1_qw60k"]
|
||||
[ext_resource type="PackedScene" uid="uid://bfvijh611aggp" path="res://Scenes/Camera/camera_controller.tscn" id="3_qw60k"]
|
||||
[ext_resource type="Script" uid="uid://14cwbxcvt5dx" path="res://Scenes/Main/game_board.gd" id="4_5yls4"]
|
||||
[ext_resource type="Resource" uid="uid://bpf7mj7w5kftq" path="res://Resource/Grid.tres" id="5_p6jpk"]
|
||||
[ext_resource type="PackedScene" uid="uid://b1d6lktijxy3s" path="res://Scenes/Unit/move/unit.tscn" id="6_2a143"]
|
||||
[ext_resource type="Script" uid="uid://cidjtc27oj1gn" path="res://Scenes/Main/cursor.gd" id="7_y3v7k"]
|
||||
[ext_resource type="Texture2D" uid="uid://bckknh8k5fh1s" path="res://Graphics/TileMaps/kenney_rpgUrbanKit/Tiles/tile_0448.png" id="8_hryqi"]
|
||||
|
||||
[node name="Main" type="Node"]
|
||||
script = ExtResource("1_qw60k")
|
||||
@@ -10,3 +15,24 @@ script = ExtResource("1_qw60k")
|
||||
[node name="Map" parent="." instance=ExtResource("1_1r6ip")]
|
||||
|
||||
[node name="CameraController" parent="." instance=ExtResource("3_qw60k")]
|
||||
grid = ExtResource("5_p6jpk")
|
||||
|
||||
[node name="GameBoard" type="Node2D" parent="."]
|
||||
script = ExtResource("4_5yls4")
|
||||
grid = ExtResource("5_p6jpk")
|
||||
|
||||
[node name="Unit" parent="GameBoard" instance=ExtResource("6_2a143")]
|
||||
grid = ExtResource("5_p6jpk")
|
||||
|
||||
[node name="Cursor" type="Node2D" parent="GameBoard"]
|
||||
script = ExtResource("7_y3v7k")
|
||||
grid = ExtResource("5_p6jpk")
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="GameBoard/Cursor"]
|
||||
position = Vector2(10, -10)
|
||||
texture = ExtResource("8_hryqi")
|
||||
|
||||
[node name="Timer" type="Timer" parent="GameBoard/Cursor"]
|
||||
wait_time = 0.1
|
||||
|
||||
[editable path="CameraController"]
|
||||
|
||||
Reference in New Issue
Block a user