Compare commits

...

10 Commits

35 changed files with 629 additions and 179 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,11 +1,14 @@
class_name Actor
extends KinematicBody2D
var velocity = Vector2(0,0)
var direction = Vector2(-1,0)
#var velocity = Vector2(0,0)
#var direction = Vector2(-1,0)
export var sprite_facing_right: bool = true
export(String, "Player", "Enemy", "NPC") 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
@ -23,6 +26,38 @@ var sound_effects_dict: Dictionary
# 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 ):
@ -36,4 +71,14 @@ func play_sound_frame(animation: String, frame: int ):
if sound_effects_dict.has(sound_index):
sound_effect_player.stream = sound_effects_dict[sound_index]
sound_effect_player.play()
print("Playing SE: ", sound_index)
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)

View 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)

View 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 )

View 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)

View 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"]

View File

@ -0,0 +1,8 @@
extends Area2D
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

View File

@ -0,0 +1,8 @@
[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 )

View File

@ -0,0 +1,23 @@
extends Area2D
func set_hittbox(enabled: bool):
for child in get_children():
if child is CollisionShape2D:
child.set_deferred("disabled", !enabled)
# 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)

View File

@ -1,13 +1,8 @@
[gd_scene load_steps=2 format=2]
[sub_resource type="RectangleShape2D" id=148]
extents = Vector2( 11.5, 14.5 )
[ext_resource path="res://src/components/Hurtbox_Component.gd" type="Script" id=1]
[node name="Hurtbox_Component" type="Area2D"]
collision_layer = 16
collision_mask = 128
script = ExtResource( 1 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
self_modulate = Color( 1, 0, 0, 1 )
position = Vector2( 0, -4 )
shape = SubResource( 148 )
[connection signal="area_shape_entered" from="." to="." method="_on_Hurtbox_Component_area_shape_entered"]

View File

@ -68,7 +68,7 @@ func set_hitbox(enabled: bool):
func shoot_projectile():
var is_shooting = false
is_shooting = gun.shoot(direction.x)
is_shooting = gun.shoot(transform.x.x)
func _on_Hurtbox_body_entered(body):

View File

@ -131,6 +131,7 @@ script = ExtResource( 1 )
position = Vector2( 8, -8 )
frames = SubResource( 168 )
animation = "idle"
frame = 2
playing = true
flip_h = true
__meta__ = {

View File

@ -1,6 +1,10 @@
[gd_scene load_steps=22 format=2]
[gd_scene load_steps=29 format=2]
[ext_resource path="res://src/templates/Actor/ActorTemplate.tscn" type="PackedScene" id=1]
[ext_resource path="res://src/enemyC/enemyC_movement_component.gd" type="Script" id=2]
[ext_resource path="res://src/enemyC/attack.gd" type="Script" id=3]
[ext_resource path="res://src/components/Hitbox_Component.tscn" type="PackedScene" id=4]
[ext_resource path="res://src/components/GenericSender.tscn" type="PackedScene" id=5]
[sub_resource type="StreamTexture" id=1]
load_path = "res://.import/botEnemy.png-46efd539a38730ff15fb4ddb087329c6.stex"
@ -105,7 +109,17 @@ animations = [ {
"speed": 10.0
} ]
[sub_resource type="RectangleShape2D" id=22]
extents = Vector2( 10, 16 )
[sub_resource type="RectangleShape2D" id=23]
extents = Vector2( 9, 3.5 )
[sub_resource type="CapsuleShape2D" id=24]
height = 10.0
[node name="EnemyC" instance=ExtResource( 1 )]
actor_type = "Enemy"
[node name="AnimatedSprite" parent="." index="0"]
position = Vector2( 11, -7 )
@ -128,8 +142,59 @@ __meta__ = {
[node name="CollisionShape2D" parent="." index="1"]
position = Vector2( -0.5, -2 )
[node name="movement_component" parent="." index="2"]
script = ExtResource( 2 )
[node name="IdleTimeout" type="Timer" parent="movement_component" index="0"]
wait_time = 2.0
one_shot = true
autostart = true
[node name="idle" parent="movement_state_machine" index="0"]
animation_sequence = [ "idle" ]
[node name="fall" parent="movement_state_machine" index="1"]
animation_sequence = [ "idle" ]
[node name="attack" type="Node" parent="movement_state_machine" index="2"]
script = ExtResource( 3 )
debug_state = true
timeout_seconds = 2.0
animation_sequence = [ "attack" ]
fall_node = NodePath("../fall")
idle_node = NodePath("../idle")
[node name="move" parent="movement_state_machine" index="3"]
animation_sequence = [ "walk" ]
[node name="CollisionShape2D" parent="Hurtbox_Component" index="0"]
position = Vector2( -1, -2 )
shape = SubResource( 22 )
[node name="EdgeDetection" type="RayCast2D" parent="." index="6"]
modulate = Color( 0.054902, 1, 0, 1 )
show_behind_parent = true
position = Vector2( 15, 3 )
enabled = true
cast_to = Vector2( 0, 17 )
collide_with_areas = true
[node name="PlayerDetection" type="RayCast2D" parent="." index="7"]
enabled = true
cast_to = Vector2( 21, 0 )
collision_mask = 2
[node name="Hitbox_Component" parent="." index="8" instance=ExtResource( 4 )]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hitbox_Component" index="0"]
modulate = Color( 1, 0.596078, 0.121569, 1 )
position = Vector2( 18, -8.5 )
shape = SubResource( 23 )
disabled = true
[node name="GenericSender" parent="." index="9" instance=ExtResource( 5 )]
receiver_node_name = "GenericReceiver"
[node name="CollisionShape2D" type="CollisionShape2D" parent="GenericSender" index="0"]
position = Vector2( 48, 0 )
shape = SubResource( 24 )

42
src/enemyC/attack.gd Normal file
View File

@ -0,0 +1,42 @@
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 enter() -> void:
.enter()
# parent.set_hurtbox(true)
if state_timeout:
state_timeout.start()
move_component.velocity.x = 0
if debug_state:
print(owner.name, " Move Component: ", move_component.desired_movement_vector.x)
func process_frame(_delta: float) -> State:
if move_component.wants_shoot() == false and state_timeout.time_left == 0:
return idle_state
# if animations.frame > 1:
# parent.set_hitbox(true)
# else:
# parent.set_hitbox(false)
return null
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 !parent.is_on_floor():
return fall_state
return null

View File

@ -0,0 +1,45 @@
extends MovementComponent
onready var idle_timeout = $IdleTimeout
onready var edge_detector:RayCast2D = $"../EdgeDetection"
onready var player_detector:RayCast2D = $"../PlayerDetection"
var flip_flop = false
var wants_to_attack = false
func process_physics(delta):
if current_movement_state == "move" and edge_detector.is_colliding() == false:
#print(owner.name, "uh oh gonna fall!")
stop()
return
if player_detector.is_colliding():
#print(owner.name, " wants to attack")
stop()
wants_to_attack = true
if attack_function.is_valid():
attack_function.call_func()
return
else:
wants_to_attack = false
func process(delta):
if current_movement_state == "idle" and idle_timeout.time_left == 0:
if debug_component:
print ("Time to move!")
if flip_flop:
flip_flop = false
go_right()
idle_timeout.start()
else:
flip_flop = true
go_left()
idle_timeout.start()
if current_movement_state == "move" and idle_timeout.time_left == 0:
if debug_component:
print("Time to stop.")
idle_timeout.start()
stop()
return
func wants_shoot() -> bool:
return wants_to_attack

View File

@ -3,30 +3,23 @@ extends "res://src/templates/Actor/states/idle.gd"
var debugTimeTracker := 0.0
export (NodePath) var jump_node
export (NodePath) var move_node
export (NodePath) var fire_node
export (NodePath) var wander_node
export (NodePath) var attack_node
onready var jump_state: State = get_node(jump_node)
onready var move_state: State = get_node(move_node)
onready var fire_state: State = get_node(fire_node)
onready var wander_state: State = get_node(wander_node)
onready var attack_state: State = get_node(attack_node)
func enter() -> void:
.enter()
parent.set_hurtbox(true)
parent.velocity.x = 0
state_timeout.start()
func process_input(_event: InputEvent) -> State:
# if get_jump() and parent.is_on_floor():
func process_frame(_delta: float) -> State:# if get_jump() and parent.is_on_floor():
# return jump_state
if move_component.wants_jump() and parent.is_on_floor():
return jump_state
# if move_component.get_movement_direction() != 0.0:
# return move_state
if move_component.wants_shoot():
return fire_state
if state_timeout.time_left == 0:
return wander_state
# move_component.wants_jump()
move_component.get_movement_direction()
@ -46,8 +39,6 @@ func process_physics(delta: float) -> State:
parent.velocity.x = move_component.desired_movement_vector.x * move_speed
parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
if parent.velocity.x != 0.0:
return move_state
if !parent.is_on_floor():
return fall_state

View File

@ -0,0 +1,58 @@
extends StateAnimatedActor
export (NodePath) var idle_node
export (NodePath) var attack_node
export (NodePath) var fall_node
onready var idle_state: State = get_node(idle_node)
onready var attack_state: State = get_node(attack_node)
onready var fall_state: State = get_node(fall_node)
var flip_flop = false
func enter(state_modifiers: Array = []) -> void:
.enter()
parent.set_hurtbox(true)
state_timeout.start()
if flip_flop:
flip_flop = false
move_component.desired_movement_vector.x = 1.0
else:
flip_flop = true
move_component.desired_movement_vector.x = -1.0
func process_frame(_delta: float) -> State:
# if parent.player_detection.is_colliding():
# return attack_state
if state_timeout.time_left == 0:
return idle_state
# if move_component.wants_jump() and parent.is_on_floor():
# return jump_state
#
# move_component.get_movement_direction()
return null
func process_physics(delta: float) -> State:
parent.velocity.y += gravity * delta
parent.velocity.x = move_component.desired_movement_vector.x * move_speed
parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
if parent.velocity.x == 0.0:
return idle_state
else:
if parent.velocity.x > 0:
parent.direction.x = 1
elif parent.velocity.x < 0:
parent.direction.x = -1
parent.transform.x.x = parent.direction.x
if !parent.is_on_floor():
return fall_state
return null

View File

@ -1,18 +1,64 @@
class_name MovementComponent
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 desired_movement_vector: Vector2 = Vector2(0,0)
var current_movement_state:String
# 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)
#Can't use floats here, switched to constants.
#enum directions {UP = -1, DOWN = 1, LEFT, RIGHT}
var attack_function: FuncRef
const UP = -1.0
const DOWN = 1.0
const LEFT = -1.0
const RIGHT = 1.0
func process_physics(delta):
pass
func process(delta):
pass
func process_input(event: InputEvent):
pass
# 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 0.0
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 jump
# Return a boolean indicating if the character wants to attack
func wants_shoot() -> bool:
return false

View File

@ -9,49 +9,6 @@ onready var gun = $Gun
#var sound_effects = preload("res://src/playerC/resources/sound_effects.tres")
func _ready() -> void:
movement_state_machine.init_animated_actor(self, movement_animations, movement_component)
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:
movement_state_machine.process_input(event)
func _physics_process(delta: float) -> void:
movement_state_machine.process_physics(delta)
# #TODO: So much hack
# if direction.x != 0:
# gun.set_scale( Vector2(direction.x,1))
# Commented out to try parent transforms instead
# if direction.x < 0:
# var t = Transform2D()
# # Translation
# t.origin = Vector2(gun.offset_position.x * -1, gun.offset_position.y)
# gun.transform = t
# elif direction.x > 0:
# var t = Transform2D()
# # Translation
# t.origin = Vector2(gun.offset_position.x, gun.offset_position.y)
# gun.transform = t
# Attempting a Kinematic2D level scale for flip operations instead.
#self.transform
#self.scale.x = -1
func _process(delta: float) -> void:
movement_state_machine.process_frame(delta)
PlayerInfo.player_position = global_position
play_sound_frame(movement_animations.animation , movement_animations.frame)
##TODO: I don't like player class having do do this.
@ -60,23 +17,25 @@ func _process(delta: float) -> void:
# if movement_animations.frames.get_animation_loop(movement_animations.animation) == false:
# movement_state_machine.current_state.animation_index += 1
func _on_Hurtbox_area_entered(area):
print("Ouch.",area)
movement_state_machine.change_state($Controllers/state_machine/hurt)
func _on_Hurtbox_area_entered():
#print("Ouch.",area)
movement_state_machine.change_state($movement_state_machine/hurt)
func set_hurtbox(enabled: bool):
#player_hurtbox.disabled = enabled #nope
player_hurtbox.set_deferred("disabled", !enabled) #WTF Apparently this is how to do it
#$Hurtbox.monitoring = enabled #nope
#$Hurtbox.set_deferred("monitoring", enabled) #works
#$Hurtbox.monitoring = false #nope
#$Hurtbox.set_monitoring(enabled) # Nope
pass
## 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 shoot_projectile():
var is_shooting = false
is_shooting = gun.shoot(direction.x)
print("Direction: ", transform.x.x)
is_shooting = gun.shoot(int(transform.x.x))
#func play_sound():
# sound_effects.stream = "res://assets/Sounds/crappy pew.wav"
func gotcha():
print("oh! You got me.")
func heylookatme(sender):
print("does it work!")

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=90 format=2]
[gd_scene load_steps=92 format=2]
[ext_resource path="res://src/playerC/Player-KinematicBody2D.gd" type="Script" id=1]
[ext_resource path="res://src/playerC/states/idle.gd" type="Script" id=2]
@ -14,6 +14,7 @@
[ext_resource path="res://src/components/Hurtbox_Component.tscn" type="PackedScene" id=12]
[ext_resource path="res://src/state_modifier.gd" type="Script" id=13]
[ext_resource path="res://src/playerC/sm.gd" type="Script" id=14]
[ext_resource path="res://src/components/GenericReceiver.tscn" type="PackedScene" id=15]
[sub_resource type="Resource" id=148]
script = ExtResource( 11 )
@ -414,9 +415,13 @@ animations = [ {
[sub_resource type="RectangleShape2D" id=74]
extents = Vector2( 14, 18.5 )
[sub_resource type="RectangleShape2D" id=149]
extents = Vector2( 10.5, 16.5 )
[node name="Player" type="KinematicBody2D"]
collision_layer = 2
script = ExtResource( 1 )
actor_type = "Player"
SoundEffects = [ SubResource( 148 ) ]
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
@ -505,6 +510,14 @@ timeout_seconds = 2.0
animation_suffix = true
[node name="Hurtbox_Component" parent="." instance=ExtResource( 12 )]
collision_layer = 32768
collision_mask = 128
monitoring = false
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hurtbox_Component"]
modulate = Color( 1, 0, 0, 1 )
position = Vector2( 0.5, -3.5 )
shape = SubResource( 149 )
[node name="Gun" type="Position2D" parent="."]
physics_interpolation_mode = 1
@ -521,3 +534,6 @@ width = 2.0
default_color = Color( 1, 0.607843, 0, 1 )
[node name="SE_Player" type="AudioStreamPlayer" parent="."]
[node name="GenericReceiver" parent="." instance=ExtResource( 15 )]
body_entered_function = "heylookatme"

View File

@ -16,20 +16,16 @@ func process_input(_event: InputEvent) -> State:
return null
func process_physics(delta: float) -> State:
parent.velocity.y += gravity * delta
move_component.velocity.y += gravity * delta
parent.velocity.x = move_component.desired_movement_vector.x * move_speed
parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
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 parent.velocity.x != 0.0:
# parent.direction.x = parent.velocity.x
if parent.velocity.x > 0:
parent.direction.x = 1
elif parent.velocity.x < 0:
parent.direction.x = -1
parent.transform.x.x = parent.direction.x
if move_component.get_movement_direction() != 0.0:
parent.transform.x.x = move_component.get_movement_direction()
# if move_component.flipped_sprite == false:
# #parent.scale.x = parent.direction.x * -1
# parent.transform.x.x = parent.direction.x * -1 # -1
@ -38,7 +34,7 @@ func process_physics(delta: float) -> State:
# parent.transform.x.x = parent.direction.x # 1
if parent.is_on_floor():
if parent.velocity.x == 0:
if move_component.velocity.x != 0:
return move_state
return idle_state
return null

View File

@ -47,12 +47,12 @@ func process_physics(delta: float) -> State:
parent.shoot_projectile()
can_fire = false
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_component.velocity.y += gravity * delta
move_component.velocity = parent.move_and_slide(move_component.velocity, Vector2(0, -1))
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 parent.velocity.x != 0.0:
if move_component.velocity.x != 0.0:
return move_state
if !parent.is_on_floor():

View File

@ -6,8 +6,8 @@ onready var idle_state: State = get_node(idle_node)
func enter() -> void:
.enter()
parent.velocity.x = 0
parent.set_hurtbox(false)
move_component.velocity.x = 0
#parent.set_hurtbox(false)
#TODO: Error check if timer was actually instanced
state_timeout.start()
@ -25,12 +25,13 @@ func process_frame(delta: float) -> State:
func process_physics(delta: float) -> State:
parent.velocity.y += gravity * delta
move_component.velocity.y += gravity * delta
#parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
if (parent.direction.x > 0):
parent.velocity.x = 1 * move_speed
else:
parent.velocity.x = -1 * move_speed
parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
move_component.velocity = parent.transform.x * move_speed
# if (parent.direction.x > 0):
# parent.velocity.x = 1 * move_speed
# else:
# parent.velocity.x = -1 * move_speed
move_component.velocity = parent.move_and_slide(move_component.velocity, Vector2(0, -1))
return null

View File

@ -15,7 +15,7 @@ onready var fire_state: State = get_node(fire_node)
func enter() -> void:
.enter()
parent.set_hurtbox(true)
parent.velocity.x = 0
move_component.velocity.x = 0
func process_input(_event: InputEvent) -> State:
# if get_jump() and parent.is_on_floor():
@ -37,17 +37,18 @@ func process_input(_event: InputEvent) -> State:
return null
func process_physics(delta: float) -> State:
debugTimeTracker += delta
if debugTimeTracker > 2:
debugTimeTracker = 0.0
print("DEBUG TRANSFORM:", parent.transform)
if debug_state:
debugTimeTracker += delta
if debugTimeTracker > 2:
debugTimeTracker = 0.0
print(owner.name, " DEBUG TRANSFORM:", parent.transform)
parent.velocity.y += gravity * delta
move_component.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_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 parent.velocity.x != 0.0:
if move_component.velocity.x != 0.0:
return move_state
if !parent.is_on_floor():

View File

@ -13,7 +13,7 @@ export var jump_force: float = 900.0
func enter() -> void:
.enter()
parent.velocity.y = -jump_force
move_component.velocity.y = -jump_force
func process_input(_event: InputEvent) -> State:
move_component.get_movement_direction()
@ -21,19 +21,17 @@ func process_input(_event: InputEvent) -> State:
func process_physics(delta: float) -> State:
parent.velocity.y += gravity * delta
move_component.velocity.y += gravity * delta
if parent.velocity.y > 0:
if move_component.velocity.y > 0:
return fall_state
parent.velocity.x = move_component.desired_movement_vector.x * move_speed
parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
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.velocity.x > 0:
parent.direction.x = 1
elif parent.velocity.x < 0:
parent.direction.x = -1
parent.transform.x.x = parent.direction.x
# if move_component.flipped_sprite == false:
# #parent.scale.x = parent.direction.x * -1
# parent.transform.x.x = parent.direction.x * -1 # -1
@ -42,7 +40,7 @@ func process_physics(delta: float) -> State:
# parent.transform.x.x = parent.direction.x # 1
if parent.is_on_floor():
if parent.velocity.x == 0:
if move_component.velocity.x == 0:
return move_state
return idle_state

View File

@ -24,12 +24,13 @@ func process_input(_event: InputEvent) -> State:
func process_physics(delta: float) -> State:
# if move_component.wants_jump() and parent.is_on_floor():
# return jump_state
debugTimeTracker += delta
if debugTimeTracker > 2:
debugTimeTracker = 0.0
print("DEBUG TRANSFORM:", parent.transform)
if debug_state:
debugTimeTracker += delta
if debugTimeTracker > 2:
debugTimeTracker = 0.0
print("DEBUG TRANSFORM:", parent.transform)
parent.velocity.y += gravity * delta
move_component.velocity.y += gravity * delta
# var movement = move_component.get_movement_direction() * move_speed
#
@ -40,18 +41,15 @@ func process_physics(delta: float) -> State:
# parent.velocity.x = movement
# 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_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 parent.velocity.x == 0.0:
if move_component.velocity.x == 0.0:
return idle_state
else:
if parent.velocity.x > 0:
parent.direction.x = 1
elif parent.velocity.x < 0:
parent.direction.x = -1
parent.transform.x.x = parent.direction.x
if move_component.get_movement_direction() != 0.0:
parent.transform.x.x = move_component.get_movement_direction()
# if move_component.flipped_sprite == true:
# animations.flip_h = parent.direction.x > 0
# else:

View File

@ -1,8 +1,14 @@
class_name State
extends Node
export var debug_state: bool = false
export var timeout_seconds: float = 0.0
signal state_entered()
signal state_exited()
signal frame_reached(state_name, animation_name, frame_number)
export(Dictionary) var emitter_frame_subscriptions
# Declare member variables here. Examples:
var modifier_stack_ref: Array # Well this didn't work
var state_timeout: Timer

View File

@ -40,6 +40,7 @@ var parent: KinematicBody2D
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()
@ -53,7 +54,10 @@ func enter() -> void:
# animations.connect("animation_finished", self, "_on_AnimatedSprite_animation_finished")
# Reset animation suffix in case there isn't one
animation_suffix = ''
print(parent.name, " entering State: ", self.name)
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
if modifier_stack_ref.empty() == false:
if modifier_stack_ref[-1].animation_name != '':
@ -75,8 +79,9 @@ func enter() -> void:
return
func exit() -> void:
emit_signal("state_exited")
# animations.disconnect("animation_finished", self, "_on_AnimatedSprite_animation_finished")
pass
return
func process_input(_event: InputEvent) -> State:
return null
@ -89,11 +94,22 @@ func process_frame(_delta: float) -> State:
animations.play(animation_sequence[animation_index] + animation_suffix)
print("An animation sequence: ", animations.animation , animation_index)
current_animation_sequence = animation_index
if emitter_frame_subscriptions.has(animations.frame):
if emitter_frame_subscriptions[animations.frame] == animations.animation:
emit_signal("frame_reached", self.name, animations.animation, animations.frame)
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):
move_component.velocity.y += gravity * delta
#parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
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))

View File

@ -1,6 +1,7 @@
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
@ -10,8 +11,11 @@ var state_modifiers: Array
func init() -> void:
for child in get_children():
if child is State:
print("Initializing State Node: ", child.name)
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))
@ -23,7 +27,7 @@ func change_state(new_state: State) -> void:
current_state = new_state
current_state.enter()
if(state_modifiers.size() > 0):
if(state_modifiers.size() > 0 and debug_state_machine):
print("Active Modifiers:")
for mods in state_modifiers:
print(mods.name)

