Compare commits

..

11 Commits

21 changed files with 655 additions and 415 deletions

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=11 format=2]
[gd_scene load_steps=10 format=2]
[ext_resource path="res://src/Levels/Level.tscn" type="PackedScene" id=1]
[ext_resource path="res://src/CameraControl-Position2D.gd" type="Script" id=5]
@ -10,23 +10,22 @@
[ext_resource path="res://icon.png" type="Texture" id=13]
[ext_resource path="res://src/playerD/Player.tscn" type="PackedScene" id=14]
[sub_resource type="SegmentShape2D" id=13]
a = Vector2( -1, -68 )
b = Vector2( -1, 349 )
[node name="Main" type="Node2D"]
[node name="Level" parent="." instance=ExtResource( 1 )]
__meta__ = {
"_edit_lock_": true
}
[node name="Player" parent="." instance=ExtResource( 14 )]
position = Vector2( 93, 54 )
position = Vector2( 859, 236 )
[node name="CameraControl" type="Position2D" parent="."]
pause_mode = 2
process_priority = 1
script = ExtResource( 5 )
__meta__ = {
"_edit_group_": true,
"_edit_lock_": true
"_edit_group_": true
}
[node name="Line2D" type="Line2D" parent="CameraControl"]
@ -41,7 +40,29 @@ __meta__ = {
process_priority = 1
anchor_mode = 0
current = true
smoothing_speed = 30.0
smoothing_speed = 3.0
__meta__ = {
"_edit_lock_": true
}
[node name="Up" type="RayCast2D" parent="CameraControl"]
position = Vector2( 160, 90 )
enabled = true
cast_to = Vector2( 0, -90 )
collision_mask = 256
collide_with_areas = true
collide_with_bodies = false
__meta__ = {
"_edit_lock_": true
}
[node name="Down" type="RayCast2D" parent="CameraControl"]
position = Vector2( 160, 90 )
enabled = true
cast_to = Vector2( 0, 90 )
collision_mask = 256
collide_with_areas = true
collide_with_bodies = false
__meta__ = {
"_edit_lock_": true
}
@ -68,26 +89,8 @@ __meta__ = {
"_edit_lock_": true
}
[node name="CameraBoundaries" type="Area2D" parent="."]
collision_layer = 256
collision_mask = 0
__meta__ = {
"_edit_lock_": true
}
[node name="CollisionShape2D" type="CollisionShape2D" parent="CameraBoundaries"]
position = Vector2( 0, 66 )
shape = SubResource( 13 )
__meta__ = {
"_edit_lock_": true
}
[node name="CollisionShape2D2" type="CollisionShape2D" parent="CameraBoundaries"]
position = Vector2( 1281, 68 )
shape = SubResource( 13 )
__meta__ = {
"_edit_lock_": true
}
[node name="Timer" type="Timer" parent="CameraControl"]
wait_time = 1.5
[node name="UI_Layer" type="CanvasLayer" parent="."]
pause_mode = 2

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 119 KiB

View File

@ -39,6 +39,11 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://src/templates/Interactable/Interactable_Receiver.gd"
}, {
"base": "Node2D",
"class": "Level",
"language": "GDScript",
"path": "res://src/Level.gd"
}, {
"base": "Node",
"class": "MovementComponent",
"language": "GDScript",
@ -64,7 +69,7 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://src/state_machine_animated_actor.gd"
}, {
"base": "Node",
"base": "Reference",
"class": "StateModifier",
"language": "GDScript",
"path": "res://src/state_modifier.gd"
@ -81,6 +86,7 @@ _global_script_class_icons={
"HealthPickup": "",
"Interactable": "",
"Interactable_Receiver": "",
"Level": "",
"MovementComponent": "",
"State": "",
"StateAnimatedActor": "",
@ -105,6 +111,7 @@ animation/layers/only_include_visible_layers_by_default=true
PlayerInfo="*res://src/singleton_autoloads/PlayerInfo.gd"
UiManager="*res://src/singleton_autoloads/UIManager.gd"
LevelInfo="*res://src/singleton_autoloads/LevelInfo.gd"
[debug]

View File

@ -4,30 +4,36 @@ export(String) var LINE_COLOR_HEX = '#FFEB3B'
var grid_position = Vector2()
var grid_size = Vector2()
var t = 0.0
onready var parent = PlayerInfo
onready var timer: Timer = $Timer
#onready var parent = $Player
##TODO: Quick and dirty because we need to pause these
onready var player_node :KinematicBody2D = $"../Player"
#onready var level_node = $"../Level"
func _ready():
# If you drag the camera from the OffsetPivot node,
# its position will not be (0, 0)
#$Camera2D.global_position = Vector2(160,90) # when doing grid snapping
#$Left.position = Vector2(160,90)
$Camera2D.position = Vector2(0,-4)
#$Camera2D.position = Vector2(0,-4)
#grid_size = OS.get_screen_size()
grid_size = get_node("/root").size
#grid_size = get_node("/root").get_visible_rect().size
print(grid_size)
set_as_toplevel(true)
update_grid_position()
#update_grid_position()
##TODO: Can't seem to get first load grid snap not to happen.
grid_position = calculate_grid_position()
jump_to_grid_position()
print("Camera Set: ",grid_position, position)
print("Ray Left: ", $Left.global_position, $Left.cast_to)
func _physics_process(delta):
t += delta * 0.4
#print(parent.position.x)
update_grid_position()
#draw_line( Vector2(0, -half_line_length), Vector2(0, half_line_length), color, 3.0)
@ -44,13 +50,62 @@ func update_grid_position():
# print("Oh God! No!")
# if grid_position == new_grid_position:
# return
grid_position = new_grid_position
jump_to_grid_position()
# if the y value has changed we can flip transition the camera
##TODO: this logic is working but I don't like it.
if grid_position.y != new_grid_position.y:
if !$Up.is_colliding() and grid_position.y > new_grid_position.y:
get_tree().paused = true
grid_position = new_grid_position
timer.start()
$Camera2D.smoothing_enabled = true
jump_to_grid_position()
#wait for stability.
player_node.global_translate(Vector2(0,-10))
var a_tenth_of_the_time = int((timer.time_left / timer.wait_time) * 10)
while a_tenth_of_the_time != 0:
#print(a_tenth_of_the_time)
var time_ticks = int((timer.time_left / timer.wait_time) * 10)
if time_ticks != a_tenth_of_the_time:
print("Shifting Player Downward :", a_tenth_of_the_time)
a_tenth_of_the_time = time_ticks
player_node.global_translate(Vector2(0,-5))
# WEIRD!? You have to add this at the end of a while loop or it gets stuck.
yield(get_tree(), "idle_frame")
#yield(timer, "timeout")
$Camera2D.smoothing_enabled = false
get_tree().paused = false
elif !$Down.is_colliding() and grid_position.y < new_grid_position.y:
get_tree().paused = true
grid_position = new_grid_position
timer.start()
$Camera2D.smoothing_enabled = true
jump_to_grid_position()
# FINALLY Got one that works. I tried all sorts of stuff to move this thing!?
var a_tenth_of_the_time = int((timer.time_left / timer.wait_time) * 10)
while a_tenth_of_the_time != 0:
#print(a_tenth_of_the_time)
var time_ticks = int((timer.time_left / timer.wait_time) * 10)
if time_ticks != a_tenth_of_the_time:
print("Shifting Player Downward :", a_tenth_of_the_time)
a_tenth_of_the_time = time_ticks
player_node.global_translate(Vector2(0,2))
# WEIRD!? You have to add this at the end of a while loop or it gets stuck.
yield(get_tree(), "idle_frame")
#yield(timer, "timeout")
$Camera2D.smoothing_enabled = false
get_tree().paused = false
else:
# Only allow horizontal camera moving
grid_position.x = new_grid_position.x
jump_to_grid_position()
else:
grid_position = new_grid_position
jump_to_grid_position()
#$Left.position = Vector2(grid_position * grid_size)
#print("Ray Left: ", $Left.global_position, $Left.cast_to)
func calculate_grid_position():
func calculate_grid_position() -> Vector2:
# this needs to heavily round off the parents position
var x_offset = floor(parent.player_position.x / grid_size.x)
var y_offset = floor(parent.player_position.y / grid_size.y)
@ -84,6 +139,16 @@ func jump_to_grid_position():
$Camera2D.limit_right = $Right.get_collision_point().x
else:
$Camera2D.limit_right = 10000000
if $Up.is_colliding():
$Camera2D.limit_top = $Up.get_collision_point().y
else:
$Camera2D.limit_top = -10000000
if $Down.is_colliding():
$Camera2D.limit_bottom = $Down.get_collision_point().y
else:
$Camera2D.limit_bottom = 10000000
position = Vector2( x_pos ,grid_position.y * grid_size.y)
#$Camera2D.force_update_scroll()
#position = Vector2( grid_position * grid_size)

19
src/Level.gd Normal file
View File

@ -0,0 +1,19 @@
class_name Level
extends Node2D
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
onready var player_start = $PlayerStart
# Called when the node enters the scene tree for the first time.
func _ready():
LevelInfo.player_start_position = player_start
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=9 format=2]
[gd_scene load_steps=14 format=2]
[ext_resource path="res://src/templates/Actor/ActorTemplate.tscn" type="PackedScene" id=1]
[ext_resource path="res://assets/Tiles/Assets/Demo TileSet.tres" type="TileSet" id=2]
@ -8,8 +8,51 @@
[ext_resource path="res://assets/Music/platformer_level03_loop.ogg" type="AudioStream" id=6]
[ext_resource path="res://src/enemyC/EnemyC.tscn" type="PackedScene" id=7]
[ext_resource path="res://src/Interactables/Door.tscn" type="PackedScene" id=8]
[ext_resource path="res://src/components/Hitbox_Component.tscn" type="PackedScene" id=9]
[ext_resource path="res://src/Level.gd" type="Script" id=10]
[sub_resource type="SegmentShape2D" id=1]
b = Vector2( 1500, 0 )
[sub_resource type="SegmentShape2D" id=2]
a = Vector2( -1, -68 )
b = Vector2( -1, 349 )
[sub_resource type="RectangleShape2D" id=3]
extents = Vector2( 50, 2 )
[node name="Level" type="Node2D"]
script = ExtResource( 10 )
[node name="PlayerStart" type="Position2D" parent="."]
position = Vector2( 86, 97 )
[node name="CameraBoundaries" type="Area2D" parent="."]
collision_layer = 256
collision_mask = 0
__meta__ = {
"_edit_lock_": true
}
[node name="CollisionShape2D3" type="CollisionShape2D" parent="CameraBoundaries"]
modulate = Color( 0.431373, 0.431373, 1, 1 )
shape = SubResource( 1 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="CameraBoundaries"]
modulate = Color( 0.431373, 0.431373, 1, 1 )
position = Vector2( 0, 66 )
shape = SubResource( 2 )
__meta__ = {
"_edit_lock_": true
}
[node name="CollisionShape2D2" type="CollisionShape2D" parent="CameraBoundaries"]
modulate = Color( 0.431373, 0.431373, 1, 1 )
position = Vector2( 1281, 68 )
shape = SubResource( 2 )
__meta__ = {
"_edit_lock_": true
}
[node name="ParallaxBackground" type="ParallaxBackground" parent="."]
scroll_base_scale = Vector2( 0.4, 1 )
@ -63,10 +106,7 @@ __meta__ = {
}
[node name="EnemyC2" parent="." instance=ExtResource( 7 )]
position = Vector2( 492, 27 )
__meta__ = {
"_edit_lock_": true
}
position = Vector2( 494, 39 )
[node name="ActorTemplate" parent="." instance=ExtResource( 1 )]
position = Vector2( 262, 44 )
@ -86,3 +126,14 @@ position = Vector2( 187, 144 )
[node name="Door" parent="." instance=ExtResource( 8 )]
position = Vector2( 866, 120 )
[node name="Hitbox_Component" parent="." instance=ExtResource( 9 )]
position = Vector2( 766, 334 )
damage_amount = 50
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hitbox_Component"]
modulate = Color( 1, 0, 0, 1 )
shape = SubResource( 3 )
__meta__ = {
"_edit_lock_": true
}

View File

@ -9,6 +9,7 @@ onready var gun = $Gun
func _ready() -> void:
PlayerInfo.player_health = $Health_Component.health
global_position = LevelInfo.player_start_position.transform.origin
movement_component.player_number = player_number
@ -21,6 +22,8 @@ func hit_Receiver(damage):
if $Health_Component.health > 0:
movement_state_machine.change_state($movement_state_machine/hurt)
PlayerInfo.player_health = $Health_Component.health
if PlayerInfo.player_health <= 0:
return
yield( get_tree().create_timer(2 + $movement_state_machine/hurt.timeout_seconds), "timeout")
$Hurtbox_Component.set_hurtbox(true)

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=127 format=2]
[gd_scene load_steps=126 format=2]
[ext_resource path="res://src/templates/Actor/ActorTemplate.tscn" type="PackedScene" id=1]
[ext_resource path="res://src/playerD/movement_component.gd" type="Script" id=2]
@ -8,13 +8,12 @@
[ext_resource path="res://src/playerD/states/fall.gd" type="Script" id=6]
[ext_resource path="res://src/components/Health_Component.tscn" type="PackedScene" id=7]
[ext_resource path="res://src/playerD/states/jump.gd" type="Script" id=8]
[ext_resource path="res://src/state_modifier.gd" type="Script" id=9]
[ext_resource path="res://src/playerD/states/attack.gd" type="Script" id=10]
[ext_resource path="res://src/playerD/states/dash.gd" type="Script" id=11]
[ext_resource path="res://src/playerD/states/hurt.gd" type="Script" id=12]
[ext_resource path="res://src/Gun.gd" type="Script" id=13]
[ext_resource path="res://src/playerD/states/roll.gd" type="Script" id=14]
[ext_resource path="res://src/state_animated_actor.gd" type="Script" id=15]
[ext_resource path="res://src/playerD/states/die.gd" type="Script" id=15]
[ext_resource path="res://src/templates/Interactable/Interactable_Receiver.gd" type="Script" id=16]
[sub_resource type="StreamTexture" id=90]
@ -170,179 +169,179 @@ region = Rect2( 1200, 1600, 240, 160 )
[sub_resource type="AtlasTexture" id=128]
atlas = SubResource( 90 )
region = Rect2( 2400, 0, 240, 160 )
region = Rect2( 240, 160, 240, 160 )
[sub_resource type="AtlasTexture" id=129]
atlas = SubResource( 90 )
region = Rect2( 0, 160, 240, 160 )
region = Rect2( 1680, 160, 240, 160 )
[sub_resource type="AtlasTexture" id=130]
atlas = SubResource( 90 )
region = Rect2( 240, 160, 240, 160 )
region = Rect2( 1920, 160, 240, 160 )
[sub_resource type="AtlasTexture" id=131]
atlas = SubResource( 90 )
region = Rect2( 1680, 160, 240, 160 )
region = Rect2( 2160, 160, 240, 160 )
[sub_resource type="AtlasTexture" id=132]
atlas = SubResource( 90 )
region = Rect2( 1920, 160, 240, 160 )
region = Rect2( 2400, 160, 240, 160 )
[sub_resource type="AtlasTexture" id=133]
atlas = SubResource( 90 )
region = Rect2( 2160, 160, 240, 160 )
region = Rect2( 0, 320, 240, 160 )
[sub_resource type="AtlasTexture" id=134]
atlas = SubResource( 90 )
region = Rect2( 2400, 160, 240, 160 )
region = Rect2( 240, 320, 240, 160 )
[sub_resource type="AtlasTexture" id=135]
atlas = SubResource( 90 )
region = Rect2( 0, 320, 240, 160 )
region = Rect2( 480, 320, 240, 160 )
[sub_resource type="AtlasTexture" id=136]
atlas = SubResource( 90 )
region = Rect2( 240, 320, 240, 160 )
region = Rect2( 720, 320, 240, 160 )
[sub_resource type="AtlasTexture" id=137]
atlas = SubResource( 90 )
region = Rect2( 480, 320, 240, 160 )
region = Rect2( 960, 320, 240, 160 )
[sub_resource type="AtlasTexture" id=138]
atlas = SubResource( 90 )
region = Rect2( 960, 320, 240, 160 )
region = Rect2( 1200, 320, 240, 160 )
[sub_resource type="AtlasTexture" id=139]
atlas = SubResource( 90 )
region = Rect2( 1200, 320, 240, 160 )
region = Rect2( 1680, 640, 240, 160 )
[sub_resource type="AtlasTexture" id=140]
atlas = SubResource( 90 )
region = Rect2( 1440, 320, 240, 160 )
region = Rect2( 1920, 640, 240, 160 )
[sub_resource type="AtlasTexture" id=141]
atlas = SubResource( 90 )
region = Rect2( 1680, 640, 240, 160 )
region = Rect2( 2160, 640, 240, 160 )
[sub_resource type="AtlasTexture" id=142]
atlas = SubResource( 90 )
region = Rect2( 1920, 640, 240, 160 )
region = Rect2( 2400, 640, 240, 160 )
[sub_resource type="AtlasTexture" id=143]
atlas = SubResource( 90 )
region = Rect2( 2160, 640, 240, 160 )
region = Rect2( 0, 800, 240, 160 )
[sub_resource type="AtlasTexture" id=144]
atlas = SubResource( 90 )
region = Rect2( 2400, 640, 240, 160 )
region = Rect2( 240, 800, 240, 160 )
[sub_resource type="AtlasTexture" id=145]
atlas = SubResource( 90 )
region = Rect2( 0, 800, 240, 160 )
region = Rect2( 480, 800, 240, 160 )
[sub_resource type="AtlasTexture" id=146]
atlas = SubResource( 90 )
region = Rect2( 240, 800, 240, 160 )
region = Rect2( 720, 800, 240, 160 )
[sub_resource type="AtlasTexture" id=147]
atlas = SubResource( 90 )
region = Rect2( 480, 800, 240, 160 )
region = Rect2( 960, 800, 240, 160 )
[sub_resource type="AtlasTexture" id=148]
atlas = SubResource( 90 )
region = Rect2( 720, 800, 240, 160 )
region = Rect2( 1200, 800, 240, 160 )
[sub_resource type="AtlasTexture" id=149]
atlas = SubResource( 90 )
region = Rect2( 960, 800, 240, 160 )
region = Rect2( 1440, 800, 240, 160 )
[sub_resource type="AtlasTexture" id=150]
atlas = SubResource( 90 )
region = Rect2( 1200, 800, 240, 160 )
region = Rect2( 1920, 320, 240, 160 )
[sub_resource type="AtlasTexture" id=151]
atlas = SubResource( 90 )
region = Rect2( 1440, 800, 240, 160 )
region = Rect2( 2160, 320, 240, 160 )
[sub_resource type="AtlasTexture" id=152]
atlas = SubResource( 90 )
region = Rect2( 1920, 320, 240, 160 )
region = Rect2( 2400, 320, 240, 160 )
[sub_resource type="AtlasTexture" id=153]
atlas = SubResource( 90 )
region = Rect2( 2160, 320, 240, 160 )
region = Rect2( 0, 480, 240, 160 )
[sub_resource type="AtlasTexture" id=154]
atlas = SubResource( 90 )
region = Rect2( 2400, 320, 240, 160 )
region = Rect2( 240, 480, 240, 160 )
[sub_resource type="AtlasTexture" id=155]
atlas = SubResource( 90 )
region = Rect2( 0, 480, 240, 160 )
region = Rect2( 480, 480, 240, 160 )
[sub_resource type="AtlasTexture" id=156]
atlas = SubResource( 90 )
region = Rect2( 240, 480, 240, 160 )
region = Rect2( 720, 480, 240, 160 )
[sub_resource type="AtlasTexture" id=157]
atlas = SubResource( 90 )
region = Rect2( 480, 480, 240, 160 )
region = Rect2( 960, 480, 240, 160 )
[sub_resource type="AtlasTexture" id=158]
atlas = SubResource( 90 )
region = Rect2( 720, 480, 240, 160 )
region = Rect2( 1200, 480, 240, 160 )
[sub_resource type="AtlasTexture" id=159]
atlas = SubResource( 90 )
region = Rect2( 960, 480, 240, 160 )
region = Rect2( 1440, 480, 240, 160 )
[sub_resource type="AtlasTexture" id=160]
atlas = SubResource( 90 )
region = Rect2( 1200, 480, 240, 160 )
region = Rect2( 1920, 480, 240, 160 )
[sub_resource type="AtlasTexture" id=161]
atlas = SubResource( 90 )
region = Rect2( 1440, 480, 240, 160 )
region = Rect2( 2160, 480, 240, 160 )
[sub_resource type="AtlasTexture" id=162]
atlas = SubResource( 90 )
region = Rect2( 1920, 480, 240, 160 )
region = Rect2( 2400, 480, 240, 160 )
[sub_resource type="AtlasTexture" id=163]
atlas = SubResource( 90 )
region = Rect2( 2160, 480, 240, 160 )
region = Rect2( 0, 640, 240, 160 )
[sub_resource type="AtlasTexture" id=164]
atlas = SubResource( 90 )
region = Rect2( 2400, 480, 240, 160 )
region = Rect2( 240, 640, 240, 160 )
[sub_resource type="AtlasTexture" id=165]
atlas = SubResource( 90 )
region = Rect2( 0, 640, 240, 160 )
region = Rect2( 480, 640, 240, 160 )
[sub_resource type="AtlasTexture" id=166]
atlas = SubResource( 90 )
region = Rect2( 240, 640, 240, 160 )
region = Rect2( 720, 640, 240, 160 )
[sub_resource type="AtlasTexture" id=167]
atlas = SubResource( 90 )
region = Rect2( 480, 640, 240, 160 )
region = Rect2( 960, 640, 240, 160 )
[sub_resource type="AtlasTexture" id=168]
atlas = SubResource( 90 )
region = Rect2( 720, 640, 240, 160 )
region = Rect2( 1200, 640, 240, 160 )
[sub_resource type="AtlasTexture" id=169]
atlas = SubResource( 90 )
region = Rect2( 960, 640, 240, 160 )
region = Rect2( 1440, 640, 240, 160 )
[sub_resource type="AtlasTexture" id=170]
atlas = SubResource( 90 )
region = Rect2( 1200, 640, 240, 160 )
region = Rect2( 2400, 0, 240, 160 )
[sub_resource type="AtlasTexture" id=171]
atlas = SubResource( 90 )
region = Rect2( 1440, 640, 240, 160 )
region = Rect2( 0, 160, 240, 160 )
[sub_resource type="AtlasTexture" id=172]
atlas = SubResource( 90 )
@ -480,36 +479,41 @@ animations = [ {
"name": "idle_shield",
"speed": 10.0
}, {
"frames": [ SubResource( 128 ), SubResource( 129 ), SubResource( 130 ) ],
"frames": [ SubResource( 128 ) ],
"loop": false,
"name": "idle_shoot",
"speed": 10.0
}, {
"frames": [ SubResource( 131 ), SubResource( 132 ), SubResource( 133 ), SubResource( 134 ), SubResource( 132 ), SubResource( 135 ), SubResource( 136 ), SubResource( 137 ) ],
"frames": [ SubResource( 129 ), SubResource( 130 ), SubResource( 131 ), SubResource( 132 ), SubResource( 130 ), SubResource( 133 ), SubResource( 134 ), SubResource( 135 ) ],
"loop": false,
"name": "jump",
"speed": 10.0
}, {
"frames": [ SubResource( 138 ), SubResource( 138 ), SubResource( 138 ), SubResource( 138 ), SubResource( 138 ), SubResource( 138 ), SubResource( 139 ), SubResource( 140 ) ],
"frames": [ SubResource( 136 ), SubResource( 136 ), SubResource( 136 ), SubResource( 136 ), SubResource( 136 ), SubResource( 136 ), SubResource( 137 ), SubResource( 138 ) ],
"loop": false,
"name": "jump_shoot",
"speed": 10.0
}, {
"frames": [ SubResource( 141 ), SubResource( 142 ), SubResource( 143 ), SubResource( 144 ), SubResource( 145 ), SubResource( 146 ), SubResource( 147 ), SubResource( 148 ), SubResource( 149 ), SubResource( 150 ), SubResource( 151 ) ],
"frames": [ SubResource( 139 ), SubResource( 140 ), SubResource( 141 ), SubResource( 142 ), SubResource( 143 ), SubResource( 144 ), SubResource( 145 ), SubResource( 146 ), SubResource( 147 ), SubResource( 148 ), SubResource( 149 ) ],
"loop": false,
"name": "roll",
"speed": 10.0
}, {
"frames": [ SubResource( 152 ), SubResource( 153 ), SubResource( 154 ), SubResource( 155 ), SubResource( 156 ), SubResource( 157 ), SubResource( 158 ), SubResource( 159 ), SubResource( 160 ), SubResource( 161 ) ],
"frames": [ SubResource( 150 ), SubResource( 151 ), SubResource( 152 ), SubResource( 153 ), SubResource( 154 ), SubResource( 155 ), SubResource( 156 ), SubResource( 157 ), SubResource( 158 ), SubResource( 159 ) ],
"loop": true,
"name": "run",
"speed": 10.0
}, {
"frames": [ SubResource( 162 ), SubResource( 163 ), SubResource( 164 ), SubResource( 165 ), SubResource( 166 ), SubResource( 167 ), SubResource( 168 ), SubResource( 169 ), SubResource( 170 ), SubResource( 171 ) ],
"frames": [ SubResource( 160 ), SubResource( 161 ), SubResource( 162 ), SubResource( 163 ), SubResource( 164 ), SubResource( 165 ), SubResource( 166 ), SubResource( 167 ), SubResource( 168 ), SubResource( 169 ) ],
"loop": true,
"name": "run_shoot",
"speed": 10.0
}, {
"frames": [ SubResource( 170 ), SubResource( 171 ), SubResource( 128 ) ],
"loop": false,
"name": "shoot",
"speed": 10.0
}, {
"frames": [ SubResource( 172 ), SubResource( 173 ), SubResource( 174 ), SubResource( 174 ), SubResource( 175 ), SubResource( 176 ), SubResource( 177 ), SubResource( 178 ), SubResource( 178 ), SubResource( 179 ), SubResource( 180 ), SubResource( 181 ), SubResource( 182 ), SubResource( 183 ), SubResource( 184 ), SubResource( 185 ), SubResource( 186 ), SubResource( 187 ), SubResource( 188 ), SubResource( 189 ), SubResource( 190 ), SubResource( 191 ) ],
"loop": true,
"name": "slash",
@ -543,7 +547,7 @@ player_number = 1
position = Vector2( -1, -51 )
frames = SubResource( 198 )
animation = "idle_shoot"
frame = 2
frame = 0
flip_h = false
__meta__ = {
"_aseprite_wizard_config_": {
@ -574,19 +578,14 @@ roll_node = NodePath("../roll")
[node name="fall" parent="movement_state_machine" index="1"]
script = ExtResource( 6 )
debug_state = true
move_speed = 90.0
animation_sequence = [ "jump" ]
landing_node = NodePath("landing")
[node name="landing" type="Node" parent="movement_state_machine/fall" index="0"]
script = ExtResource( 9 )
animation_name = "jump"
modifier_type = "Exit Animation"
starting_frame = 6
pre_append_animation = true
landing_node = NodePath("")
[node name="move" parent="movement_state_machine" index="2"]
script = ExtResource( 5 )
debug_state = true
move_speed = 90.0
animation_sequence = [ "step", "run" ]
jump_node = NodePath("../jump")
@ -594,29 +593,22 @@ attack_node = NodePath("../attack")
[node name="jump" type="Node" parent="movement_state_machine" index="3"]
script = ExtResource( 8 )
debug_state = true
move_speed = 90.0
animation_sequence = [ "jump" ]
idle_node = NodePath("../idle")
fall_node = NodePath("../fall")
attack_node = NodePath("../attack")
landing_node = NodePath("../fall/landing")
jump_force = 250.0
[node name="attack" type="Node" parent="movement_state_machine" index="4"]
script = ExtResource( 10 )
timeout_seconds = 2.0
timeout_seconds = 1.5
animation_sequence = [ "shoot" ]
jump_node = NodePath("../jump")
idle_node = NodePath("../idle")
fall_node = NodePath("../fall")
move_node = NodePath("../move")
draw_weapon_node = NodePath("draw_weapon")
[node name="draw_weapon" type="Node" parent="movement_state_machine/attack" index="0"]
script = ExtResource( 9 )
animation_name = "_shoot"
modifier_type = "Animation Suffix"
timeout_seconds = 2.2
animation_suffix = true
[node name="hurt" type="Node" parent="movement_state_machine" index="5"]
script = ExtResource( 12 )

View File

@ -6,36 +6,53 @@ export (NodePath) var fall_node
export (NodePath) var move_node
export (NodePath) var draw_weapon_node
onready var jump_state: State = get_node(jump_node)
onready var idle_state: State = get_node(idle_node)
onready var fall_state: State = get_node(fall_node)
onready var move_state: State = get_node(move_node)
onready var weapon_state_modifier: StateModifier = get_node(draw_weapon_node)
onready var jump_state: StateAnimatedActor = get_node(jump_node)
onready var idle_state: StateAnimatedActor = get_node(idle_node)
onready var fall_state: StateAnimatedActor = get_node(fall_node)
onready var move_state: StateAnimatedActor = get_node(move_node)
#onready var weapon_state_modifier: StateModifier = get_node(draw_weapon_node)
var can_fire = true
signal do_attack()
func enter() -> void:
#.enter()
##TODO: Turn this to clear only the animation modifiers.
modifier_stack_ref.clear()
mod_animation_sequence.clear()
#mod_animation_sequence = animation_sequence.duplicate(true)
mod_animation_sequence.append_array(animation_sequence)
# Reset animation suffix in case there isn't one
animation_suffix = '_shoot'
animation_index = 0
current_animation_sequence = 0
#var enter_animation = ''
var enter_frame = 0
if debug_state:
print(parent.name, " entering State: ", self.name)
move_component.current_movement_state = self.name
emit_signal("state_entered")
var draw_weapon_modifier: StateModifier
func _ready():
state_timeout.connect("timeout", self, "disable_cooldown")
draw_weapon_modifier = StateModifier.new()
var mod_timer :Timer = draw_weapon_modifier.ready( "draw_weapon", "_shoot" , draw_weapon_modifier.TYPE.ANIMATION_SUFFIX, 2.0)
add_child(mod_timer)
func disable_cooldown():
if debug_state:
print("Attack state cooldown timeout. Can attack again.")
state_ready = true
func enter() -> void:
if modifier:
if modifier.get_instance_id() == draw_weapon_modifier.get_instance_id():
#print ("They the same cannot apply modifier: ", draw_weapon_modifier.get_instance_id())
modifier = null
.enter()
##TODO: Turn this to clear only the animation modifiers.
# modifier_stack_ref.clear()
# mod_animation_sequence.clear()
# #mod_animation_sequence = animation_sequence.duplicate(true)
# mod_animation_sequence.append_array(animation_sequence)
# # Reset animation suffix in case there isn't one
# animation_suffix = '_shoot'
# animation_index = 0
# current_animation_sequence = 0
# #var enter_animation = ''
# var enter_frame = 0
#
# if debug_state:
# print(parent.name, " entering State: ", self.name)
# move_component.current_movement_state = self.name
# emit_signal("state_entered")
state_timeout.start()
can_fire = true
# if modifier_stack_ref.has($"../draw_weapon") == false:
# $"../draw_weapon".enter()
@ -45,21 +62,43 @@ func enter() -> void:
previous_state_frame_number, " ", previous_state_name)
match previous_animation_name:
"idle":
animations.play("idle_shoot")
#animations.play("idle_shoot")
if debug_state:
print("no need to change idle animation")
"run":
animations.play("run_shoot")
animations.frame = previous_state_frame_number
"jump":
animations.play("jump_shoot")
animations.frame = previous_state_frame_number
if debug_state:
print("Starting Animation: jump_shoot at frame ", animations.animation , animations.frame)
_:
print("Warning!: Attack state encountered unhandled prev animation: ", previous_animation_name)
# An example where the modifier is left to alert on a timeout
#mod_timer.connect("timeout", draw_weapon_modifier, "_on_Timer_timeout")
# An example where the current node subscribes
#mod_timer.connect("timeout", self, "_on_Timer_timeout")
state_timeout.start()
draw_weapon_modifier.state_timeout.start()
state_ready = false
animation_finished = false
func _on_Timer_timeout():
print("Modifier Timeout from attack! Forcing animation recall")
#animations.stop()
func process_frame(delta: float) -> State:
if animation_finished:
draw_weapon_modifier.state_timeout.start()
modifier = draw_weapon_modifier
return idle_state
# if animations.frame == 2:
# animations.stop()
if state_timeout.time_left == 0 and animations.animation == "shoot":
return idle_state
# if state_timeout.time_left == 0 and animations.animation == "shoot":
# return idle_state
return null
@ -70,14 +109,19 @@ func process_physics(delta: float) -> State:
can_fire = false
if move_component.wants_jump() and parent.is_on_floor():
draw_weapon_modifier.state_timeout.start()
jump_state.modifier = draw_weapon_modifier
return jump_state
move_actor_as_desired(delta)
if previous_state_name == "move" and move_component.velocity.x == 0.0:
return idle_state
# if previous_state_name == "move" and move_component.velocity.x == 0.0:
# return idle_state
if previous_state_name == "idle" and move_component.velocity.x != 0.0:
if move_component.velocity.x != 0.0:
draw_weapon_modifier.state_timeout.start()
move_state.modifier = draw_weapon_modifier
#draw_weapon_modifier.transfer_owner(move_state)
return move_state
if move_component.get_movement_direction() != 0.0:
@ -87,16 +131,10 @@ func process_physics(delta: float) -> State:
# return move_state
if !parent.is_on_floor():
draw_weapon_modifier.state_timeout.start()
fall_state.modifier = draw_weapon_modifier
return fall_state
return null
func exit() -> void:
# force timer reset
weapon_state_modifier.state_timeout.start()
push_animation_state_modifier(weapon_state_modifier)
#$"../draw_weapon".state_timeout.start()
return

View File

@ -14,7 +14,7 @@ var speed_decay_rate := 1.0
var adjusted_move_speed: float
func enter():
remove_animation_state_modifiers()
#remove_animation_state_modifiers()
.enter()
adjusted_move_speed = move_speed_modifier
speed_multiplier = 5

12
src/playerD/states/die.gd Normal file
View File

@ -0,0 +1,12 @@
extends StateAnimatedActor
func enter() -> void:
# modifier_stack_ref.clear()
.enter()
move_component.velocity.x = 0
func process_physics(_delta: float) -> State:
#Dead Dead dead.
#move_actor_as_desired(_delta)
return null

View File

@ -3,14 +3,25 @@ extends StateAnimatedActor
export (NodePath) var idle_node
export (NodePath) var landing_node
onready var idle_state: State = get_node(idle_node)
onready var landing_mod: StateModifier = get_node(landing_node)
onready var idle_state: StateAnimatedActor = get_node(idle_node)
#onready var landing_mod: StateModifier = get_node(landing_node)
var landing_modifier: StateModifier
func _ready():
landing_modifier= StateModifier.new()
#add_child(modifier)
#modifier.init_ref()
landing_modifier.ready( "landing", "jump" , landing_modifier.TYPE.EXIT_ANIMATION)
landing_modifier.starting_frame = 6
#print("ready! MOD")
func enter() -> void:
var landing_mod_index = modifier_stack_ref.rfind(landing_mod)
if landing_mod_index != -1:
#print("You're Supposed to be dead!?: ", landing_mod_index)
modifier_stack_ref.remove(landing_mod_index)
# var landing_mod_index = modifier_stack_ref.rfind(landing_mod)
# if landing_mod_index != -1:
# #print("You're Supposed to be dead!?: ", landing_mod_index)
# modifier_stack_ref.remove(landing_mod_index)
.enter()
# Jump to fall frame
animations.frame = 5
@ -26,13 +37,15 @@ func process_physics(delta: float) -> State:
parent.transform.x.x = move_component.get_movement_direction()
if parent.is_on_floor():
print("DO you even!?: ", landing_modifier.animation_name)
#modifier.reference()
idle_state.modifier = landing_modifier
return idle_state
return null
func exit() -> void:
.exit()
push_animation_state_modifier(landing_mod)
# $"../landing".enter()
# modifier_stack_ref.push_front($"../landing")
return
#func exit() -> void:
# .exit()
## push_animation_state_modifier(landing_mod)
## $"../landing".enter()
## modifier_stack_ref.push_front($"../landing")
# return

View File

@ -6,8 +6,15 @@ onready var idle_state: State = get_node(idle_node)
var flash_color = Color.yellow
var store_modifier: StateModifier
func enter() -> void:
modifier_stack_ref.clear()
if modifier:
if debug_state:
print(name, " skipping modifier and holding for next state.")
store_modifier = modifier
modifier = null
# modifier_stack_ref.clear()
.enter()
move_component.velocity.x = 0
#parent.set_hurtbox(false)
@ -15,6 +22,7 @@ func enter() -> void:
state_timeout.start()
func exit() -> void:
modifier = store_modifier
.exit()
animations.modulate = Color.white

View File

@ -9,15 +9,15 @@ export (NodePath) var landing_node
onready var idle_state: State = get_node(idle_node)
onready var fall_state: State = get_node(fall_node)
onready var attack_state: State = get_node(attack_node)
onready var landing_mod: StateModifier = get_node(landing_node)
#onready var landing_mod: StateModifier = get_node(landing_node)
export var jump_force: float = 200.0
func enter() -> void:
var landing_mod_index = modifier_stack_ref.rfind(landing_mod)
if landing_mod_index != -1:
#print("You're Supposed to be dead!?: ", landing_mod_index)
modifier_stack_ref.remove(landing_mod_index)
# var landing_mod_index = modifier_stack_ref.rfind(landing_mod)
# if landing_mod_index != -1:
# #print("You're Supposed to be dead!?: ", landing_mod_index)
# modifier_stack_ref.remove(landing_mod_index)
# if modifier_stack_ref.has(landing_mod):
# print("Jump from Landing Mod at: ", modifier_stack_ref.rfind(landing_mod))
.enter()

View File

@ -9,7 +9,7 @@ onready var idle_state: State = get_node(idle_node)
var speed_decay_rate := 1.0
func enter():
remove_animation_state_modifiers()
#remove_animation_state_modifiers()
.enter()

View 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

View File

@ -8,8 +8,9 @@ signal state_entered()
signal state_exited()
# Declare member variables here. Examples:
var modifier_stack_ref: Array # Well this didn't work
#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():

View File

@ -29,6 +29,9 @@ 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
@ -52,6 +55,8 @@ var previous_state_frame_number : int
var previous_state_name: String
var previous_speed_multiplier: float
var modifier: StateModifier
#var animation_sequence_timer: Timer
@ -65,76 +70,75 @@ func _ready():
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
func enter() -> void:
# animations.connect("animation_finished", self, "_on_AnimatedSprite_animation_finished")
# By Default, we build an animation sequence off of this state's before checking
# for modifiers
mod_animation_sequence.clear()
#mod_animation_sequence = animation_sequence.duplicate(true)
mod_animation_sequence.append_array(animation_sequence)
# Reset animation suffix in case there isn't one
animation_suffix = ''
animation_index = 0
current_animation_sequence = 0
animation_suffix = suffix
animation_index = index
current_animation_sequence = animation_index
#var enter_animation = ''
var enter_frame = 0
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
# A new attempt at animation modifiers
if modifier_stack_ref.empty() == false:
print("nope: ")
var i = modifier_stack_ref.size() - 1
##NOTE: i apparently reverse range itteration doesn't work
#for i in range(modifier_stack_ref.size(), 0): # work in reverse
while (i >= 0 and modifier_stack_ref[i].modifier_type != "None"):
print("Animation Modifier!: ",modifier_stack_ref[i].modifier_type)
match modifier_stack_ref[i].modifier_type:
"Exit Animation":
mod_animation_sequence.push_front(modifier_stack_ref[i].animation_name)
enter_frame = modifier_stack_ref[i].starting_frame
# Gonna ty and avoid this for now
#modifier_stack_ref.pop_at(i) # we're done with this modifier
"Animation Suffix":
if animations.frames.has_animation(mod_animation_sequence[animation_index] + modifier_stack_ref[i].animation_name):
animation_suffix = modifier_stack_ref[i].animation_name
else:
print("Warning!: Animation suffix that doesn't exist ",
mod_animation_sequence[animation_index] + modifier_stack_ref[i].animation_name)
"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_stack_ref[i].animation_name)
enter_frame = modifier_stack_ref[i].starting_frame
i -= 1
#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
# if modifier_stack_ref.empty() == false: # a modifier is applied
# if modifier_stack_ref[-1].animation_name != '': # the first one has an animation
# if modifier_stack_ref[-1].animation_suffix: # it's a suffix type
# if mod_animation_sequence.size() > 0: # the current animation is multipart (sequence > 0)
# animation_index = 0
# current_animation_sequence = 0
# # Guess I don't need this one anymore
# #if animations.frames.get_animation_names().has(animation_sequence[animation_index] + modifier_stack_ref[-1].animation_name):
# if animations.frames.has_animation(mod_animation_sequence[animation_index] + modifier_stack_ref[-1].animation_name):
# animation_suffix = modifier_stack_ref[-1].animation_name
# elif modifier_stack_ref[-1].pre_append_animation == true: # it's a pre-append type
# #animation_sequence.size()
# print ("DEBUG: A prepend animation")
# #mod_animation_sequence = animation_sequence
# mod_animation_sequence.push_front(modifier_stack_ref[-1].animation_name)
# else:
# animations.play(modifier_stack_ref[-1].animation_name)
# animations.frame = modifier_stack_ref[-1].starting_frame
# return
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:
@ -146,17 +150,71 @@ func enter() -> void:
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()
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_frame(_delta: float) -> State:
#if animation_sequence.size() > 0 and current_animation_sequence != animation_index:
if mod_animation_sequence.size() > animation_index and current_animation_sequence != animation_index:
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
@ -166,11 +224,8 @@ func process_frame(_delta: float) -> State:
print("An animation sequence: ", mod_animation_sequence[animation_index - 1], " -> ",
animations.animation , " (", animation_index, ")")
current_animation_sequence = animation_index
# We have no more sequence animations and the current one doesn't loop
# we do this to prevent the default idle animation from playing.
if animation_index >= mod_animation_sequence.size() and animations.frames.get_animation_loop(
animations.animation) == false:
animations.stop()
##TODO: Could probably add some more checks here.
# Singal based frame call.
if emitter_frame_subscriptions.has(animations.frame):
@ -182,6 +237,7 @@ func process_frame(_delta: float) -> State:
else:
frame_signal_emitted = false
func process_frame(_delta: float) -> State:
return null
func process_physics(_delta: float) -> State:
@ -212,53 +268,3 @@ func move_actor_as_desired(delta: float):
move_component.velocity.x = move_component.desired_movement_vector.x * new_speed
move_component.velocity = parent.move_and_slide(move_component.velocity, Vector2(0, -1))
func push_animation_state_modifier(modifier: StateModifier):
## This function attempt to optimally place multiple modifiers in an array
# in such a way where the first elements are modifiers without animation changes
# the last elements are animation changes or animation suffixes.
# there is some potential for performance issues at scale with this kinds of operations.
# This function will grow in complexity as needed but the idea is that here is
# where different modifier logic can be tested and developed.
# First assure this modifer isn't already there. If it is, maybe I should reset it?
if modifier_stack_ref.has(modifier) == false:
modifier.enter() # call enter function of the modifier
if modifier_stack_ref.size() > 0: # only bother with this if multiple modifers applied
# Get the last modifier in the stack
var last_modifer: StateModifier = modifier_stack_ref[-1]
# If the modifier at the back and the new one are the same type, we have a problem.
if last_modifer.modifier_type == modifier.modifier_type and last_modifer.modifier_type != 'None':
print("WARNING: Multiple same type modifiers applying.")
# Replace the modifier
modifier_stack_ref.pop_back()
modifier_stack_ref.push_back(modifier)
else:
match last_modifer.modifier_type:
"None":
# no special processing, push it to the front of a list
modifier_stack_ref.push_front(modifier)
"Exit Animation":
if modifier.modifier_type == "Animation Suffix":
# We place this at the back so we can still modify it maybe?
modifier_stack_ref.push_back(modifier)
"Animation Suffix":
if modifier.modifier_type == "Exit Animation":
# We have to place this one right before maybe?
# Whoops! Forgot to actually do this
#modifier_stack_ref.push_back(modifier)
modifier_stack_ref.insert(modifier_stack_ref.size() - 1, modifier)
# if last_modifer.animation_name != '': # and if an animation applies
# if last_modifer.pre_append_animation == modifier.pre_append_animation: # They're the same type
# if modifier.pre_append_animation == true and modifier_stack_ref[-1].animation_suffix == true:
# modifier.animation_suffix
# modifier_stack_ref.push_back(modifier)
else:
modifier_stack_ref.push_front(modifier)
func remove_animation_state_modifiers():
for i in modifier_stack_ref.size():
if modifier_stack_ref[i].modifier_type != "None":
#print("Time to pop state modifer: ", state_modifiers[i].animation_name, current_state.animation_suffix, " <-> ", current_state.animations.animation + current_state.animation_suffix)
modifier_stack_ref.pop_at(i)

View File

@ -4,7 +4,7 @@ export (NodePath) var starting_state
export var debug_state_machine: bool = false
var current_state: State
var state_modifiers: Array
#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.
@ -13,7 +13,7 @@ func init() -> void:
if child is State:
if debug_state_machine:
print("Initializing State Node: ", child.name)
child.modifier_stack_ref = state_modifiers
# child.modifier_stack_ref = state_modifiers
if debug_state_machine:
child.debug_state = true
@ -27,10 +27,10 @@ func change_state(new_state: State) -> void:
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)
# 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.

View File

@ -1,18 +1,24 @@
class_name StateMachineAnimatedActor extends StateMachine
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
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)
# 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.)
@ -35,7 +41,7 @@ func init_animated_actor(parent: KinematicBody2D, animations: AnimatedSprite, mo
child.parent = parent
child.animations = animations
child.move_component = move_component
child.modifier_stack_ref = state_modifiers
# child.modifier_stack_ref = state_modifiers
if debug_state_machine:
child.debug_state = true
@ -48,95 +54,67 @@ func process_frame(delta: float) -> void:
# 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
##TODO:
# no longer needed this way maybe. way to overengineer man.
# if current_anim_state.animation_sequence.size() >= current_anim_state.mod_animation_sequence.size():
# print("Change sequence!: ", current_anim_state.mod_animation_sequence)
# print("Origin sequence!: ", current_state.mod_animation_sequence)
# 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
# else:
# current_anim_state.animations.play(
# current_anim_state.animation_sequence[0])
if debug_state_machine:
print("Pop State Modifier: ", state_modifiers[i].name)
state_modifiers.pop_at(i)
# if state_modifiers[-1].state_timeout.time_left == 0 and state_modifiers[-1].pre_append_animation == false:
# if debug_state_machine:
# print("Pop State Modifier: ", state_modifiers[-1].name)
# state_modifiers.pop_back()
# # Reset animation suffix
# current_state.animation_suffix = ''
# var current_frame = current_state.animations.frame
# #current_state.animations.play(current_state.animation_sequence[current_state.animation_index])
# #TODO: Bodge to fix crash
# current_state.animation_index = 0
# current_state.current_animation_sequence = 0
# current_state.animations.play(current_state.animation_sequence[0])
# current_state.animations.frame = current_frame;
# 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
# 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 state_modifiers.empty() == false:
# if state_modifiers[-1].pre_append_animation == true:
# if debug_state_machine:
# print("Pop State Modifier: ", state_modifiers[-1].name)
# state_modifiers.pop_back()
##TODO:
# consider just stopping the animation and index increment here.
# 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.")
#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

View File

@ -1,5 +1,5 @@
class_name StateModifier
extends Node
extends Reference
## State modification
##
## A state modifier doesn't have any direct control of a game object.
@ -10,33 +10,36 @@ extends Node
##
## @WIP
export var debug_state: bool = false
enum TYPE {NONE,EXIT_ANIMATION, ANIMATION_SUFFIX, REPLACE_ANIMATION}
export var animation_name: String
var debug_state: bool = false
## Animation modifier variables
## The name of the animation that could be applied and starting frame
var animation_name: String
var starting_frame: int = 0
## Modification Type
## if an animation is specified, the default behavior will be just to override
## the state animation. Or perform a 'Replace Animation'
export(String, "None",
"Exit Animation",
"Animation Suffix",
"Replace Animation") var modifier_type = "None"
var modifier_type = TYPE.NONE
export var starting_frame: int = 0
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.)
export var move_speed: float
export var move_speed_modifier: float = 0
export var move_speed_modifier_decay: float = 0
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")
export var timeout_seconds: float = 0.0
# Attempting to use this as an animation suffix that can linger after
# state transition like 'run-fire' to 'idle-fire' 'jump-fire' etc.
export var animation_suffix: bool = false
export var pre_append_animation: bool = false
#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.
@ -44,32 +47,60 @@ export var pre_append_animation: bool = false
# var animation_index: int = 0
# var current_animation_sequence: int = 0
var gravity: int = ProjectSettings.get_setting("physics/2d/default_gravity")
#var animation_sequence_timer: Timer
var state_timeout: Timer
var timeout_seconds: float = 0.0
func _ready():
# 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: StateModifier) -> StateModifier:
# var new_modifier = StateModifier.new()
# new_modifier.ready(animation_name, modifier_type, timeout_seconds)
#
# return StateModifier.new()
func ready(modifier_name:String, anim_name:String = '', type = TYPE.NONE, timeout : float = 0, parent:Node = null, function_name : String = "") -> Timer:
# If somebody forgot to specify the type
if animation_name != '' and modifier_type == "None":
modifier_type = "Replace Animation"
state_timeout = Timer.new()
if timeout_seconds > 0:
state_timeout.wait_time = timeout_seconds
state_timeout.one_shot = true
state_timeout.autostart = false
add_child(state_timeout)
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)
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)
return null
func enter() -> void:
if debug_state:
print("Apply State Modifier: ", self.name)
state_timeout.start()
#modifier_stack_ref = state_modifiers
return
func exit() -> void:
pass
## 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 _update():
pass
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.")