#57 rework des inputs et actions
This commit is contained in:
@@ -1,41 +0,0 @@
|
||||
extends Area2D
|
||||
class_name ActionArea
|
||||
|
||||
const OPACITY = 0.4
|
||||
const ACTIVATED_COLOR = Color.TURQUOISE
|
||||
const DEACTIVATED_COLOR = Color.REBECCA_PURPLE
|
||||
|
||||
var collision_shape : CollisionShape2D = null
|
||||
var area_width : float
|
||||
var area_max_distance : float
|
||||
var player : Player
|
||||
|
||||
var activated : bool = false
|
||||
|
||||
func _init(
|
||||
_player: Player,
|
||||
_area_width : float = 40,
|
||||
):
|
||||
player = _player
|
||||
area_width = _area_width
|
||||
|
||||
func _ready():
|
||||
collision_shape = CollisionShape2D.new()
|
||||
collision_shape.shape = CircleShape2D.new()
|
||||
collision_shape.shape.radius = area_width
|
||||
add_child(collision_shape)
|
||||
|
||||
func _process(_delta):
|
||||
var target_position = get_global_mouse_position() - player.global_position
|
||||
if Vector2.ONE.distance_to(target_position) > player.max_reach:
|
||||
target_position = Vector2.ZERO.direction_to(target_position)*player.max_reach
|
||||
|
||||
position = target_position
|
||||
queue_redraw()
|
||||
|
||||
func _draw():
|
||||
draw_circle(
|
||||
Vector2.ZERO,
|
||||
area_width,
|
||||
Color((ACTIVATED_COLOR if activated else DEACTIVATED_COLOR), OPACITY)
|
||||
)
|
||||
@@ -1 +0,0 @@
|
||||
uid://btmwjrscevcb1
|
||||
@@ -1,46 +1,32 @@
|
||||
extends CharacterBody2D
|
||||
class_name Player
|
||||
|
||||
const MAX_REACH_CIRCLE_OPACITY = 0.1
|
||||
const MAX_REACH = 100
|
||||
|
||||
signal player_updated(player: Player)
|
||||
signal action_tried_without_energy
|
||||
signal action_not_permitted
|
||||
signal upgraded
|
||||
|
||||
var planet : Planet # mis à jour par la classe Planet
|
||||
@export var speed = 350
|
||||
|
||||
@onready var inventory : Inventory = Inventory.new()
|
||||
|
||||
var max_energy : int = 3
|
||||
var max_reach : int = 100 :
|
||||
set(v):
|
||||
max_reach = v
|
||||
queue_redraw()
|
||||
var has_just_received_instruction : bool = false # pour récupérer les zones dans les action_area, une frame doit être passée depuis la création de la zone
|
||||
|
||||
var controlling_player : bool = true :
|
||||
set(v):
|
||||
controlling_player = v
|
||||
velocity = Vector2.ZERO
|
||||
|
||||
var target_interactable : Interactable = null # mis à jour par la classe Interactable
|
||||
var instruction : Instruction = null
|
||||
|
||||
var can_use_item : bool = false :
|
||||
set(v):
|
||||
var old = can_use_item
|
||||
can_use_item = v
|
||||
if old != can_use_item:
|
||||
print("emit")
|
||||
player_updated.emit(self)
|
||||
var energy : int = max_energy :
|
||||
set(v):
|
||||
energy = v
|
||||
player_updated.emit(self)
|
||||
var action_area : ActionArea = null :
|
||||
set(v):
|
||||
action_area = v
|
||||
queue_redraw()
|
||||
|
||||
@onready var inventory : Inventory = Inventory.new()
|
||||
@onready var preview_zone : Area2D = null
|
||||
@onready var action_zone : Area2D = null
|
||||
|
||||
func _ready():
|
||||
player_updated.emit(self)
|
||||
@@ -50,7 +36,7 @@ func _ready():
|
||||
# Méthode déclenchée par la classe planet
|
||||
func _start_pass_day():
|
||||
controlling_player = false
|
||||
target_interactable = null
|
||||
instruction = null
|
||||
|
||||
# Méthode déclenchée par la classe planet
|
||||
func _pass_day():
|
||||
@@ -61,100 +47,93 @@ func _end_pass_day():
|
||||
controlling_player = true
|
||||
|
||||
func _process(_delta):
|
||||
get_input()
|
||||
move_and_slide()
|
||||
|
||||
func _on_inventory_updated(_inventory: Inventory):
|
||||
emit_signal("player_updated", self)
|
||||
|
||||
func _draw():
|
||||
if action_area:
|
||||
draw_arc(
|
||||
Vector2.ZERO,
|
||||
max_reach,
|
||||
0.,
|
||||
2*PI,
|
||||
30,
|
||||
Color(Color.WHITE,MAX_REACH_CIRCLE_OPACITY),
|
||||
1
|
||||
)
|
||||
|
||||
func get_input():
|
||||
if controlling_player:
|
||||
var old_velocity=velocity
|
||||
calculate_direction()
|
||||
|
||||
can_use_item = inventory.get_item() and inventory.get_item().can_use(self)
|
||||
if action_area:
|
||||
action_area.activated = can_use_item
|
||||
if target_interactable and target_interactable in $InteractArea2D.get_overlapping_areas():
|
||||
if target_interactable.can_interact(self):
|
||||
Pointer.stop_inspect_entity(target_interactable)
|
||||
target_interactable.interact(self)
|
||||
target_interactable = null
|
||||
if Input.is_action_just_pressed("action"):
|
||||
try_use_item()
|
||||
if Input.is_action_just_pressed("drop") and inventory.get_item():
|
||||
drop_item()
|
||||
if instruction and instruction.can_be_done(self) and not has_just_received_instruction:
|
||||
instruction.do(self)
|
||||
instruction = null
|
||||
move_preview_zone(get_global_mouse_position())
|
||||
|
||||
has_just_received_instruction = false
|
||||
|
||||
# Sound
|
||||
if old_velocity.length()==0 and velocity.length()!=0:
|
||||
play_sfx("move")
|
||||
else:
|
||||
velocity = Vector2.ZERO
|
||||
move_and_slide()
|
||||
|
||||
func _on_inventory_updated(_inventory: Inventory):
|
||||
if inventory.get_item():
|
||||
setup_preview_zone(inventory.get_item().use_zone_radius)
|
||||
emit_signal("player_updated", self)
|
||||
|
||||
func calculate_direction():
|
||||
var input_direction: Vector2 = Input.get_vector("move_left", "move_right", "move_up", "move_down")
|
||||
|
||||
if input_direction.length() != 0:
|
||||
target_interactable = null
|
||||
|
||||
if target_interactable:
|
||||
input_direction = self.global_position.direction_to(target_interactable.global_position)
|
||||
instruction = null
|
||||
|
||||
if instruction:
|
||||
input_direction = self.global_position.direction_to(instruction.position)
|
||||
|
||||
velocity = input_direction * speed
|
||||
if input_direction.x:
|
||||
$Sprite.flip_h = (input_direction.x < 0)
|
||||
|
||||
func try_use_item():
|
||||
if energy == 0:
|
||||
action_tried_without_energy.emit()
|
||||
elif not can_use_item:
|
||||
action_not_permitted.emit()
|
||||
if energy > 0 and can_use_item:
|
||||
use_item()
|
||||
|
||||
func can_interact(interactable : Interactable):
|
||||
return interactable.can_interact(self)
|
||||
|
||||
func try_interact(interactable : Interactable):
|
||||
has_just_received_instruction = true
|
||||
instruction = InteractableInstruction.new(
|
||||
interactable
|
||||
)
|
||||
|
||||
func try_move(move_to : Vector2):
|
||||
instruction = MoveInstruction.new(move_to)
|
||||
|
||||
func get_item(item : Item):
|
||||
remove_action_area()
|
||||
inventory.set_item(item)
|
||||
var new_action_area = item.generate_action_area(self)
|
||||
if new_action_area != null :
|
||||
add_action_area(new_action_area)
|
||||
play_sfx("pick")
|
||||
|
||||
func drop_item():
|
||||
var item_to_drop = inventory.pop_item()
|
||||
planet.drop_item(item_to_drop, global_position)
|
||||
remove_action_area()
|
||||
play_sfx("drop")
|
||||
|
||||
func delete_item():
|
||||
inventory.set_item(null)
|
||||
remove_action_area()
|
||||
func delete_item(item: Item):
|
||||
inventory.remove_item(item)
|
||||
|
||||
func use_item():
|
||||
var item : Item = inventory.get_item()
|
||||
var is_item_used = item.use(self)
|
||||
if is_item_used:
|
||||
energy -= 1
|
||||
if item.is_one_time_use():
|
||||
delete_item()
|
||||
func try_use_item(item : Item, use_position : Vector2):
|
||||
has_just_received_instruction = true
|
||||
setup_action_zone(use_position, item.use_zone_radius)
|
||||
instruction = ItemActionInstruction.new(
|
||||
use_position,
|
||||
item
|
||||
)
|
||||
|
||||
func add_action_area(area : ActionArea):
|
||||
action_area = area
|
||||
add_child(action_area)
|
||||
func preview_can_use_item(item : Item) -> bool:
|
||||
return can_use_item_on_zone(item, preview_zone)
|
||||
|
||||
func remove_action_area():
|
||||
if (action_area):
|
||||
remove_child(action_area)
|
||||
action_area.queue_free()
|
||||
action_area = null
|
||||
func can_use_item_on_zone(item : Item, zone: Area2D) -> bool:
|
||||
return (
|
||||
inventory.has_item(item)
|
||||
and (energy - item.use_energy) >= 0
|
||||
and item.can_use(self, zone)
|
||||
)
|
||||
|
||||
func use_item(item : Item):
|
||||
print(action_zone.get_overlapping_areas())
|
||||
if can_use_item_on_zone(item, action_zone):
|
||||
var is_item_used = item.use(self, action_zone)
|
||||
if is_item_used:
|
||||
energy -= item.use_energy
|
||||
if item.is_one_time_use():
|
||||
delete_item(item)
|
||||
|
||||
func upgrade():
|
||||
max_energy += 1
|
||||
@@ -164,6 +143,44 @@ func upgrade():
|
||||
func recharge(amount : int = max_energy):
|
||||
energy = min(energy + amount, max_energy)
|
||||
|
||||
func generate_action_area(radius : int = 0) -> Area2D:
|
||||
var area2D = Area2D.new()
|
||||
var collision_shape = CollisionShape2D.new()
|
||||
var circle_shape = CircleShape2D.new()
|
||||
|
||||
circle_shape.radius = radius
|
||||
collision_shape.shape = circle_shape
|
||||
area2D.add_child(collision_shape)
|
||||
|
||||
get_parent().add_child(area2D)
|
||||
|
||||
return area2D
|
||||
|
||||
func setup_preview_zone(zone_radius : int) -> Area2D:
|
||||
if preview_zone:
|
||||
preview_zone.queue_free()
|
||||
preview_zone = generate_action_area(zone_radius)
|
||||
return preview_zone
|
||||
|
||||
func setup_action_zone(zone_position : Vector2, zone_radius : int) -> Area2D:
|
||||
if action_zone:
|
||||
action_zone.queue_free()
|
||||
action_zone = generate_action_area(zone_radius)
|
||||
action_zone.global_position = zone_position
|
||||
return action_zone
|
||||
|
||||
func move_preview_zone(zone_position : Vector2):
|
||||
if preview_zone:
|
||||
preview_zone.global_position = zone_position
|
||||
|
||||
func detect_area_in_preview_zone() -> Array:
|
||||
return preview_zone.get_overlapping_areas()
|
||||
|
||||
func detect_area_in_action_zone() -> Array:
|
||||
if action_zone:
|
||||
return action_zone.get_overlapping_areas()
|
||||
return []
|
||||
|
||||
func play_sfx(sound : String):
|
||||
match sound:
|
||||
"dig":
|
||||
@@ -176,3 +193,45 @@ func play_sfx(sound : String):
|
||||
$Audio/AudioStreamPlayer_drop.play()
|
||||
"move":
|
||||
$Audio/AudioStreamPlayer_movement.play()
|
||||
|
||||
class Instruction:
|
||||
|
||||
var position : Vector2
|
||||
|
||||
func _init(_pos : Vector2):
|
||||
position = _pos
|
||||
|
||||
func can_be_done(player : Player):
|
||||
return player.global_position.distance_to(position) < 10
|
||||
|
||||
func do(_player : Player):
|
||||
pass
|
||||
|
||||
class MoveInstruction extends Instruction:
|
||||
pass
|
||||
|
||||
class ItemActionInstruction extends Instruction:
|
||||
var item = Item
|
||||
|
||||
func _init(_pos : Vector2, _item : Item):
|
||||
position = _pos
|
||||
item = _item
|
||||
|
||||
func can_be_done(player : Player):
|
||||
return player.global_position.distance_to(position) < player.MAX_REACH
|
||||
|
||||
func do(player : Player):
|
||||
player.use_item(item)
|
||||
|
||||
class InteractableInstruction extends Instruction:
|
||||
var interactable = Interactable
|
||||
|
||||
func _init(_interactable : Interactable):
|
||||
interactable = _interactable
|
||||
position = interactable.global_position
|
||||
|
||||
func can_be_done(player : Player):
|
||||
return player.global_position.distance_to(position) < player.MAX_REACH
|
||||
|
||||
func do(player : Player):
|
||||
interactable.interact(player)
|
||||
|
||||
Reference in New Issue
Block a user