View File

@ -6,11 +6,14 @@ func init_animated_actor(parent: KinematicBody2D, animations: AnimatedSprite, mo
animations.connect("animation_finished", self, "_on_AnimatedSprite_animation_finished")
for child in get_children():
if child is StateAnimatedActor:
print("Initializing State Node for ", parent.name, ": ", child.name)
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))
@ -23,7 +26,8 @@ func process_frame(delta: float) -> void:
# states to be that complex.
if state_modifiers.empty() == false:
if state_modifiers[-1].state_timeout.time_left == 0:
print("Pop State Modifier: ", state_modifiers[-1].name)
if debug_state_machine:
print("Pop State Modifier: ", state_modifiers[-1].name)
state_modifiers.pop_back()
# Reset animation suffix
current_state.animation_suffix = ''

View File

@ -44,6 +44,7 @@ func _physics_process(delta: float) -> void:
#self.scale.x = -1
func _process(delta: float) -> void:
movement_component.process(delta)
movement_state_machine.process_frame(delta)
play_sound_frame(movement_animations.animation , movement_animations.frame)
@ -54,11 +55,5 @@ func _process(delta: float) -> void:
# if movement_animations.frames.get_animation_loop(movement_animations.animation) == false:
# movement_state_machine.current_state.animation_index += 1
func _on_Hurtbox_area_entered(area):
print("Ouch.",area)
movement_state_machine.change_state($Controllers/state_machine/hurt)
func set_hurtbox(enabled: bool):
actor_hurtbox.set_deferred("disabled", !enabled) #WTF Apparently this is how to do it

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=16 format=2]
[gd_scene load_steps=18 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]
@ -6,7 +6,8 @@
[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/ActorTemplate.gd" type="Script" id=12]
[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 )
@ -43,13 +44,15 @@ animations = [ {
[sub_resource type="RectangleShape2D" id=74]
extents = Vector2( 14, 18.5 )
[sub_resource type="CircleShape2D" id=82]
[node name="ActorTemplate" type="KinematicBody2D"]
collision_layer = 2
script = ExtResource( 12 )
script = ExtResource( 8 )
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
frames = SubResource( 75 )
frame = 2
frame = 4
playing = true
flip_h = true
__meta__ = {
@ -80,12 +83,24 @@ starting_state = NodePath("idle")
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="."]

View File

@ -5,17 +5,14 @@ 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
#parent.velocity.y += gravity * delta
move_component.velocity.y += gravity * delta
parent.velocity.x = move_component.desired_movement_vector.x * move_speed
parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
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 parent.velocity.x > 0:
parent.direction.x = 1
elif parent.velocity.x < 0:
parent.direction.x = -1
parent.transform.x.x = parent.direction.x
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

View File

@ -1,21 +1,29 @@
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)
parent.velocity.x = 0
print("Move Component: ", move_component.desired_movement_vector.x)
# 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))
# 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

View 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