221 lines
6.9 KiB
GDScript
221 lines
6.9 KiB
GDScript
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
|
|
|
|
var hover_indicator = preload("res://assets/sprites/ui/ui_icons_green_down4.png")
|
|
var selected_indicator = preload("res://assets/sprites/ui/ui_icons_blue_down4.png")
|
|
|
|
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
|
|
|
|
func _ready():
|
|
|
|
var hover_sprite = Sprite2D.new()
|
|
hover_sprite.texture = hover_indicator
|
|
hover_sprite.position.y = -15
|
|
hover_sprite.visible = false
|
|
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
|
|
if map_renderer:
|
|
map_renderer.darken_all_except_player(self)
|
|
else:
|
|
get_node("HoverIndicator").texture = hover_indicator
|
|
# Reset darkening
|
|
if map_renderer:
|
|
map_renderer.reset_darkening()
|
|
|
|
# Keep indicator visible when selected
|
|
get_node("HoverIndicator").visible = selected or hovered == player
|
|
|
|
var player_data = {
|
|
"stats": {
|
|
"health": 100,
|
|
"mana": 100,
|
|
"speed": 3,
|
|
"attack": 10,
|
|
"defense": 5,
|
|
"actionpoints": 5,
|
|
},
|
|
"inventory": [],
|
|
"name": "Hero"
|
|
}
|
|
func _input(event):
|
|
if event is InputEventMouseMotion:
|
|
check_hover()
|
|
|
|
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()
|
|
else:
|
|
selected = false
|
|
|
|
func check_hover():
|
|
var mouse_pos = get_global_mouse_position()
|
|
var was_hovered = hovered != null
|
|
# print("Mouse pos: ", mouse_pos, " Player pos: ", player.position)
|
|
|
|
if hovered:
|
|
hovered.get_node("HoverIndicator").visible = false
|
|
hovered = null
|
|
|
|
if player.has_node("CollisionShape2D"):
|
|
var collision = player.get_node("CollisionShape2D")
|
|
var shape = collision.shape
|
|
|
|
var local_pos = player.to_local(mouse_pos)
|
|
|
|
if shape is RectangleShape2D:
|
|
var extents = shape.extents
|
|
if local_pos.x >= -extents.x and local_pos.x <= extents.x and \
|
|
local_pos.y >= -extents.y and local_pos.y <= extents.y:
|
|
hovered = player
|
|
player.get_node("HoverIndicator").visible = true
|
|
|
|
if (was_hovered != (hovered != null)) and map_renderer:
|
|
map_renderer.set_unit_hover_state(hovered != null)
|
|
|
|
|
|
func set_unit_position(x, y, z):
|
|
var z_layer = z
|
|
var x_position = x + 16
|
|
var y_position = y
|
|
|
|
# Update the main node position
|
|
global_position = Vector2(x_position, y_position)
|
|
|
|
# Update the visual z-index directly
|
|
animated_sprite.z_index = z_layer
|
|
# Keep sprite centered at node position
|
|
animated_sprite.position = Vector2.ZERO
|
|
|
|
print("Player Z-Layer: ", z_layer)
|
|
print("Player position updated to: ", global_position)
|
|
|
|
func get_sprite_size():
|
|
return collision_shape_2d.shape
|
|
|
|
func _process(delta: float):
|
|
check_hover()
|
|
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)"
|