Setup project, bring over some source files as libraries
This commit is contained in:
parent
e0458f8170
commit
a591d9d94b
3
Main.tscn
Normal file
3
Main.tscn
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[gd_scene format=2]
|
||||
|
||||
[node name="Main" type="Node2D"]
|
||||
35
icon.png.import
Normal file
35
icon.png.import
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://icon.png"
|
||||
dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
process/normal_map_invert_y=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
||||
84
lib/classes/actor.gd
Normal file
84
lib/classes/actor.gd
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
class_name Actor
|
||||
extends KinematicBody2D
|
||||
|
||||
#var velocity = Vector2(0,0)
|
||||
#var direction = Vector2(-1,0)
|
||||
|
||||
export(String, "Player", "Enemy", "NPC", "Object") var actor_type
|
||||
#export var sprite_facing_right: bool = true
|
||||
export(Array, Resource) var SoundEffects
|
||||
export var debug_actor: bool = false
|
||||
|
||||
|
||||
onready var movement_animations: AnimatedSprite = $AnimatedSprite
|
||||
|
||||
onready var sound_effect_player: AudioStreamPlayer = $SE_Player
|
||||
|
||||
onready var movement_component: MovementComponent = $movement_component
|
||||
|
||||
onready var movement_state_machine: StateMachineAnimatedActor = $movement_state_machine
|
||||
|
||||
var sound_effects_dict: Dictionary
|
||||
|
||||
##TODO:
|
||||
# Can't seem to implement the ready and process node functions
|
||||
# without causing a double run somehow. Not sure why.
|
||||
# not a huge deal because this is mostly to help with
|
||||
# interfaces for the state machines.
|
||||
|
||||
func _ready() -> void:
|
||||
movement_state_machine.init_animated_actor(self, movement_animations, movement_component)
|
||||
movement_component.attack_function = funcref(self, "attack")
|
||||
# movement_component.player_number = player_number
|
||||
|
||||
# Experimenting with sound based resources I did this and it worked
|
||||
#sound_effect_player.stream = sound_effects.sounds["pew"]
|
||||
#print(sounds.sounds["pew"])
|
||||
#sound_effects.play()
|
||||
|
||||
# Trying something new with a custom resourse.
|
||||
for i in SoundEffects:
|
||||
sound_effects_dict[i.animation_name + str(i.frame_number)] = i.sound
|
||||
print (sound_effects_dict)
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if actor_type == "Player":
|
||||
movement_component.process_input(event)
|
||||
movement_state_machine.process_input(event)
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
movement_component.process_physics(delta)
|
||||
movement_state_machine.process_physics(delta)
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if actor_type == "NPC" or actor_type == "Enemy":
|
||||
movement_component.process(delta)
|
||||
movement_state_machine.process_frame(delta)
|
||||
# PlayerInfo.player_position = global_position
|
||||
play_sound_frame(movement_animations.animation , movement_animations.frame)
|
||||
|
||||
|
||||
var last_sound_frame_animation: String = ''
|
||||
var last_sound_frame: int = -1
|
||||
func play_sound_frame(animation: String, frame: int ):
|
||||
##DEBUG:
|
||||
#if animation == 'run' and frame == 6:
|
||||
# print("Do the thign! (", animation + str(frame), ")", " (", last_sound_frame_animation + str(last_sound_frame), ")")
|
||||
if animation != last_sound_frame_animation or frame != last_sound_frame:
|
||||
last_sound_frame = frame
|
||||
last_sound_frame_animation = animation
|
||||
var sound_index = animation + str(frame)
|
||||
if sound_effects_dict.has(sound_index):
|
||||
sound_effect_player.stream = sound_effects_dict[sound_index]
|
||||
sound_effect_player.play()
|
||||
print(self.name, " Playing SE: ", sound_index)
|
||||
|
||||
func attack():
|
||||
#print(self.name, ": It's not inheritence, it's funcrefs")
|
||||
if movement_state_machine.current_state.name != 'attack':
|
||||
if($movement_state_machine/attack):
|
||||
movement_state_machine.change_state($movement_state_machine/attack)
|
||||
if ($Hitbox_Component/CollisionShape2D):
|
||||
#print(self.name, ": Found a hitbox")
|
||||
var hit_box = $Hitbox_Component
|
||||
hit_box.set_hitbox(true)
|
||||
34
lib/classes/state.gd
Normal file
34
lib/classes/state.gd
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
class_name State
|
||||
extends Node
|
||||
|
||||
export var debug_state: bool = false
|
||||
export var timeout_seconds: float = 0.0
|
||||
|
||||
signal state_entered()
|
||||
signal state_exited()
|
||||
|
||||
# Declare member variables here. Examples:
|
||||
#var modifier_stack_ref: Array # Well this didn't work
|
||||
var state_timeout: Timer
|
||||
var state_ready: bool = true
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
func enter() -> void:
|
||||
pass
|
||||
|
||||
|
||||
func exit() -> void:
|
||||
pass
|
||||
|
||||
func process_input(_event: InputEvent) -> State:
|
||||
return null
|
||||
|
||||
func process_frame(_delta: float) -> State:
|
||||
return null
|
||||
|
||||
func process_physics(_delta: float) -> State:
|
||||
return null
|
||||
453
lib/classes/state_animated_actor.gd
Normal file
453
lib/classes/state_animated_actor.gd
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
class_name StateAnimatedActor
|
||||
extends State
|
||||
## Animation and movement state class
|
||||
##
|
||||
## A state intended to control the movement and animation
|
||||
## functions of a KinimaticBody2D node. Initialized with a
|
||||
## player, movement node, and kinematicbody2d
|
||||
## I think if we also had modifier states that transfered along with the enter and entrance of nodes, that would be helpful.
|
||||
##
|
||||
## @WIP
|
||||
|
||||
# export (NodePath) var jump_node
|
||||
|
||||
# onready var jump_state: State = get_node(jump_node)
|
||||
|
||||
## Deprecated
|
||||
# export var animation_name: String
|
||||
|
||||
# Movement Speed in Pixels Per Second
|
||||
export var move_speed: float = 60
|
||||
export var move_acceleration: float = 0
|
||||
export var move_speed_modifier: float = 0
|
||||
export var move_modifier_move_acceleration: float = 0
|
||||
export var jerk_factor: float = 0
|
||||
|
||||
#var adjusted_move_speed: float
|
||||
var jerk: float
|
||||
|
||||
var physics_modifier :StateModifier
|
||||
|
||||
##TODO: Deprecate this useless fool!
|
||||
var speed_multiplier: float = 1.0
|
||||
|
||||
export(Array, String) var animation_sequence
|
||||
|
||||
signal frame_reached(state_name, animation_name, frame_number)
|
||||
export(Dictionary) var emitter_frame_subscriptions
|
||||
var frame_signal_emitted: bool = false
|
||||
|
||||
var animation_finished: bool = false
|
||||
|
||||
|
||||
# this just wouldn't work well. Maybe I can try a resource
|
||||
# export(Array, NodePath) var transition_state_nodes
|
||||
|
||||
#TODO: I think these two variables accidentally serve the same purpose
|
||||
# I think one was intended to be a string of the current animation name.
|
||||
var animation_index: int = 0
|
||||
var current_animation_sequence: int = 0
|
||||
var animation_suffix: String = '';
|
||||
|
||||
var mod_animation_sequence = [PoolStringArray()]
|
||||
|
||||
var gravity: int = ProjectSettings.get_setting("physics/2d/default_gravity")
|
||||
|
||||
var animations: AnimatedSprite
|
||||
var move_component: MovementComponent
|
||||
var parent: KinematicBody2D
|
||||
|
||||
#animation_name :String, frame_number : int, animation_sequence :Array
|
||||
var previous_animation_name : String
|
||||
var previous_state_frame_number : int
|
||||
var previous_state_name: String
|
||||
var previous_speed_multiplier: float
|
||||
|
||||
var modifier: StateModifier
|
||||
|
||||
#var animation_sequence_timer: Timer
|
||||
|
||||
|
||||
|
||||
func _ready():
|
||||
##TODO: this bit me in the butt. Should add a safety or something.
|
||||
# Only add timout node if timer value was specified.
|
||||
if(timeout_seconds > 0.0):
|
||||
state_timeout = Timer.new()
|
||||
state_timeout.wait_time = timeout_seconds
|
||||
state_timeout.one_shot = true
|
||||
state_timeout.autostart = false
|
||||
add_child(state_timeout)
|
||||
|
||||
#modifier = StateModifier.new()
|
||||
|
||||
# If called, this will attempt to make the most appropriate animation change
|
||||
# would likely be triggered from an animation sequence finishing or a
|
||||
# modifier being applied/removed outside of enter/exit transitions.
|
||||
func update_animation(enter_frame := 0, index := 0, suffix := ''):
|
||||
## TODO:
|
||||
# Need to find a way to attempt to keep and transfer the Index or frame
|
||||
#
|
||||
# if clear_modifier:
|
||||
# print("Goodbye Modifiers!")
|
||||
# modifier = null
|
||||
# if modifier:
|
||||
# if modifier.state_timeout and modifier.timeout_seconds == 0:
|
||||
# modifier = null
|
||||
|
||||
# By Default, we build an animation sequence off of this state's before checking
|
||||
# for modifiers
|
||||
mod_animation_sequence.clear()
|
||||
mod_animation_sequence.append_array(animation_sequence)
|
||||
# Reset animation suffix in case there isn't one
|
||||
animation_suffix = suffix
|
||||
animation_index = index
|
||||
current_animation_sequence = animation_index
|
||||
#var enter_animation = ''
|
||||
#var enter_frame = 0
|
||||
|
||||
if modifier != null:
|
||||
# if modifier.modifier_type == modifier.TYPE.EXIT_ANIMATION:
|
||||
# #print("OHHH Modifier Applies! ", modifier.animation_name)
|
||||
# mod_animation_sequence.push_front(modifier.animation_name)
|
||||
# enter_frame = modifier.starting_frame
|
||||
match modifier.modifier_type:
|
||||
modifier.TYPE.EXIT_ANIMATION:
|
||||
mod_animation_sequence.push_front(modifier.animation_name)
|
||||
enter_frame = modifier.starting_frame
|
||||
|
||||
modifier.TYPE.ANIMATION_SUFFIX:
|
||||
if animations.frames.has_animation(mod_animation_sequence[animation_index] + modifier.animation_name):
|
||||
animation_suffix = modifier.animation_name
|
||||
else:
|
||||
print("Warning!: Modifier attempting to apply suffix that doesn't exist ",
|
||||
mod_animation_sequence[animation_index] + modifier.animation_name)
|
||||
|
||||
modifier.TYPE.REPLACE_ANIMATION:
|
||||
#animations.play(modifier_stack_ref[i].animation_name)
|
||||
#animations.frame = modifier_stack_ref[i].starting_frame
|
||||
mod_animation_sequence.clear()
|
||||
mod_animation_sequence.push_back(modifier.animation_name)
|
||||
enter_frame = modifier.starting_frame
|
||||
|
||||
# Some safety checks with supplied update parameters
|
||||
if animation_index != 0:
|
||||
if mod_animation_sequence.size() < animation_index + 1:
|
||||
if debug_state:
|
||||
print("Warning!: attempting to set to non-existant index ")
|
||||
animation_index = 0
|
||||
current_animation_sequence = animation_index
|
||||
|
||||
if animations.frames.has_animation(mod_animation_sequence[animation_index] + animation_suffix) == false:
|
||||
if debug_state:
|
||||
print("Warning!: Animation doesn't exist! ")
|
||||
|
||||
if enter_frame != 0:
|
||||
if animations.frames.get_frame_count(animations.animation) != animations.frames.get_frame_count(mod_animation_sequence[animation_index] + animation_suffix):
|
||||
if debug_state:
|
||||
print("Warning!: attempting to set a mismatched frame ")
|
||||
enter_frame = 0
|
||||
|
||||
if mod_animation_sequence.size() > 0:
|
||||
if debug_state:
|
||||
print("Starting Animation: " , mod_animation_sequence[animation_index] + animation_suffix)
|
||||
animations.play(mod_animation_sequence[animation_index] + animation_suffix)
|
||||
#TODO: maybe check current animatio has this frame
|
||||
animations.frame = enter_frame
|
||||
else:
|
||||
print("Error! Resolved to empty animation sequence!?")
|
||||
return
|
||||
|
||||
|
||||
func enter() -> void:
|
||||
if debug_state:
|
||||
print(parent.name, " entering State: ", self.name)
|
||||
move_component.current_movement_state = self.name
|
||||
emit_signal("state_entered")
|
||||
#modifier_stack_ref = state_modifiers
|
||||
update_animation()
|
||||
|
||||
# Reset movespeed counters
|
||||
#move_component.momentum.x = move_speed_modifier
|
||||
jerk = 0
|
||||
|
||||
return
|
||||
|
||||
func exit() -> void:
|
||||
emit_signal("state_exited")
|
||||
# animations.disconnect("animation_finished", self, "_on_AnimatedSprite_animation_finished")
|
||||
#modifier = null
|
||||
return
|
||||
|
||||
func transfer_modifiers(exiting_state_modifier : StateModifier):
|
||||
if modifier == null: # We have no existing modifier applied.
|
||||
match exiting_state_modifier.modifier_type:
|
||||
exiting_state_modifier.TYPE.ANIMATION_SUFFIX:
|
||||
if debug_state:
|
||||
print("Transferring Animation Suffix")
|
||||
modifier = exiting_state_modifier
|
||||
exiting_state_modifier.TYPE.EXIT_ANIMATION:
|
||||
if debug_state:
|
||||
print("Exit Animation: well this was useless.")
|
||||
else:
|
||||
print("Insert modifier merge function here...")
|
||||
|
||||
func process_input(_event: InputEvent) -> State:
|
||||
return null
|
||||
|
||||
func process_animations():
|
||||
|
||||
if modifier != null:
|
||||
if modifier.state_timeout and modifier.state_timeout.time_left == 0:
|
||||
print("Expired Modifier, updating animation.")
|
||||
#modifier = null
|
||||
match modifier.modifier_type:
|
||||
|
||||
modifier.TYPE.ANIMATION_SUFFIX:
|
||||
# Attempt to seemlessly transition animations.
|
||||
modifier = null
|
||||
update_animation(animations.frame,animation_index)
|
||||
|
||||
modifier.TYPE.REPLACE_ANIMATION:
|
||||
if debug_state:
|
||||
print("I don't have anything for replacements yet.")
|
||||
modifier = null
|
||||
update_animation()
|
||||
_:
|
||||
modifier = null
|
||||
return
|
||||
|
||||
|
||||
# We have no more sequence animations and the current one doesn't loop
|
||||
# we do this to prevent the default idle animation from playing.
|
||||
##TODO: between this and the signal based iterator I get some really strange behavior
|
||||
if animation_index >= mod_animation_sequence.size() and animations.frames.get_animation_loop(
|
||||
animations.animation) == false:
|
||||
#print(animations.animation, " Animation Stopped")
|
||||
animations.stop()
|
||||
#animation_finished = true
|
||||
elif mod_animation_sequence.size() > animation_index and current_animation_sequence != animation_index:
|
||||
#TODO: why was I doing this
|
||||
# if animation_index >= mod_animation_sequence.size():
|
||||
# animation_index = 0
|
||||
##TODO: Add a safety check here.
|
||||
animations.play(mod_animation_sequence[animation_index] + animation_suffix)
|
||||
if debug_state:
|
||||
print("An animation sequence: ", mod_animation_sequence[animation_index - 1], " -> ",
|
||||
animations.animation , " (", animation_index, ")")
|
||||
current_animation_sequence = animation_index
|
||||
|
||||
##TODO: Could probably add some more checks here.
|
||||
|
||||
# Singal based frame call.
|
||||
if emitter_frame_subscriptions.has(animations.frame):
|
||||
if emitter_frame_subscriptions[animations.frame] == animations.animation:
|
||||
if frame_signal_emitted == false:
|
||||
emit_signal("frame_reached", self.name, animations.animation, animations.frame)
|
||||
# Try to only so this once.
|
||||
frame_signal_emitted = true
|
||||
else:
|
||||
frame_signal_emitted = false
|
||||
|
||||
func process_frame(_delta: float) -> State:
|
||||
return null
|
||||
|
||||
func process_physics(_delta: float) -> State:
|
||||
move_actor_as_desired(_delta)
|
||||
return null
|
||||
|
||||
#func _on_AnimatedSprite_animation_finished():
|
||||
# if animations.frames.get_animation_loop(animations.animation) == false:
|
||||
# animation_index += 1
|
||||
|
||||
func move_actor_as_desired(delta: float, x_move_direction_override: float = 0):
|
||||
|
||||
var _move_speed = move_speed
|
||||
var _move_speed_modifier = move_speed_modifier
|
||||
var _move_modifier_move_acceleration = move_modifier_move_acceleration
|
||||
var _move_acceleration = move_acceleration
|
||||
var _jerk_factor = jerk_factor
|
||||
var _gravity = gravity
|
||||
|
||||
if physics_modifier:
|
||||
#physics_modifier.modifier_properties.jerk_factor
|
||||
#print(physics_modifier.name)
|
||||
#UiManager.debug_text = physics_modifier.name + str(round(adjusted_move_speed))
|
||||
var mod_props :ModifierProperties = physics_modifier.get_modifier_properties()
|
||||
if mod_props.move_speed != 0 and mod_props.directional_modifier == false:
|
||||
_move_speed = mod_props.move_speed
|
||||
_move_speed_modifier += mod_props.move_speed_modifier
|
||||
_move_acceleration += mod_props.move_acceleration
|
||||
_move_modifier_move_acceleration += mod_props.move_modifier_move_acceleration
|
||||
_jerk_factor += mod_props.jerk_factor
|
||||
|
||||
var help_me_not_be_dumb = ''
|
||||
|
||||
# Allow us to bump out of halt.
|
||||
if _move_speed == 0 and move_component.desired_movement_vector.x != 0:
|
||||
_move_speed = abs(move_component.desired_movement_vector.x)
|
||||
|
||||
# Determine or physics movement direction
|
||||
var current_x_velocity = move_component.velocity.x #move_component.velocity.x
|
||||
var move_direction = 0.0
|
||||
# Determine movement direction if we have momentum
|
||||
if move_component.momentum.x != 0:
|
||||
if x_move_direction_override == 0:
|
||||
move_direction = sign(current_x_velocity)
|
||||
# if move_component.desired_movement_vector.x != 0:
|
||||
# # set the move direction to the desired direction
|
||||
# move_direction = move_component.desired_movement_vector.x
|
||||
# else:
|
||||
# # Set move direction to the transform direction
|
||||
# move_direction = parent.transform.x.x
|
||||
else:
|
||||
move_direction = x_move_direction_override
|
||||
else: # No current momentum in place
|
||||
if x_move_direction_override == 0:
|
||||
move_direction = move_component.desired_movement_vector.x
|
||||
else:
|
||||
move_direction = x_move_direction_override
|
||||
|
||||
## TODO: I hate that I have to do this check again.
|
||||
if physics_modifier:
|
||||
var mod_props :ModifierProperties = physics_modifier.get_modifier_properties()
|
||||
if mod_props.move_speed != 0 and mod_props.directional_modifier == true:
|
||||
# Since move_direction is always positive
|
||||
if sign(move_direction) == sign(mod_props.move_speed):
|
||||
_move_speed += mod_props.move_speed
|
||||
else:
|
||||
_move_speed -= mod_props.move_speed
|
||||
if sign(move_direction) == 0:
|
||||
move_direction = sign(mod_props.move_speed) * -1
|
||||
#print("doing this? ")
|
||||
|
||||
|
||||
|
||||
# Determine the maximum move speed
|
||||
var MAX_SPEED :float = 0
|
||||
var MIN_SPEED :float = 0
|
||||
if sign(_move_speed_modifier) == -1: # decreased speed modifier
|
||||
help_me_not_be_dumb += '-SpeedMod'
|
||||
# Move speed cannot go below zero with modifier applied
|
||||
MIN_SPEED = _move_speed + _move_speed_modifier
|
||||
# Poor man's clamp
|
||||
if MIN_SPEED < 0:
|
||||
MIN_SPEED = 0
|
||||
MAX_SPEED = _move_speed
|
||||
elif sign(_move_speed_modifier) == +1: # increased speed modifier
|
||||
help_me_not_be_dumb += '+SpeedMod'
|
||||
MIN_SPEED = _move_speed
|
||||
MAX_SPEED = _move_speed + _move_speed_modifier
|
||||
else: # physics won't apply here
|
||||
help_me_not_be_dumb += '_Speed' # Neutral Speed
|
||||
MIN_SPEED = _move_speed
|
||||
MAX_SPEED = _move_speed
|
||||
|
||||
# get the latest aggregate acceleration
|
||||
# If we have any acceleration applying
|
||||
if (_move_modifier_move_acceleration + _move_acceleration) != 0:
|
||||
# The acceleration is differant
|
||||
# Perhaps it would be better to trigger this on a difference in modifier but they usually go together.
|
||||
if abs(move_component.acceleration.x) != abs(_move_modifier_move_acceleration + _move_acceleration):
|
||||
if move_direction:
|
||||
print("Acceleration changed.", abs(move_component.acceleration.x), "-", (_move_modifier_move_acceleration + _move_acceleration))
|
||||
move_component.acceleration.x = _move_modifier_move_acceleration + _move_acceleration
|
||||
|
||||
# If we're no longer tryingg to move int the direction of our movement and momentum.
|
||||
if sign(current_x_velocity) != sign(move_component.desired_movement_vector.x) and move_component.momentum.x != 0:
|
||||
if sign(_move_speed_modifier) == -1 : # decreased speed modifier
|
||||
|
||||
# Maybe we can compare the direction of the acceleration
|
||||
# The direction of the acceleration should usually be positive at this point.
|
||||
# when the modifier is negative.
|
||||
if sign(move_direction) == sign(current_x_velocity):
|
||||
if sign(move_component.acceleration.x) == sign(move_component.momentum.x):
|
||||
print("Whoh Woah")
|
||||
# Flip the direction of the acceleration
|
||||
move_component.acceleration.x *= -1
|
||||
if (sign(move_component.desired_movement_vector.x) == -1 and
|
||||
sign(current_x_velocity) == 1) or (sign(move_component.desired_movement_vector.x) == -1 and
|
||||
sign(current_x_velocity) == -1):
|
||||
print("be more opposite")
|
||||
# if sign(_move_speed_modifier) == 1: # increased speed modifier
|
||||
# print("faster faster.")
|
||||
elif sign(move_component.desired_movement_vector.x) == sign(current_x_velocity) and move_component.momentum.x != 0:
|
||||
if sign(move_component.acceleration.x) != sign(move_component.momentum.x) and x_move_direction_override == 0:
|
||||
print("Step it up!")
|
||||
# Flip the direction of the acceleration
|
||||
move_component.acceleration.x *= -1
|
||||
|
||||
# Apply momentum and acceleration if a modifer exists
|
||||
if move_component.momentum.x <= 0 and _move_speed_modifier !=0:
|
||||
#if we're trying to move but we have no momentum applied currently
|
||||
#if move_component.desired_movement_vector.x != 0:
|
||||
if move_direction:
|
||||
move_component.acceleration.x = _move_modifier_move_acceleration + _move_acceleration
|
||||
##TODO: I don't know where I should actually set the momentum. :
|
||||
if sign(_move_speed_modifier) == -1: # decreased speed modifier
|
||||
move_component.momentum.x = 0
|
||||
elif sign(_move_speed_modifier) == +1: # increased speed modifier
|
||||
##TODO: in most cases this should only be applied once. need to find a way to warn against this.
|
||||
move_component.momentum.x = abs(move_speed_modifier)
|
||||
print("momentum applied!")
|
||||
|
||||
# Reverse the accelerations if we carry over momentum but the modifier no longer applies.
|
||||
if move_component.momentum.x > 0 and _move_speed_modifier == 0:
|
||||
if sign(move_component.acceleration.x) == sign(move_component.momentum.x):
|
||||
print("Whoh Woah your done.")
|
||||
# Flip the direction of the acceleration
|
||||
move_component.acceleration.x *= -1
|
||||
|
||||
|
||||
# We're going to adjust our move speed only to the modifier
|
||||
move_component.momentum.x += move_component.acceleration.x * delta
|
||||
jerk += _jerk_factor * delta
|
||||
|
||||
|
||||
var new_move_speed :float = 0
|
||||
if sign(_move_speed_modifier) == -1: # decreased speed modifier
|
||||
# MIN_SPEED = _move_speed + _move_speed_modifier
|
||||
# MAX_SPEED = _move_speed
|
||||
move_component.momentum.x = clamp(move_component.momentum.x, 0, abs(_move_speed_modifier))
|
||||
# new_move_speed = (_move_speed + _move_speed_modifier ) + (sign(_move_speed_modifier) * -1 * move_component.momentum.x) # + jerk
|
||||
new_move_speed = MIN_SPEED + (sign(_move_speed_modifier) * -1 * move_component.momentum.x) # + jerk
|
||||
elif sign(_move_speed_modifier) == +1: # increased speed modifier
|
||||
# MIN_SPEED = _move_speed
|
||||
# MAX_SPEED = _move_speed + _move_speed_modifier
|
||||
move_component.momentum.x = clamp(move_component.momentum.x, 0, _move_speed_modifier )
|
||||
new_move_speed = _move_speed + move_component.momentum.x # + jerk
|
||||
else: # physics won't apply here
|
||||
# move_component.acceleration.x = 0
|
||||
# move_component.momentum.x = 0
|
||||
# new_move_speed = _move_speed
|
||||
move_component.momentum.x = clamp(move_component.momentum.x, 0, MIN_SPEED )
|
||||
new_move_speed = _move_speed + move_component.momentum.x # + jerk
|
||||
|
||||
#new_move_speed = clamp(new_move_speed, MIN_SPEED, MAX_SPEED)
|
||||
|
||||
var sim_move_speed = (MIN_SPEED + (sign(_move_speed_modifier) * -1 * move_component.momentum.x))
|
||||
|
||||
# if move_component.momentum.x != 0:
|
||||
if true:
|
||||
UiManager.debug_text = ( "Mod(" + str(sign(_move_speed_modifier)) + ") Dir(" + str(move_direction) + ") Vel(" + str(sign(current_x_velocity)) + ") Mov(" + str(sign(move_component.desired_movement_vector.x)) +
|
||||
")\nNS:" + str(round(sim_move_speed)) + #" Z:" + str(sign(_move_speed_modifier) * -1 * move_component.momentum.x) +
|
||||
"\nS:" + str(round(_move_speed + _move_speed_modifier)) + ",M" + str(round(move_component.momentum.x)) +
|
||||
",A" + str(round(move_component.acceleration.x)) +
|
||||
"\nVel:" + str(round(move_component.velocity.x)) + "Min:" + str(round(MIN_SPEED)) + ",Max:" + str(round(MAX_SPEED))
|
||||
) # str(round(jerk))
|
||||
|
||||
move_component.sim_velocity.x = move_direction * sim_move_speed
|
||||
#print(adjusted_move_speed, ",", new_move_speed, ",", jerk)
|
||||
|
||||
#print(new_move_speed, " ", adjusted_move_speed)
|
||||
|
||||
move_component.velocity.y += _gravity * delta
|
||||
#parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
|
||||
#print(speed_multiplier)
|
||||
# move_component.velocity.x = move_component.desired_movement_vector.x * _move_speed
|
||||
move_component.velocity.x = move_direction * new_move_speed
|
||||
#move_component.velocity = parent.move_and_slide(move_component.velocity, Vector2.UP)
|
||||
var snap = Vector2.DOWN * 8
|
||||
if move_component.velocity.y < -8:
|
||||
snap = Vector2.ZERO
|
||||
move_component.velocity = parent.move_and_slide_with_snap(move_component.velocity, snap , Vector2.UP, true)
|
||||
50
lib/classes/state_machine.gd
Normal file
50
lib/classes/state_machine.gd
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
class_name StateMachine extends Node
|
||||
|
||||
export (NodePath) var starting_state
|
||||
export var debug_state_machine: bool = false
|
||||
|
||||
var current_state: State
|
||||
#var state_modifiers: Array
|
||||
|
||||
# Initialize the state machine by giving each child state a reference to the
|
||||
# parent object it belongs to and enter the default starting_state.
|
||||
func init() -> void:
|
||||
for child in get_children():
|
||||
if child is State:
|
||||
if debug_state_machine:
|
||||
print("Initializing State Node: ", child.name)
|
||||
# child.modifier_stack_ref = state_modifiers
|
||||
if debug_state_machine:
|
||||
child.debug_state = true
|
||||
|
||||
# Initialize to the default state
|
||||
change_state(get_node(starting_state))
|
||||
|
||||
# Change to the new state by first calling any exit logic on the current state.
|
||||
func change_state(new_state: State) -> void:
|
||||
if current_state:
|
||||
current_state.exit()
|
||||
|
||||
current_state = new_state
|
||||
current_state.enter()
|
||||
# if(state_modifiers.size() > 0 and debug_state_machine):
|
||||
# print("Active Modifiers:")
|
||||
# for mods in state_modifiers:
|
||||
# print(mods.name)
|
||||
|
||||
# Pass through functions for the Player to call,
|
||||
# handling state changes as needed.
|
||||
func process_physics(delta: float) -> void:
|
||||
var new_state = current_state.process_physics(delta)
|
||||
if new_state:
|
||||
change_state(new_state)
|
||||
|
||||
func process_input(event: InputEvent) -> void:
|
||||
var new_state = current_state.process_input(event)
|
||||
if new_state:
|
||||
change_state(new_state)
|
||||
|
||||
func process_frame(delta: float) -> void:
|
||||
var new_state = current_state.process_frame(delta)
|
||||
if new_state:
|
||||
change_state(new_state)
|
||||
126
lib/classes/state_machine_animated_actor.gd
Normal file
126
lib/classes/state_machine_animated_actor.gd
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
class_name StateMachineAnimatedActor extends StateMachine
|
||||
|
||||
#var physics_modifier : StateModifier
|
||||
|
||||
func change_state(new_state: State) -> void:
|
||||
if new_state.state_ready == false:
|
||||
# Don't transition to unready state
|
||||
return
|
||||
if current_state:
|
||||
current_state.exit()
|
||||
# Set parameters for information
|
||||
if new_state is StateAnimatedActor and current_state is StateAnimatedActor:
|
||||
set_previous_animation( current_state, new_state)
|
||||
if current_state.modifier: # Current state has a modifier
|
||||
new_state.transfer_modifiers(current_state.modifier)
|
||||
current_state.modifier = null
|
||||
if current_state.physics_modifier: # Current state has a physics modifier
|
||||
new_state.physics_modifier = current_state.physics_modifier
|
||||
current_state.physics_modifier = null
|
||||
|
||||
current_state = new_state
|
||||
current_state.enter()
|
||||
# if(state_modifiers.size() > 0 and debug_state_machine):
|
||||
# print("Active Modifiers:")
|
||||
# for mods in state_modifiers:
|
||||
# print(mods.name)
|
||||
|
||||
func set_previous_animation( old_state: StateAnimatedActor, new_state: StateAnimatedActor ) -> void:
|
||||
# added this to help prevent nul index crashes. (Usually because of signal based state changes.)
|
||||
if old_state.mod_animation_sequence:
|
||||
new_state.previous_animation_name = old_state.mod_animation_sequence[old_state.current_animation_sequence]
|
||||
new_state.previous_state_frame_number = old_state.animations.frame
|
||||
new_state.previous_state_name = old_state.name
|
||||
new_state.previous_speed_multiplier = old_state.speed_multiplier
|
||||
#animation_name :String, frame_number : int, animation_sequence :Array
|
||||
return
|
||||
|
||||
# Initialize the state machine by giving each child state a reference to the
|
||||
# parent object it belongs to and enter the default starting_state.
|
||||
func init_animated_actor(parent: KinematicBody2D, animations: AnimatedSprite, move_component: MovementComponent) -> void:
|
||||
animations.connect("animation_finished", self, "_on_AnimatedSprite_animation_finished")
|
||||
for child in get_children():
|
||||
if child is StateAnimatedActor:
|
||||
if debug_state_machine:
|
||||
print("Initializing State Node for ", parent.name, ": ", child.name)
|
||||
child.parent = parent
|
||||
child.animations = animations
|
||||
child.move_component = move_component
|
||||
# child.modifier_stack_ref = state_modifiers
|
||||
if debug_state_machine:
|
||||
child.debug_state = true
|
||||
|
||||
# Initialize to the default state
|
||||
change_state(get_node(starting_state))
|
||||
|
||||
|
||||
func process_frame(delta: float) -> void:
|
||||
# Check the state modifiers for timeouts, and maybe more conditions later
|
||||
# If the modifier is no longer valid, pop it from the stack.
|
||||
# We could iterate through a whole list of states but I'm not sure i want
|
||||
# states to be that complex.
|
||||
# var current_anim_state :StateAnimatedActor = current_state
|
||||
# if state_modifiers.empty() == false:
|
||||
# for i in range(state_modifiers.size()):
|
||||
# # if this modifer is a timer based one
|
||||
# if state_modifiers[i].state_timeout.time_left == 0 and state_modifiers[i].timeout_seconds !=0:
|
||||
# # Need to do extra stuff if it's an animation based one
|
||||
# if state_modifiers[i].modifier_type == "Animation Suffix":
|
||||
# if debug_state_machine:
|
||||
# print("State Modifier Timeout: ", state_modifiers[i].name, " -> ", state_modifiers[i].animation_name)
|
||||
# # Reset animation suffix
|
||||
# current_anim_state.animation_suffix = ''
|
||||
# # Get the current frame of animation
|
||||
# var current_frame = current_anim_state.animations.frame
|
||||
#
|
||||
# # Set the animation index to the current one
|
||||
# current_anim_state.animation_index = current_anim_state.current_animation_sequence
|
||||
# #current_anim_state.current_animation_sequence
|
||||
# #current_anim_state.animations.play()
|
||||
#
|
||||
# current_anim_state.animations.play(
|
||||
# current_anim_state.mod_animation_sequence[current_anim_state.animation_index])
|
||||
# # Try to set the current frame to the same as before.
|
||||
# current_anim_state.animations.frames.frames.size() >= current_frame
|
||||
# current_anim_state.animations.frame = current_frame
|
||||
#
|
||||
# if debug_state_machine:
|
||||
# print("Pop State Modifier: ", state_modifiers[i].name)
|
||||
# state_modifiers.pop_at(i)
|
||||
if current_state is StateAnimatedActor:
|
||||
current_state.process_animations()
|
||||
var new_state = current_state.process_frame(delta)
|
||||
if new_state:
|
||||
change_state(new_state)
|
||||
|
||||
|
||||
func _on_AnimatedSprite_animation_finished():
|
||||
# if debug_state_machine:
|
||||
# print("Stop!!!!!")
|
||||
##TODO:
|
||||
# It's hard to pop an exit animation off when it's stacked with another kind of animation.
|
||||
# for i in state_modifiers.size():
|
||||
# if state_modifiers[i].modifier_type == "Exit Animation":
|
||||
# #print("Time to pop state modifer: ", state_modifiers[i].animation_name, current_state.animation_suffix, " <-> ", current_state.animations.animation + current_state.animation_suffix)
|
||||
# if (state_modifiers[i].animation_name + current_state.animation_suffix) == current_state.animations.animation:
|
||||
# print("Time to pop state modifer: ", state_modifiers[i].animation_name, current_state.animation_suffix, " <-> ", current_state.animations.animation )
|
||||
# print(current_state.mod_animation_sequence)
|
||||
# state_modifiers.pop_at(i)
|
||||
# current_state.animation_index += 1
|
||||
# break
|
||||
|
||||
# if current_state is StateAnimatedActor:
|
||||
# current_state.animation_finished = true
|
||||
if current_state.animations.frames.get_animation_loop(
|
||||
current_state.animations.animation) == false:
|
||||
#print("Stop!!!!!", current_state.animation_sequence.size(), " - ", current_state.animation_index)
|
||||
if current_state.animation_sequence.size() > 0:
|
||||
#print("<-- next anim.")
|
||||
current_state.animation_index += 1
|
||||
if current_state.animation_index >= current_state.animation_sequence.size():
|
||||
#print("Stop!!!!!")
|
||||
current_state.animation_finished = true
|
||||
|
||||
|
||||
|
||||
|
||||
133
lib/classes/state_modifier.gd
Normal file
133
lib/classes/state_modifier.gd
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
class_name StateModifier
|
||||
extends Reference
|
||||
## State modification
|
||||
##
|
||||
## A state modifier doesn't have any direct control of a game object.
|
||||
## They are transfered from the enter and exit of other states and
|
||||
## influence the movement or animation of their parent states.
|
||||
## Rather than going full into paralell state machines I hope that this
|
||||
## modifier will be suitable for a basic state machine.
|
||||
##
|
||||
## @WIP
|
||||
|
||||
enum TYPE {NONE,EXIT_ANIMATION, ANIMATION_SUFFIX, REPLACE_ANIMATION}
|
||||
|
||||
var debug_state: bool = false
|
||||
|
||||
## These should be the original properties set when the modifier is created.
|
||||
# property changes can be applied over time but these are the instantiated values.
|
||||
var modifier_properties: ModifierProperties
|
||||
|
||||
## Animation modifier variables
|
||||
## The name of the animation that could be applied and starting frame
|
||||
var animation_name: String
|
||||
var starting_frame: int = 0
|
||||
##TODO: Animation speed
|
||||
|
||||
## Modification Type
|
||||
## if an animation is specified, the default behavior will be just to override
|
||||
## the state animation. Or perform a 'Replace Animation'
|
||||
var modifier_type = TYPE.NONE
|
||||
|
||||
var name :String = ''
|
||||
|
||||
# Move Speed in Pixels Per Second
|
||||
# These should only apply if Modification Type Set to None.
|
||||
# (But I'm not sure if I like that model.)
|
||||
#var move_speed: float
|
||||
#var move_speed_modifier: float = 0
|
||||
#var move_speed_modifier_decay: float = 0
|
||||
|
||||
var gravity: int = ProjectSettings.get_setting("physics/2d/default_gravity")
|
||||
|
||||
|
||||
# Attempting to use this as an animation suffix that can linger after
|
||||
# state transition like 'run-fire' to 'idle-fire' 'jump-fire' etc.
|
||||
#var animation_suffix: bool = false
|
||||
#var pre_append_animation: bool = false
|
||||
|
||||
# not sure if I can do the array thing from state change. Maybe?
|
||||
# disabling this sequencing for now.
|
||||
# export(Array, String) var animation_sequence
|
||||
# var animation_index: int = 0
|
||||
# var current_animation_sequence: int = 0
|
||||
|
||||
|
||||
#var animation_sequence_timer: Timer
|
||||
|
||||
var state_timeout: Timer
|
||||
var timeout_seconds: float = 0.0
|
||||
|
||||
# Meant to be called on timeout or other counters this modifier may have.
|
||||
# Should be updated whenever modifier owner transfers
|
||||
var state_call_function: FuncRef
|
||||
|
||||
## Can't do it this way.
|
||||
#func copy_modifier() -> StateModifier:
|
||||
# var new_modifier = StateModifier.new()
|
||||
# new_modifier.ready(animation_name, modifier_type, timeout_seconds)
|
||||
#
|
||||
# return StateModifier.new()
|
||||
#
|
||||
func merge_modifier(merging_mod: ModifierProperties):
|
||||
if merging_mod.modifier_type != TYPE.NONE:
|
||||
print("Warning Merging modifier types that aren't set to 'none' is not supported!")
|
||||
return
|
||||
# Can't support timeouts or animation stuff right now.
|
||||
#timeout_seconds = merging_mod.timeout_seconds
|
||||
# move_speed = merging_mod.move_speed
|
||||
# gravity = merging_mod.gravity
|
||||
# move_speed_modifier = merging_mod.move_speed_modifier
|
||||
# move_speed_modifier_decay = merging_mod.move_speed_modifier_decay
|
||||
|
||||
|
||||
func get_modifier_properties() -> ModifierProperties:
|
||||
#( p_move_speed:float, p_gravity:int , p_move_acceleration , p_move_speed_modifier:float,
|
||||
# p_move_modifier_move_acceleration:float, p_jerk_factor: float):
|
||||
var mp = ModifierProperties.new( modifier_properties.move_speed,
|
||||
modifier_properties.gravity,
|
||||
modifier_properties.move_acceleration,
|
||||
modifier_properties.move_speed_modifier,
|
||||
modifier_properties.move_modifier_move_acceleration,
|
||||
modifier_properties.jerk_factor)
|
||||
mp.directional_modifier = modifier_properties.directional_modifier
|
||||
return mp
|
||||
|
||||
func ready(modifier_name:String, anim_name:String = '', type = TYPE.NONE, timeout : float = 0, parent:Node = null, function_name : String = "") -> Timer:
|
||||
name = modifier_name
|
||||
# If somebody forgot to specify the type
|
||||
if anim_name != '' and type == TYPE.NONE:
|
||||
modifier_type = TYPE.REPLACE_ANIMATION
|
||||
animation_name = anim_name
|
||||
modifier_type = type
|
||||
# if parent != null and function_name != "":
|
||||
# state_call_function = funcref(parent, function_name)
|
||||
|
||||
modifier_properties = ModifierProperties.new(0,0,0,0,0,0)
|
||||
|
||||
if timeout > 0:
|
||||
state_timeout = Timer.new()
|
||||
state_timeout.wait_time = timeout
|
||||
state_timeout.one_shot = true
|
||||
state_timeout.autostart = false
|
||||
return state_timeout
|
||||
#add_child(state_timeout)
|
||||
#ModifierProperties.new()
|
||||
return null
|
||||
|
||||
|
||||
## Transfer and callback related methods. These sort of worked but I didn't end up using them
|
||||
## They're an interesting idea though.
|
||||
func transfer_owner(parent:Node):
|
||||
print("Modifier owner will now be: ", parent.name)
|
||||
state_call_function = funcref(parent, 'update_animation')
|
||||
|
||||
func _on_Timer_timeout():
|
||||
#print("Oh Crap! I can't beleive it worked")
|
||||
if state_call_function:
|
||||
if state_call_function.is_valid():
|
||||
state_call_function.call_func()
|
||||
else:
|
||||
print("Warning! Modifier timed out with no callback to alert.")
|
||||
else:
|
||||
print("Warning! no function applies.")
|
||||
28
lib/classes/state_modifier_properties.gd
Normal file
28
lib/classes/state_modifier_properties.gd
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
class_name ModifierProperties
|
||||
extends Reference
|
||||
|
||||
var modifier_type: int = 0
|
||||
#var timeout_seconds: float = 0.0
|
||||
|
||||
var move_speed: float = 0.0
|
||||
var move_acceleration: float = 0.0
|
||||
var move_speed_modifier: float = 0.0
|
||||
var move_modifier_move_acceleration: float = 0.0
|
||||
var jerk_factor: float = 0
|
||||
|
||||
var gravity:int = 0
|
||||
|
||||
# Bad name. Just means that it is intended to apply in a certain direction
|
||||
# (Positive or negative) not an offset of the existing values.
|
||||
var directional_modifier: bool = false
|
||||
|
||||
|
||||
func _init( p_move_speed:float, p_gravity:int , p_move_acceleration , p_move_speed_modifier:float,
|
||||
p_move_modifier_move_acceleration:float, p_jerk_factor: float):
|
||||
#timeout_seconds = p_timeout_seconds
|
||||
move_speed = p_move_speed
|
||||
move_acceleration = p_move_acceleration
|
||||
gravity = p_gravity
|
||||
move_speed_modifier = p_move_speed_modifier
|
||||
move_modifier_move_acceleration = p_move_modifier_move_acceleration
|
||||
jerk_factor = p_jerk_factor
|
||||
26
lib/components/GenericReceiver.gd
Normal file
26
lib/components/GenericReceiver.gd
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
extends Node
|
||||
|
||||
export(String) var body_entered_function = ""
|
||||
|
||||
var call_function: FuncRef
|
||||
|
||||
# Declare member variables here. Examples:
|
||||
# var a = 2
|
||||
# var b = "text"
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
if body_entered_function:
|
||||
call_function = funcref(owner, body_entered_function)
|
||||
#call_function.call_func()
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
#func _process(delta):
|
||||
# pass
|
||||
|
||||
func on_body_entered(sender):
|
||||
print("Receiving call from " + sender.name)
|
||||
if body_entered_function:
|
||||
call_function.call_func(sender)
|
||||
|
||||
6
lib/components/GenericReceiver.tscn
Normal file
6
lib/components/GenericReceiver.tscn
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/components/GenericReceiver.gd" type="Script" id=1]
|
||||
|
||||
[node name="GenericReceiver" type="Node"]
|
||||
script = ExtResource( 1 )
|
||||
41
lib/components/GenericSender.gd
Normal file
41
lib/components/GenericSender.gd
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
extends Area2D
|
||||
|
||||
export(String) var receiver_node_name = ""
|
||||
|
||||
# Declare member variables here. Examples:
|
||||
# var a = 2
|
||||
# var b = "text"
|
||||
|
||||
|
||||
## Called when the node enters the scene tree for the first time.
|
||||
#func _ready():
|
||||
# pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
#func _process(delta):
|
||||
# pass
|
||||
|
||||
##TODO: maybe guarantee type with receiver node type instead of just the name.
|
||||
# The the name helps keep the receiver type generic.
|
||||
|
||||
func _on_GenericSender_body_entered(body):
|
||||
if body.has_node(receiver_node_name):
|
||||
body.get_node(receiver_node_name).on_body_entered(self)
|
||||
|
||||
|
||||
#func _on_Hurtbox_Component_area_shape_entered(area_rid, area, area_shape_index, local_shape_index):
|
||||
# #print(area.get_parent().name, "hit", owner.name)
|
||||
## if area.get_parent().has_method("gotcha"):
|
||||
# print(area.get_parent().name, " you can do it.", owner.name)
|
||||
#
|
||||
# if owner.has_method("_on_Hurtbox_area_entered"):
|
||||
# owner.call("_on_Hurtbox_area_entered")
|
||||
# print(area.get_parent().name, " just hit me: ", owner.name)
|
||||
|
||||
|
||||
|
||||
func _on_GenericSender_area_shape_entered(area_rid, area, area_shape_index, local_shape_index):
|
||||
if area.get_parent().has_node(receiver_node_name):
|
||||
area.get_parent().get_node(receiver_node_name).on_body_entered(self)
|
||||
|
||||
11
lib/components/GenericSender.tscn
Normal file
11
lib/components/GenericSender.tscn
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/components/GenericSender.gd" type="Script" id=1]
|
||||
|
||||
[node name="GenericSender" type="Area2D"]
|
||||
collision_layer = 0
|
||||
collision_mask = 32768
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[connection signal="area_shape_entered" from="." to="." method="_on_GenericSender_area_shape_entered"]
|
||||
[connection signal="body_entered" from="." to="." method="_on_GenericSender_body_entered"]
|
||||
26
lib/components/Health_Component.gd
Normal file
26
lib/components/Health_Component.gd
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
class_name HealthComponent
|
||||
extends Node
|
||||
|
||||
export var max_health: int = 0
|
||||
onready var health :int = max_health
|
||||
|
||||
|
||||
signal health_depleted()
|
||||
|
||||
func take_damage(damage_amount :int):
|
||||
if damage_amount < 0:
|
||||
print("ERROR: Only positive numbers in health component functions.")
|
||||
health -= damage_amount
|
||||
|
||||
if health <= 0:
|
||||
emit_signal("health_depleted")
|
||||
health = 0
|
||||
|
||||
func heal(heal_amount :int):
|
||||
if heal_amount < 0:
|
||||
print("ERROR: Only positive numbers in health component functions.")
|
||||
return
|
||||
health += heal_amount
|
||||
|
||||
if health > max_health:
|
||||
health = max_health
|
||||
6
lib/components/Health_Component.tscn
Normal file
6
lib/components/Health_Component.tscn
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/components/Health_Component.gd" type="Script" id=1]
|
||||
|
||||
[node name="Health_Component" type="Node"]
|
||||
script = ExtResource( 1 )
|
||||
18
lib/components/Hitbox_Component.gd
Normal file
18
lib/components/Hitbox_Component.gd
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
extends Area2D
|
||||
|
||||
export(int) var damage_amount = 0
|
||||
|
||||
func set_hitbox(enabled: bool):
|
||||
for child in get_children():
|
||||
if child is CollisionShape2D:
|
||||
child.set_deferred("disabled", !enabled)
|
||||
## TODO: This breaks now I guess because I moved the process functions out to parent class
|
||||
#player_hurtbox.set_deferred("disabled", !enabled) #WTF Apparently this is how to do it
|
||||
|
||||
|
||||
func _on_Hitbox_Component_area_shape_entered(area_rid, area, area_shape_index, local_shape_index):
|
||||
var colliding_node = area.get_parent()
|
||||
if colliding_node.has_node("Hurtbox_Component"):
|
||||
colliding_node.get_node("Hurtbox_Component").on_hit(self)
|
||||
else:
|
||||
print(owner.name, ": Attempted to Hit an unready node, no Hurtbox_Component reciever node in ", colliding_node.name)
|
||||
10
lib/components/Hitbox_Component.tscn
Normal file
10
lib/components/Hitbox_Component.tscn
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/components/Hitbox_Component.gd" type="Script" id=1]
|
||||
|
||||
[node name="Hitbox_Component" type="Area2D"]
|
||||
collision_layer = 128
|
||||
collision_mask = 0
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[connection signal="area_shape_entered" from="." to="." method="_on_Hitbox_Component_area_shape_entered"]
|
||||
45
lib/components/Hurtbox_Component.gd
Normal file
45
lib/components/Hurtbox_Component.gd
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
extends Area2D
|
||||
|
||||
export(String) var hurtbox_entered_function = ""
|
||||
|
||||
var call_function: FuncRef
|
||||
|
||||
# Declare member variables here. Examples:
|
||||
# var a = 2
|
||||
# var b = "text"
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
if hurtbox_entered_function:
|
||||
call_function = funcref(owner, hurtbox_entered_function)
|
||||
else:
|
||||
print("Warning: No hurtbox function defined on ", owner.name)
|
||||
|
||||
func set_hurtbox(enabled: bool):
|
||||
for child in get_children():
|
||||
if child is CollisionShape2D:
|
||||
child.set_deferred("disabled", !enabled)
|
||||
|
||||
# Switching to a new model that starts with Hitbox
|
||||
func on_hit(sender):
|
||||
print("Received hit from: " + sender.owner.name)
|
||||
if hurtbox_entered_function:
|
||||
call_function.call_func(sender.damage_amount)
|
||||
|
||||
# This one doesn't seem to work
|
||||
#func _on_Hurtbox_Component_body_entered(body):
|
||||
# print(body.name, "hit", owner.name)
|
||||
# if owner.has_method("gotcha"):
|
||||
# print(body.name, " you can do it.", owner.name)
|
||||
|
||||
|
||||
# well this one works.
|
||||
#func _on_Hurtbox_Component_area_shape_entered(area_rid, area, area_shape_index, local_shape_index):
|
||||
# #print(area.get_parent().name, "hit", owner.name)
|
||||
## if area.get_parent().has_method("gotcha"):
|
||||
# print(area.get_parent().name, " you can do it.", owner.name)
|
||||
#
|
||||
# if owner.has_method("_on_Hurtbox_area_entered"):
|
||||
# owner.call("_on_Hurtbox_area_entered")
|
||||
# print(area.get_parent().name, " just hit me: ", owner.name)
|
||||
6
lib/components/Hurtbox_Component.tscn
Normal file
6
lib/components/Hurtbox_Component.tscn
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/components/Hurtbox_Component.gd" type="Script" id=1]
|
||||
|
||||
[node name="Hurtbox_Component" type="Area2D"]
|
||||
script = ExtResource( 1 )
|
||||
52
lib/components/Modifier_Component.gd
Normal file
52
lib/components/Modifier_Component.gd
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
extends Area2D
|
||||
|
||||
|
||||
var modifier_type = 0
|
||||
|
||||
export var modifier_name :String = ''
|
||||
var animation_name: String = '' # Not using this one
|
||||
var timeout_seconds: float = 0.0 # Not doing timeout based ones yet either.
|
||||
|
||||
export var directional_modifier: bool = false
|
||||
|
||||
export var move_speed: float = 0.0
|
||||
export var move_acceleration: float = 0.0
|
||||
export var move_speed_modifier: float = 0.0
|
||||
export var move_modifier_move_acceleration: float = 0.0
|
||||
export var jerk_factor: float = 0
|
||||
|
||||
export var gravity_modifier: int = 0
|
||||
|
||||
#var state_timeout: Timer
|
||||
|
||||
# Declare member variables here. Examples:
|
||||
# var a = 2
|
||||
# var b = "text"
|
||||
|
||||
var modifier :StateModifier
|
||||
#var modifier_properties: ModifierProperties
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
modifier = StateModifier.new()
|
||||
modifier.ready( modifier_name, animation_name , modifier.TYPE.NONE, timeout_seconds)
|
||||
modifier.modifier_properties = ModifierProperties.new( move_speed,
|
||||
gravity_modifier,
|
||||
move_acceleration,
|
||||
move_speed_modifier,
|
||||
move_modifier_move_acceleration,
|
||||
jerk_factor)
|
||||
print("Debug Direction property shy are you stopid?! ", directional_modifier)
|
||||
modifier.modifier_properties.directional_modifier = directional_modifier
|
||||
|
||||
func _on_Modifier_Component_body_entered(body):
|
||||
var colliding_node = body
|
||||
if colliding_node.has_node("Modifier_Receiver"):
|
||||
colliding_node.get_node("Modifier_Receiver").register_modifier(modifier)
|
||||
|
||||
|
||||
func _on_Modifier_Component_body_exited(body):
|
||||
var colliding_node = body
|
||||
if colliding_node.has_node("Modifier_Receiver"):
|
||||
colliding_node.get_node("Modifier_Receiver").remove_modifier(modifier)
|
||||
9
lib/components/Modifier_Component.tscn
Normal file
9
lib/components/Modifier_Component.tscn
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/components/Modifier_Component.gd" type="Script" id=1]
|
||||
|
||||
[node name="Modifier_Component" type="Area2D"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[connection signal="body_entered" from="." to="." method="_on_Modifier_Component_body_entered"]
|
||||
[connection signal="body_exited" from="." to="." method="_on_Modifier_Component_body_exited"]
|
||||
53
lib/components/Modifier_Receiver.gd
Normal file
53
lib/components/Modifier_Receiver.gd
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
class_name Modifier_Receiver
|
||||
extends Node2D
|
||||
|
||||
# This may be stupid but we're going to have two kinds of callbacks here.
|
||||
# It's going to be up to the parent/actor/kinematicbody2d/whatever to know
|
||||
# what conditions have to be met before being able to call that interactible's
|
||||
# function.
|
||||
# This is a nice and generic interface that I might be able to use for
|
||||
# things like opening doors in a level, opening chests/flipping switches etc.
|
||||
|
||||
# This node can keep an array of various interactibles within a level
|
||||
# and provide several helper functions for managing them perhaps.
|
||||
|
||||
export(String) var modifier_parent_callback = ""
|
||||
export var debug_receiver :bool = false
|
||||
|
||||
var call_function: FuncRef
|
||||
|
||||
#var interactable_function_callables = []
|
||||
|
||||
var modifier_collection = []
|
||||
|
||||
# Declare member variables here. Examples:
|
||||
# var a = 2
|
||||
# var b = "text"
|
||||
|
||||
##NOTE:
|
||||
## Call function should be implemented as two parameters, one expecting a modifier
|
||||
## and the other expecting a boolean as to whether its being added
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
if modifier_parent_callback:
|
||||
call_function = funcref(owner, modifier_parent_callback)
|
||||
else:
|
||||
print("Warning: No modifier receiver function defined on ", owner.name)
|
||||
|
||||
# Switching to a new model that starts with Hitbox
|
||||
func register_modifier(modifier: StateModifier):
|
||||
if modifier_collection.has(modifier) == false:
|
||||
print("New Modifier Registered " + modifier.name)
|
||||
modifier_collection.append(modifier)
|
||||
if call_function.is_valid():
|
||||
call_function.call_func(modifier, true)
|
||||
|
||||
func remove_modifier(modifier):
|
||||
print("Modifier Removal " + modifier.name)
|
||||
if modifier_collection.has(modifier):
|
||||
var modifier_index = modifier_collection.rfind(modifier)
|
||||
if modifier_index != -1:
|
||||
modifier_collection.remove(modifier_index)
|
||||
if call_function.is_valid():
|
||||
call_function.call_func(modifier, false)
|
||||
6
lib/components/Modifier_Receiver.tscn
Normal file
6
lib/components/Modifier_Receiver.tscn
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/components/Modifier_Receiver.gd" type="Script" id=1]
|
||||
|
||||
[node name="Modifier_Receiver" type="Node2D"]
|
||||
script = ExtResource( 1 )
|
||||
13
lib/singleton_autoloads/LevelInfo.gd
Normal file
13
lib/singleton_autoloads/LevelInfo.gd
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
extends Node
|
||||
|
||||
|
||||
# Declare member variables here. Examples:
|
||||
# var a = 2
|
||||
# var b = "text"
|
||||
var player_start_position: Position2D
|
||||
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
#func _process(delta):
|
||||
# pass
|
||||
17
lib/singleton_autoloads/PlayerInfo.gd
Normal file
17
lib/singleton_autoloads/PlayerInfo.gd
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
extends Node
|
||||
|
||||
|
||||
# Declare member variables here. Examples:
|
||||
# var a = 2
|
||||
# var b = "text"
|
||||
var player_position: Vector2
|
||||
var player_health: int
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
#func _process(delta):
|
||||
# pass
|
||||
26
lib/singleton_autoloads/UIManager.gd
Normal file
26
lib/singleton_autoloads/UIManager.gd
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
extends Node
|
||||
|
||||
## This singleton sits in the middle allowing multiple game areas to call and
|
||||
# manipulate the UI
|
||||
|
||||
enum UI_PANES {OFF, HUD, DIALOG}
|
||||
|
||||
var dialog_text = 'foo'
|
||||
var dialog_portrait = preload("res://icon.png")
|
||||
var current_pane = UI_PANES.OFF
|
||||
|
||||
var debug_text :String
|
||||
|
||||
# Declare member variables here. Examples:
|
||||
# var a = 2
|
||||
# var b = "text"
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
#func _process(delta):
|
||||
# pass
|
||||
99
lib/templates/Actor/ActorTemplate.tscn
Normal file
99
lib/templates/Actor/ActorTemplate.tscn
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
[gd_scene load_steps=17 format=2]
|
||||
|
||||
[ext_resource path="res://src/components/Hurtbox_Component.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://src/state_machine_animated_actor.gd" type="Script" id=2]
|
||||
[ext_resource path="res://src/templates/Actor/states/fall.gd" type="Script" id=3]
|
||||
[ext_resource path="res://src/templates/Actor/states/idle.gd" type="Script" id=4]
|
||||
[ext_resource path="res://src/movement_component.gd" type="Script" id=5]
|
||||
[ext_resource path="res://src/templates/Actor/resources/Smiley.png" type="Texture" id=6]
|
||||
[ext_resource path="res://src/templates/Actor/states/move.gd" type="Script" id=7]
|
||||
[ext_resource path="res://src/actor.gd" type="Script" id=8]
|
||||
|
||||
[sub_resource type="AtlasTexture" id=76]
|
||||
atlas = ExtResource( 6 )
|
||||
region = Rect2( 0, 0, 32, 32 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=77]
|
||||
atlas = ExtResource( 6 )
|
||||
region = Rect2( 32, 0, 32, 32 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=78]
|
||||
atlas = ExtResource( 6 )
|
||||
region = Rect2( 64, 0, 32, 32 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=79]
|
||||
atlas = ExtResource( 6 )
|
||||
region = Rect2( 0, 32, 32, 32 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=80]
|
||||
atlas = ExtResource( 6 )
|
||||
region = Rect2( 32, 32, 32, 32 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=81]
|
||||
atlas = ExtResource( 6 )
|
||||
region = Rect2( 64, 32, 32, 32 )
|
||||
|
||||
[sub_resource type="SpriteFrames" id=75]
|
||||
animations = [ {
|
||||
"frames": [ SubResource( 76 ), SubResource( 77 ), SubResource( 78 ), SubResource( 79 ), SubResource( 80 ), SubResource( 81 ) ],
|
||||
"loop": true,
|
||||
"name": "default",
|
||||
"speed": 5.0
|
||||
} ]
|
||||
|
||||
[sub_resource type="CircleShape2D" id=82]
|
||||
|
||||
[node name="ActorTemplate" type="KinematicBody2D"]
|
||||
collision_layer = 2
|
||||
script = ExtResource( 8 )
|
||||
|
||||
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
|
||||
frames = SubResource( 75 )
|
||||
frame = 3
|
||||
playing = true
|
||||
flip_h = true
|
||||
__meta__ = {
|
||||
"_aseprite_wizard_config_": {
|
||||
"layer": "",
|
||||
"o_ex_p": "",
|
||||
"o_folder": "res://assets",
|
||||
"o_name": "",
|
||||
"only_visible": true,
|
||||
"op_exp": false,
|
||||
"slice": "",
|
||||
"source": "E:/Godot/Art/MegaMan.aseprite"
|
||||
}
|
||||
}
|
||||
|
||||
[node name="movement_component" type="Node" parent="."]
|
||||
script = ExtResource( 5 )
|
||||
|
||||
[node name="movement_state_machine" type="Node" parent="."]
|
||||
script = ExtResource( 2 )
|
||||
starting_state = NodePath("idle")
|
||||
|
||||
[node name="idle" type="Node" parent="movement_state_machine"]
|
||||
script = ExtResource( 4 )
|
||||
animation_sequence = [ "default" ]
|
||||
fall_node = NodePath("../fall")
|
||||
move_node = NodePath("../move")
|
||||
|
||||
[node name="fall" type="Node" parent="movement_state_machine"]
|
||||
script = ExtResource( 3 )
|
||||
animation_sequence = [ "default" ]
|
||||
idle_node = NodePath("../idle")
|
||||
|
||||
[node name="move" type="Node" parent="movement_state_machine"]
|
||||
script = ExtResource( 7 )
|
||||
animation_sequence = [ "default" ]
|
||||
fall_node = NodePath("../fall")
|
||||
idle_node = NodePath("../idle")
|
||||
|
||||
[node name="Hurtbox_Component" parent="." instance=ExtResource( 1 )]
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hurtbox_Component"]
|
||||
modulate = Color( 1, 0, 0, 1 )
|
||||
position = Vector2( -1, 1 )
|
||||
shape = SubResource( 82 )
|
||||
|
||||
[node name="SE_Player" type="AudioStreamPlayer" parent="."]
|
||||
BIN
lib/templates/Actor/resources/Smiley.png
Normal file
BIN
lib/templates/Actor/resources/Smiley.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 508 B |
35
lib/templates/Actor/resources/Smiley.png.import
Normal file
35
lib/templates/Actor/resources/Smiley.png.import
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/Smiley.png-8c81e651641e7afc57c144693e5c2423.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/templates/Actor/resources/Smiley.png"
|
||||
dest_files=[ "res://.import/Smiley.png-8c81e651641e7afc57c144693e5c2423.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=false
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
process/normal_map_invert_y=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
||||
19
lib/templates/Actor/states/fall.gd
Normal file
19
lib/templates/Actor/states/fall.gd
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
extends StateAnimatedActor
|
||||
|
||||
export (NodePath) var idle_node
|
||||
|
||||
onready var idle_state: State = get_node(idle_node)
|
||||
|
||||
func process_physics(delta: float) -> State:
|
||||
#parent.velocity.y += gravity * delta
|
||||
move_component.velocity.y += gravity * delta
|
||||
|
||||
move_component.velocity.x = move_component.desired_movement_vector.x * move_speed
|
||||
move_component.velocity = parent.move_and_slide(move_component.velocity, Vector2(0, -1))
|
||||
|
||||
if move_component.get_movement_direction() != 0.0:
|
||||
parent.transform.x.x = move_component.get_movement_direction()
|
||||
|
||||
if parent.is_on_floor():
|
||||
return idle_state
|
||||
return null
|
||||
30
lib/templates/Actor/states/idle.gd
Normal file
30
lib/templates/Actor/states/idle.gd
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
extends StateAnimatedActor
|
||||
|
||||
export (NodePath) var fall_node
|
||||
export (NodePath) var move_node
|
||||
|
||||
onready var fall_state: State = get_node(fall_node)
|
||||
onready var move_state: State = get_node(move_node)
|
||||
|
||||
func enter() -> void:
|
||||
.enter()
|
||||
# parent.set_hurtbox(true)
|
||||
move_component.velocity.x = 0
|
||||
if debug_state:
|
||||
print(owner.name, " Move Component: ", move_component.desired_movement_vector.x)
|
||||
|
||||
func process_physics(delta: float) -> State:
|
||||
|
||||
# parent.velocity.y += gravity * delta
|
||||
# #parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
|
||||
# parent.velocity.x = move_component.desired_movement_vector.x * move_speed
|
||||
# parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
|
||||
|
||||
move_actor_as_desired(delta)
|
||||
|
||||
if move_component.velocity.x != 0.0:
|
||||
return move_state
|
||||
|
||||
if !parent.is_on_floor():
|
||||
return fall_state
|
||||
return null
|
||||
21
lib/templates/Actor/states/move.gd
Normal file
21
lib/templates/Actor/states/move.gd
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
extends StateAnimatedActor
|
||||
|
||||
export (NodePath) var fall_node
|
||||
export (NodePath) var idle_node
|
||||
|
||||
onready var fall_state: State = get_node(fall_node)
|
||||
onready var idle_state: State = get_node(idle_node)
|
||||
|
||||
func process_physics(delta: float) -> State:
|
||||
|
||||
move_actor_as_desired(delta)
|
||||
|
||||
if move_component.velocity.x == 0.0:
|
||||
return idle_state
|
||||
|
||||
#Flip the character before tha actual move maybe.
|
||||
parent.transform.x.x = move_component.get_movement_direction()
|
||||
|
||||
if !parent.is_on_floor():
|
||||
return fall_state
|
||||
return null
|
||||
48
lib/templates/Interactable/Interactable_Component.gd
Normal file
48
lib/templates/Interactable/Interactable_Component.gd
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
class_name Interactable
|
||||
extends Area2D
|
||||
|
||||
## I'm not quite sure what to do with this yet but the idea is having an
|
||||
# area2d that detects not just a body entering a certain zone but triggering an
|
||||
# interract status. For a player this would probably be pressing a button.
|
||||
# the component can perhaps have a prompt of some sort to indicate what they're
|
||||
# supposed to do. Additionaly the interraction could perhaps trigger some
|
||||
# sort of animation when the action is performed.
|
||||
|
||||
# This may have to be implemented as a bi-directional mediator pattern where
|
||||
# the player node is given some sort of call back upon entering the region and
|
||||
# when it happens it fires off that call back.
|
||||
# This means that whatever entity that is supposed to interract with these
|
||||
# objects should also have a receiver function of some kind.
|
||||
|
||||
# Declare member variables here. Examples:
|
||||
# var a = 2
|
||||
# var b = "text"
|
||||
|
||||
export var type_name :String
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
pass # Replace with function body.
|
||||
|
||||
func trigger_interaction():
|
||||
# This is something that should maybe be extended for every differant interactible.
|
||||
# They could inherit from this base class and implement this function.
|
||||
# sprite.frame = 1
|
||||
pass
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
#func _process(delta):
|
||||
# pass
|
||||
|
||||
# When a body enters this area
|
||||
# We want to give that body (a player I assume) a callback or a reference to this
|
||||
# Node.
|
||||
func _on_Interactable_Component_body_entered(body):
|
||||
var colliding_node = body
|
||||
if colliding_node.has_node("Interactable_Receiver"):
|
||||
colliding_node.get_node("Interactable_Receiver").register_interactable(self)
|
||||
|
||||
func _on_Interactable_Component_body_exited(body):
|
||||
var colliding_node = body
|
||||
if colliding_node.has_node("Interactable_Receiver"):
|
||||
colliding_node.get_node("Interactable_Receiver").remove_interactable(self)
|
||||
9
lib/templates/Interactable/Interactable_Component.tscn
Normal file
9
lib/templates/Interactable/Interactable_Component.tscn
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/templates/Interactable/Interactable_Component.gd" type="Script" id=2]
|
||||
|
||||
[node name="Interactable_Template" type="Area2D"]
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[connection signal="body_entered" from="." to="." method="_on_Interactable_Component_body_entered"]
|
||||
[connection signal="body_exited" from="." to="." method="_on_Interactable_Component_body_exited"]
|
||||
48
lib/templates/Interactable/Interactable_Receiver.gd
Normal file
48
lib/templates/Interactable/Interactable_Receiver.gd
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
class_name Interactable_Receiver
|
||||
extends Node2D
|
||||
|
||||
# This may be stupid but we're going to have two kinds of callbacks here.
|
||||
# It's going to be up to the parent/actor/kinematicbody2d/whatever to know
|
||||
# what conditions have to be met before being able to call that interactible's
|
||||
# function.
|
||||
# This is a nice and generic interface that I might be able to use for
|
||||
# things like opening doors in a level, opening chests/flipping switches etc.
|
||||
|
||||
# This node can keep an array of various interactibles within a level
|
||||
# and provide several helper functions for managing them perhaps.
|
||||
|
||||
export(String) var interactable_parent_callback = ""
|
||||
|
||||
var call_function: FuncRef
|
||||
|
||||
var interactable_function_callables = []
|
||||
|
||||
# Declare member variables here. Examples:
|
||||
# var a = 2
|
||||
# var b = "text"
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
if interactable_parent_callback:
|
||||
call_function = funcref(owner, interactable_parent_callback)
|
||||
else:
|
||||
print("Warning: No interactable receiver function defined on ", owner.name)
|
||||
|
||||
# Switching to a new model that starts with Hitbox
|
||||
func register_interactable(sender):
|
||||
print("Interactable Registered " + sender.name)
|
||||
if call_function.is_valid():
|
||||
var should_register: bool = call_function.call_func(sender)
|
||||
if should_register:
|
||||
interactable_function_callables.append(sender)
|
||||
else:
|
||||
print("Interactable handled by Player")
|
||||
|
||||
func remove_interactable(sender):
|
||||
print("Interactable Removal " + sender.name)
|
||||
if interactable_function_callables.has(sender):
|
||||
var sender_index = interactable_function_callables.rfind(sender)
|
||||
if sender_index != -1:
|
||||
interactable_function_callables.remove(sender_index)
|
||||
|
||||
145
project.godot
Normal file
145
project.godot
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
; Engine configuration file.
|
||||
; It's best edited using the editor UI and not directly,
|
||||
; since the parameters that go here are not all obvious.
|
||||
;
|
||||
; Format:
|
||||
; [section] ; section goes between []
|
||||
; param=value ; assign values to parameters
|
||||
|
||||
config_version=4
|
||||
|
||||
_global_script_classes=[ {
|
||||
"base": "",
|
||||
"class": "GitAPI",
|
||||
"language": "NativeScript",
|
||||
"path": "res://addons/godot-git-plugin/git_api.gdns"
|
||||
} ]
|
||||
_global_script_class_icons={
|
||||
"GitAPI": ""
|
||||
}
|
||||
|
||||
[application]
|
||||
|
||||
config/name="Attempt 2"
|
||||
run/main_scene="res://Main.tscn"
|
||||
run/delta_sync_after_draw=true
|
||||
run/delta_smoothing=false
|
||||
boot_splash/show_image=false
|
||||
config/icon="res://icon.png"
|
||||
|
||||
[aseprite]
|
||||
|
||||
animation/layers/exclusion_pattern="_+"
|
||||
animation/layers/only_include_visible_layers_by_default=true
|
||||
|
||||
[autoload]
|
||||
|
||||
PlayerInfo="*res://src/singleton_autoloads/PlayerInfo.gd"
|
||||
UiManager="*res://src/singleton_autoloads/UIManager.gd"
|
||||
LevelInfo="*res://src/singleton_autoloads/LevelInfo.gd"
|
||||
|
||||
[debug]
|
||||
|
||||
shapes/collision/shape_color=Color( 1, 1, 1, 0.419608 )
|
||||
|
||||
[display]
|
||||
|
||||
window/size/width=320
|
||||
window/size/height=180
|
||||
window/size/resizable=false
|
||||
window/size/test_width=960
|
||||
window/size/test_height=540
|
||||
window/stretch/mode="viewport"
|
||||
window/stretch/aspect="keep"
|
||||
|
||||
[editor_plugins]
|
||||
|
||||
enabled=PoolStringArray( "res://addons/AsepriteWizard/plugin.cfg" )
|
||||
|
||||
[gui]
|
||||
|
||||
common/drop_mouse_on_gui_input_disabled=true
|
||||
|
||||
[importer_defaults]
|
||||
|
||||
texture={
|
||||
"flags/filter": false
|
||||
}
|
||||
|
||||
[input]
|
||||
|
||||
ui_accept={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777221,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777222,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_left_1={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_right_1={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
jump_1={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":0,"physical_scancode":32,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_left_2={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_right_2={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
jump_2={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":74,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
shoot_1={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":77,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":2,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
shoot_2={
|
||||
"deadzone": 0.5,
|
||||
"events": [ ]
|
||||
}
|
||||
dash_1={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":78,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":1,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[layer_names]
|
||||
|
||||
2d_physics/layer_1="World"
|
||||
2d_physics/layer_2="Player"
|
||||
2d_physics/layer_3="Enemies"
|
||||
2d_physics/layer_5="PlayerHurtbox"
|
||||
2d_physics/layer_6="EnemyHurtbox"
|
||||
2d_physics/layer_7="PlayerHitbox"
|
||||
2d_physics/layer_8="EnemyHitbox"
|
||||
2d_physics/layer_11="Climbable"
|
||||
common/enable_pause_aware_picking=true
|
||||
2d/default_gravity=600
|
||||
|
||||
[rendering]
|
||||
|
||||
quality/driver/driver_name="GLES2"
|
||||
vram_compression/import_etc=true
|
||||
Loading…
Reference in New Issue
Block a user