class_name Movement_StateReceiver extends Node ## Movement component # attempts to interact with movement of the scene root without knowing what # it is. It can be perhaps a static body or kinematicbody # it doesn't actually move a node, that's what the state machine does # but it does keep track of velocity # I can't give it an actor node or a direct reference. # It can use a number of detection components to help inform decisions. export var debug_component: bool = false onready var current_state = StateAnimatedActor.new() onready var parent: KinematicBody2D = get_parent() export var callable_state_machine :NodePath var request_state_change: FuncRef var get_state_machine_modifiers: FuncRef #get_modifiers_of_type onready var desired_movement_vector: Vector2 = Vector2(0,0) # Since animactor state machine can actually view properties from this type # I'm thinking about moving the velocity tracker in here instead of player. #var velocity = Vector2(0,0) var velocity_controller :VelocityController = VelocityController.new() #Removing Probably not used #var sim_velocity = Vector2(0,0) var physics_delta:float var process_delta:float var state_duration:float = 0.0 ## Tracks how long we've been in state var modifier: StateModifierMovement #Removing Probably not used #var attack_function: FuncRef const UP = -1.0 const DOWN = 1.0 const LEFT = -1.0 const RIGHT = 1.0 #const TILE_SIZE = 4 var FLOOR_ANGLE_THRESHOLD := deg2rad(60) func _ready(): #velocity_controller.debug = true ## FuncRef to request state machine change state request_state_change = funcref(get_node(callable_state_machine), 'change_to_known_state') get_state_machine_modifiers = funcref(get_node(callable_state_machine), 'get_modifiers_of_type') ## Connect signal to get alerted of state change get_node(callable_state_machine).connect("state_changed", self,"_on_state_change") ## Get notified when modifiers updated get_node(callable_state_machine).connect("modifiers_updated",self,"_on_modifiers_updated") ## A reference to the current state machine state current_state = get_node(callable_state_machine).current_state ## A reference to the state machine merged modifiers #modifier = get_node(callable_state_machine).merged_animation_state_modifiers ############ ## These get called by the parent ############ func process_physics(delta): physics_delta = delta if has_method('_state_process_physics_' + current_state.name): call('_state_process_physics_' + current_state.name) else: apply_movement_to_parent( velocity_controller.calculate_velocity( physics_delta , apply_state_modifier(current_state.get_movement_parameters()), Vector2(0,1) ) ) # more likely needed for Players func process_physics_input(delta): physics_delta = delta desired_movement_vector = Vector2(0,0) if has_method('_state_process_physics_input_' + current_state.name): call('_state_process_physics_input_' + current_state.name) # More likely needed for NPCs func process(delta): process_delta = delta if has_method('_state_process_' + current_state.name): call('_state_process_' + current_state.name) # For event based input polling (Hadouken?) func process_unhandled_input(event: InputEvent): # Reset desired movement vector desired_movement_vector = Vector2(0,0) if has_method('_state_process_input_' + current_state.name): call('_state_process_input_' + current_state.name) ############ ############ ## A Series of helper functions ############ func go_up(): desired_movement_vector.y = UP func go_down(): desired_movement_vector.y = DOWN func go_left(): desired_movement_vector.x = LEFT func go_right(): desired_movement_vector.x = RIGHT func stop(): desired_movement_vector = Vector2(0,0) # Return the desired direction of movement for the character # in the range [-1, 1], where positive values indicate a desire # to move to the right and negative values to the left. func get_movement_direction() -> float: return desired_movement_vector.x # Return a boolean indicating if the character wants to jump func wants_jump() -> bool: return false # Return a boolean indicating if the character wants to attack func wants_shoot() -> bool: return false # Return a boolean indicating if the character wants to dash func wants_dash() -> bool: return false func wants_roll() -> bool: return false func wants_climb() -> bool: return false ############ func get_climb_shape_location() -> Vector2: return Vector2(-1,-1) func _on_state_change(old_state_name:String, new_state :State): ## Reset State Duration Counter state_duration = 0.0 ###### State machine if new_state is StateAnimatedActor: #Testing this. Update: It works ## Confirmed that I do neet to update the current_state with the passed state. current_state = new_state if has_method('_on_state_change_' + current_state.name): call('_on_state_change_' + current_state.name) else: push_warning("Received non animated Actor state.") #current_state = new_state func _on_modifiers_updated(_modifier_type :int, _modifier_action :int, _merged_modifier :StateModifier): ## Get reference (subscribe) to the merged modifier for movement if _merged_modifier is StateModifierMovement: if debug_component: print("Registered Modifier Movement: ", _merged_modifier.horizontal_speed) modifier = _merged_modifier func apply_state_modifier(movement_parameters :MovementParameters) -> MovementParameters: # if modifier and modifier.is_active: # if (current_state.is_grounded and modifier.only_grounded): # Should we skip # movement_parameters.apply_state_modifier(modifier) var active_mods :bool= true var mods :Array = get_state_machine_modifiers.call_func('StateModifierMovement', active_mods, current_state.is_grounded) if (mods.size() > 0): ## Process mods and supply current velocity for single directions movement_parameters.apply_multiple_modifiers(mods, velocity_controller.velocity) return movement_parameters ## Passed in acceleration, vel, etc is applied to whatever ## the parent is. If Kinematic then move_and_slide, otherwise manually adjusted func apply_movement_to_parent( _velocity :Vector2) -> void: #var snap = Vector2((_velocity.normalized().x * -1 * TILE_SIZE) ,DOWN * TILE_SIZE) var snap = Vector2.DOWN #* TILE_SIZE #var snap = Vector2.DOWN ## Disable snap when trying to jump (hacky?) if !current_state.is_grounded: snap = Vector2.ZERO if parent is KinematicBody2D: #velocity_controller.velocity = parent.move_and_slide_with_snap(_velocity, snap , Vector2.UP, true, 4, FLOOR_ANGLE_THRESHOLD) #velocity_controller.velocity.x = parent.move_and_slide(_velocity,Vector2.UP,false,TILE_SIZE,FLOOR_ANGLE_THRESHOLD).x velocity_controller.velocity = parent.move_and_slide_with_snap(_velocity, snap , Vector2.UP, true, 4, FLOOR_ANGLE_THRESHOLD) if !parent.is_on_floor() and parent.get_slide_count() == 0: var collision_to_floor = parent.get_floor_angle() var collision_count = parent.get_slide_count() var foo = 2+2 #move_and_slide_with_snap(linear_velocity: Vector2, snap: Vector2, up_direction: Vector2 = Vector2( 0, 0 ), stop_on_slope: bool = false, max_slides: int = 4, floor_max_angle: float = 0.785398, infinite_inertia: bool = true)