diff --git a/addons/godot-git-plugin/win64/~libgit_plugin.windows.editor.x86_64.dll b/addons/godot-git-plugin/win64/~libgit_plugin.windows.editor.x86_64.dll new file mode 100644 index 0000000..47bbb1d Binary files /dev/null and b/addons/godot-git-plugin/win64/~libgit_plugin.windows.editor.x86_64.dll differ diff --git a/scenes/player.tscn b/scenes/player.tscn index 3a46232..7450b8d 100644 --- a/scenes/player.tscn +++ b/scenes/player.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=17 format=3 uid="uid://d1jhpluu86cbd"] +[gd_scene load_steps=18 format=3 uid="uid://d1jhpluu86cbd"] [ext_resource type="Texture2D" uid="uid://d3tfo61gemayy" path="res://assets/sprites/units/$Cat_Female (2).png" id="1_3vyb7"] [ext_resource type="Script" uid="uid://jfojoaymauh2" path="res://scripts/player.gd" id="1_g2els"] +[ext_resource type="Script" uid="uid://u7567afura88" path="res://scripts/toggle_movement.gd" id="3_qhqgy"] [sub_resource type="AtlasTexture" id="AtlasTexture_3li8b"] atlas = ExtResource("1_3vyb7") @@ -127,3 +128,24 @@ position = Vector2(0, 2.5) shape = SubResource("RectangleShape2D_v6fml") [node name="Camera2D" type="Camera2D" parent="."] + +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer"] +anchors_preset = 1 +anchor_left = 1.0 +anchor_right = 1.0 +offset_left = -213.0 +offset_bottom = 58.0 +grow_horizontal = 0 + +[node name="ToggleMovement" type="Button" parent="CanvasLayer/VBoxContainer"] +layout_mode = 2 +text = "Toggle Movement" +script = ExtResource("3_qhqgy") + +[node name="MovementType" type="Label" parent="CanvasLayer/VBoxContainer"] +layout_mode = 2 +text = "\"Mode: Non-Combat (Free)\"" + +[connection signal="pressed" from="CanvasLayer/VBoxContainer/ToggleMovement" to="." method="_on_toggle_movement_pressed"] diff --git a/scripts/isometric_map_data.gd b/scripts/isometric_map_data.gd index 61510f7..c09a3bd 100644 --- a/scripts/isometric_map_data.gd +++ b/scripts/isometric_map_data.gd @@ -28,6 +28,53 @@ func _set_max_array_size(): if MAX_ARRAY_SIZE < GRID_SIZE_HEIGHT: MAX_ARRAY_SIZE = GRID_SIZE_HEIGHT + +func is_array_tile_valid(array_pos: Vector3i): + if 0 < array_pos.x and array_pos.x < MAX_ARRAY_SIZE and 0 < array_pos.y and array_pos.y < MAX_ARRAY_SIZE and 0 < array_pos.z and array_pos.z < MAX_ARRAY_SIZE: + return true + return false + +func get_array_neighbors(array_pos: Vector3i, movement_range: int) -> Array: + var neighbors = [] + var visited = {array_pos: true} # Using a dictionary for faster lookups + var directions = [ + Vector3i(0, 0, 1), # up + Vector3i(0, 0, -1), # down + Vector3i(0, 1, 0), # left + Vector3i(0, -1, 0), # right + Vector3i(1, 0, 0), # forward + Vector3i(-1, 0, 0), # backward + ] + + # Use a breadth-first search approach + var current_level = [array_pos] + + for distance in range(1, movement_range + 1): + var next_level = [] + + for current_pos in current_level: + for dir in directions: + var neighbor_pos = current_pos + dir + + # Check if we've already processed this position or if it's invalid + if neighbor_pos in visited or not is_array_tile_valid(neighbor_pos): + continue + + # Mark as visited and add to results + visited[neighbor_pos] = true + neighbors.append(neighbor_pos) + next_level.append(neighbor_pos) + + # Move to the next level of neighbors + current_level = next_level + + # If no more positions to check at this level, we can stop early + if current_level.is_empty(): + break + + return neighbors + + func initialize_map_data(): # Initialize empty map structure map_data = [] diff --git a/scripts/isometric_map_renderer.gd b/scripts/isometric_map_renderer.gd index 251e9ab..9aaf172 100644 --- a/scripts/isometric_map_renderer.gd +++ b/scripts/isometric_map_renderer.gd @@ -9,6 +9,7 @@ var TILE_SIZE_ISOMETRIC_X = 32 # in px var TILE_SIZE_ISOMETRIC_Y = 16 # in px var unit_is_hovered = false +var unit_is_selected = false var darkening_active = false @@ -36,6 +37,9 @@ func reset_darkening(): func set_unit_hover_state(is_hovered): unit_is_hovered = is_hovered + +func set_unit_selected_state(is_selected): + unit_is_selected = is_selected # Initialize with reference to a map data object and a tilemap to use as template func _init(map_data_ref, tilemap_template): @@ -175,6 +179,10 @@ func handle_hover(mouse_position): # Handle tile selection logic func handle_tile_selection(): + if unit_is_selected: + reset_darkening() + unit_is_selected = false + for z in map_data.GRID_SIZE_HEIGHT: for x in map_data.GRID_SIZE_WIDTH: for y in map_data.GRID_SIZE_LENGTH: diff --git a/scripts/isometric_map_system.gd b/scripts/isometric_map_system.gd index 6f592af..32a56de 100644 --- a/scripts/isometric_map_system.gd +++ b/scripts/isometric_map_system.gd @@ -25,6 +25,7 @@ func debug_print(message): if debug_enabled: print("[IsometricMapSystem] " + str(message)) + # Utility functions for conversion between coordinate systems func iso_to_world(tile_x, tile_y, player_z_layer = 0, tile_width = 32, tile_height = 16): # Calculate the world position from isometric coordinates diff --git a/scripts/player.gd b/scripts/player.gd index ca92ade..0d658e9 100644 --- a/scripts/player.gd +++ b/scripts/player.gd @@ -3,6 +3,7 @@ extends CharacterBody2D @onready var collision_shape_2d: CollisionShape2D = $CollisionShape2D @onready var animated_sprite: AnimatedSprite2D = $AnimatedSprite2D @onready var player: CharacterBody2D = $"." +@onready var movementlabel: Label = $CanvasLayer/VBoxContainer/MovementType var hovered = null var selected = null @@ -12,6 +13,22 @@ var selected_indicator = preload("res://assets/sprites/ui/ui_icons_blue_down4.pn var map_renderer = null +@export var move_speed: float = 200.0 # Speed for free movement +@export var tile_size: Vector2 = Vector2(32, 16) +@export var combat_move_time: float = 0.3 + +enum MovementMode { + FREE, + COMBAT +} + +var current_mode: MovementMode = MovementMode.FREE +var is_moving: bool = false +var target_position: Vector2 = Vector2.ZERO +var start_position: Vector2 = Vector2.ZERO +var move_progress: float = 0.0 +var move_direction: Vector2 = Vector2.ZERO + func set_map_renderer(renderer): map_renderer = renderer @@ -24,9 +41,11 @@ func _ready(): hover_sprite.name = "HoverIndicator" hover_sprite.z_index = 100 player.add_child(hover_sprite) + target_position = position func toggle_selection(): selected = !selected + map_renderer.set_unit_selected_state(selected) if selected: get_node("HoverIndicator").texture = selected_indicator # Tell the map renderer to darken everything @@ -61,7 +80,9 @@ func _unhandled_input(event): if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed: # If we're being hovered and clicked if hovered == player: - toggle_selection() + toggle_selection() + else: + selected = false func check_hover(): var mouse_pos = get_global_mouse_position() @@ -108,11 +129,92 @@ func set_unit_position(x, y, z): func get_sprite_size(): return collision_shape_2d.shape -func _process(_delta: float): +func _process(delta: float): check_hover() - play_player_animation("idle") + match current_mode: + MovementMode.FREE: + play_player_animation("movement") + process_free_movement(delta) + MovementMode.COMBAT: + play_player_animation("idle") + #process_combat_movement(delta) + +func process_free_movement(delta): + # Get input direction + var direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") + # Convert direction to isometric (optional - depends on your camera setup) + var iso_direction = Vector2(direction.x, direction.y) + + # Set velocity and move + velocity = iso_direction.normalized() * move_speed + move_and_slide() + +func process_combat_movement(delta): + if is_moving: + # Continue current movement + move_progress += delta / combat_move_time + if move_progress >= 1.0: + # Movement complete + position = target_position + is_moving = false + else: + # Interpolate position + position = start_position.lerp(target_position, move_progress) + else: + # Check for new movement input + var direction = Vector2.ZERO + if Input.is_action_just_pressed("ui_right"): + direction = Vector2(1, 0) + elif Input.is_action_just_pressed("ui_left"): + direction = Vector2(-1, 0) + elif Input.is_action_just_pressed("ui_down"): + direction = Vector2(0, 1) + elif Input.is_action_just_pressed("ui_up"): + direction = Vector2(0, -1) + + if direction != Vector2.ZERO: + start_tile_movement(direction) + +# Start a new tile movement +func start_tile_movement(direction: Vector2): + # Convert direction to isometric + var iso_direction = Vector2(direction.x - direction.y, (direction.x + direction.y) / 2) + + # Calculate target position + start_position = position + target_position = position + (iso_direction * tile_size) + + # Start movement + is_moving = true + move_progress = 0.0 + move_direction = direction + +# Toggle between movement modes +func toggle_movement_mode(): + if current_mode == MovementMode.FREE: + current_mode = MovementMode.COMBAT + # Snap to nearest tile when entering combat mode + position = Vector2( + round(position.x / tile_size.x) * tile_size.x, + round(position.y / tile_size.y) * tile_size.y + ) + else: + current_mode = MovementMode.FREE + + print("Movement mode switched to: ", "FREE" if current_mode == MovementMode.FREE else "COMBAT") func play_player_animation(state="idle"): if state == "idle": animated_sprite.play("down") + if state == "movement": + animated_sprite.play("down") + + + +func _on_toggle_movement_pressed() -> void: + player.toggle_movement_mode() + if player.current_mode == player.MovementMode.FREE: + movementlabel.text = "Mode: Non-Combat (Free)" + else: + movementlabel.text = "Mode: Combat (Tile-Based)" diff --git a/scripts/toggle_movement.gd b/scripts/toggle_movement.gd new file mode 100644 index 0000000..c75bcb5 --- /dev/null +++ b/scripts/toggle_movement.gd @@ -0,0 +1 @@ +extends Button diff --git a/scripts/toggle_movement.gd.uid b/scripts/toggle_movement.gd.uid new file mode 100644 index 0000000..027ee68 --- /dev/null +++ b/scripts/toggle_movement.gd.uid @@ -0,0 +1 @@ +uid://u7567afura88