weapon ready/aiming done

This commit is contained in:
Rowan 2025-06-07 03:48:39 -04:00
parent ac3f0d73a6
commit be47641bab
5 changed files with 208 additions and 26 deletions

View file

@ -45,16 +45,54 @@ move_right={
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":1.0,"script":null)
]
}
look_up={
"deadzone": 0.2,
"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":3,"axis_value":-1.0,"script":null)
]
}
look_down={
"deadzone": 0.2,
"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":3,"axis_value":1.0,"script":null)
]
}
look_left={
"deadzone": 0.2,
"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":2,"axis_value":-1.0,"script":null)
]
}
look_right={
"deadzone": 0.2,
"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":2,"axis_value":1.0,"script":null)
]
}
run={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":true,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":true,"script":null)
]
}
interact={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":true,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":true,"script":null)
]
}
ready={
"deadzone": 0.2,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":2,"canceled":false,"pressed":false,"double_click":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":4,"axis_value":1.0,"script":null)
]
}
fire={
"deadzone": 0.2,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":5,"axis_value":1.0,"script":null)
]
}
reload={
"deadzone": 0.2,
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":10,"pressure":0.0,"pressed":true,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":82,"key_label":0,"unicode":114,"location":0,"echo":false,"script":null)
]
}

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=30 format=3 uid="uid://crbrniwi6kd3p"]
[gd_scene load_steps=36 format=3 uid="uid://crbrniwi6kd3p"]
[ext_resource type="PackedScene" uid="uid://dpmbimh6m4ari" path="res://scenes/player_mesh.tscn" id="1_3vyb7"]
[ext_resource type="Script" uid="uid://50vv0ta67tgl" path="res://src/player.gd" id="1_qhqgy"]
@ -9,6 +9,9 @@
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_g2els"]
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_smehm"]
animation = &"Aim"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_tuyoq"]
animation = &"PistolIdle"
@ -29,6 +32,9 @@ nodes/Blend2/node = SubResource("AnimationNodeBlend2_smehm")
nodes/Blend2/position = Vector2(80, 120)
node_connections = [&"Blend2", 0, &"Animation", &"Blend2", 1, &"Animation 2", &"output", 0, &"Blend2"]
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_ur7pv"]
animation = &"Fire"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_y4r1p"]
animation = &"PistolIdle"
@ -43,12 +49,32 @@ advance_expression = "velocity"
advance_mode = 2
advance_expression = "not velocity"
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_oprun"]
advance_mode = 2
advance_expression = "is_weapon_ready"
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_a8ls1"]
advance_mode = 2
advance_expression = "is_firing"
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_qfm1y"]
switch_mode = 2
advance_mode = 2
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_fulsm"]
advance_mode = 2
advance_expression = "not is_weapon_ready"
[sub_resource type="AnimationNodeStateMachine" id="AnimationNodeStateMachine_d2wvv"]
states/Aim/node = SubResource("AnimationNodeAnimation_smehm")
states/Aim/position = Vector2(327, 194)
states/BlendTree/node = SubResource("AnimationNodeBlendTree_ur7pv")
states/BlendTree/position = Vector2(488, 100)
states/Fire/node = SubResource("AnimationNodeAnimation_ur7pv")
states/Fire/position = Vector2(462, 194)
states/PistolIdle/node = SubResource("AnimationNodeAnimation_y4r1p")
states/PistolIdle/position = Vector2(327, 100)
transitions = ["Start", "PistolIdle", SubResource("AnimationNodeStateMachineTransition_ur7pv"), "PistolIdle", "BlendTree", SubResource("AnimationNodeStateMachineTransition_y4r1p"), "BlendTree", "PistolIdle", SubResource("AnimationNodeStateMachineTransition_d2wvv")]
transitions = ["Start", "PistolIdle", SubResource("AnimationNodeStateMachineTransition_ur7pv"), "PistolIdle", "BlendTree", SubResource("AnimationNodeStateMachineTransition_y4r1p"), "BlendTree", "PistolIdle", SubResource("AnimationNodeStateMachineTransition_d2wvv"), "PistolIdle", "Aim", SubResource("AnimationNodeStateMachineTransition_oprun"), "Aim", "Fire", SubResource("AnimationNodeStateMachineTransition_a8ls1"), "Fire", "Aim", SubResource("AnimationNodeStateMachineTransition_qfm1y"), "Aim", "PistolIdle", SubResource("AnimationNodeStateMachineTransition_fulsm")]
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_qhqgy"]
animation = &"Idle"
@ -72,7 +98,7 @@ advance_expression = "input.is_running"
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_qhqgy"]
advance_mode = 2
advance_expression = "not input.is_running"
advance_expression = "not input.is_running or not velocity"
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_dqkch"]
advance_mode = 2

View file

@ -1,6 +1,6 @@
class_name Persistence extends Node
@export var path = "user://saves/data.sav"
@export var path = "user://saves/"
@export var group_name = "persist"
const SaveMethod = "on_save"
@ -14,9 +14,12 @@ static func get_instance_data(node: Node):
data = node.call(SaveMethod)
}
func save() -> Result:
func save(filename: String) -> Result:
DirAccess.make_dir_recursive_absolute(path.get_base_dir())
var file = FileAccess.open(path, FileAccess.WRITE)
var file_path = path.path_join(filename)
if not file_path.is_valid_filename():
return Result.err('invalid file path "%s"' % file_path)
var file = FileAccess.open(file_path, FileAccess.WRITE)
var nodes = get_tree().get_nodes_in_group(group_name)
for node in nodes:

View file

@ -6,23 +6,37 @@ class_name Player extends CharacterBody3D
@onready var input = $Input
@onready var interactor = $Interactor
var is_carrying_item = false
var is_carrying_item = true
var is_weapon_ready: bool:
get: return is_carrying_item and input.is_weapon_ready
func _ready() -> void:
input.connect("interact", _on_interact)
input.connect('interact', _on_interact)
input.connect('fire', _on_fire)
func _physics_process(delta: float) -> void:
move_and_rotate(delta)
if is_weapon_ready:
rotate_toward_look(delta)
else:
move_and_rotate(delta)
func move_and_rotate(_delta: float):
var speed = run_speed if input.is_running else walk_speed
velocity = input.next_velocity(speed)
if !velocity.is_zero_approx():
look_at(global_position + velocity, Vector3.UP, true)
move_and_slide()
var speed = run_speed if input.is_running else walk_speed
velocity = input.next_velocity(speed)
if !velocity.is_zero_approx():
look_at(global_position + velocity, Vector3.UP, true)
move_and_slide()
func rotate_toward_look(_delta: float):
var target = input.get_look_target(global_position)
if target.is_some():
look_at(target.unwrap(), Vector3.UP, true)
func _on_interact():
interactor.interact_nearest()
func _on_fire():
if is_weapon_ready:
print('firing weapon')
func on_save():
return {

View file

@ -1,10 +1,59 @@
class_name PlayerInput extends Node
enum Device {
Unknown,
KeyboardMouse,
Gamepad
}
class Action:
static var Run = 'run'
static var Interact = 'interact'
static var Ready = 'ready'
static var Fire = 'fire'
signal walk
signal run
signal interact
signal ready_weapon
signal unready_weapon
signal fire
var is_running: bool = false
var is_interacting: bool = false
var last_known_device: Device = Device.Unknown
var _is_running: bool = false
var is_running: bool:
get: return _is_running
set(value):
if _is_running != value:
_is_running = value
if value: run.emit()
else: walk.emit()
var _is_interacting: bool = false
var is_interacting: bool:
get: return _is_interacting
set(value):
if _is_interacting != value:
_is_interacting = value
if value: interact.emit()
var _is_weapon_ready: bool = false
var is_weapon_ready: bool:
get: return _is_weapon_ready
set(value):
if _is_weapon_ready != value:
_is_weapon_ready = value
if value: ready_weapon.emit()
else: unready_weapon.emit()
var _is_firing: bool = false
var is_firing: bool:
get: return _is_firing
set(value):
if _is_firing != value:
_is_firing = value
if value: fire.emit()
var movement_dir: Vector2:
get: return Input.get_vector(
@ -12,17 +61,69 @@ var movement_dir: Vector2:
'move_up', 'move_down'
).normalized()
var _mouse_position: Vector2:
get:
var viewport = get_viewport()
var mouse_pos = viewport.get_mouse_position()
var cam = viewport.get_camera_3d()
var space_state = cam.get_world_3d().direct_space_state
var origin = cam.project_ray_origin(mouse_pos)
var end = origin + (cam.project_ray_normal(mouse_pos) * cam.far)
var query = PhysicsRayQueryParameters3D.create(origin, end)
var result = space_state.intersect_ray(query)
var position = result.get('position') as Vector3
return Vector2(position.x, position.z)
var _analog_dir: Vector2:
get: return Input.get_vector(
'look_left', 'look_right',
'look_up', 'look_down'
).normalized()
func _process(_delta: float) -> void:
var running = Input.is_action_pressed("run")
if running != is_running:
run.emit(running)
is_running = running
is_running = Input.is_action_pressed(Action.Run)
var was_interacting = is_interacting
is_interacting = Input.is_action_pressed("interact")
func _get_device(event: InputEvent) -> Device:
if event is InputEventMouse or event is InputEventKey:
return Device.KeyboardMouse
elif event is InputEventJoypadButton or event is InputEventJoypadMotion:
return Device.Gamepad
else:
return Device.Unknown
if is_interacting and not was_interacting:
interact.emit()
func _input(event: InputEvent) -> void:
last_known_device = _get_device(event)
if event.is_action_pressed(Action.Interact):
is_interacting = true
if event.is_action_released(Action.Interact):
is_interacting = false
if event.is_action_pressed(Action.Ready):
is_weapon_ready = true
if event.is_action_released(Action.Ready):
is_weapon_ready = false
if event.is_action_pressed(Action.Fire):
is_firing = true
if event.is_action_released(Action.Fire):
is_firing = false
func next_velocity(speed: float, dir: Vector2 = movement_dir) -> Vector3:
return Vector3(dir.x, 0, dir.y) * speed
func get_look_target(position: Vector3) -> Option:
match last_known_device:
Device.KeyboardMouse:
var pos = _mouse_position
return Option.some(Vector3(pos.x, position.y, pos.y))
Device.Gamepad:
var pos = _analog_dir
if pos.is_zero_approx():
return Option.none
return Option.some(Vector3(pos.x, 0, pos.y) + position)
_: return Option.none