Should have done this a while ago.

This commit is contained in:
Nitsud Yarg 2024-04-25 20:13:25 -07:00
commit aaad967476
63 changed files with 3379 additions and 0 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
# Godot 4+ specific ignores
.godot/
.import/
.mono/
addons/

140
Enemy-KinematicBody2D.gd Normal file
View File

@ -0,0 +1,140 @@
class_name Enemy extends KinematicBody2D
enum STATE {IDLE, WANDER, JUMP, FALL, HURT, ATTACK}
enum STATE_SECONDARY {NONE, SHOOT}
#const WALK_FORCE = 600
const WALK_MAX_SPEED = (30*2)
#const STOP_FORCE = 1300
const JUMP_SPEED = 270
var velocity = Vector2()
var gravity = 60*9.8
var player_state = STATE.IDLE
var player_last_state = null
var animation_play_finished = true
var flip_direction = false
onready var _animated_sprite = $AnimatedSprite
func _physics_process(delta):
# Horizontal movement
if player_state != STATE.WANDER and $IdleTimeout.time_left == 0:
if flip_direction:
velocity.x = (1 * WALK_MAX_SPEED)
flip_direction = false
else:
velocity.x = (-1 * WALK_MAX_SPEED)
flip_direction = true
# Vertical movement code. Apply gravity.
velocity.y += gravity * delta
# Move based on the velocity and snap to the ground.
#velocity = move_and_slide_with_snap(velocity, Vector2.DOWN, Vector2.UP)
velocity = move_and_slide(velocity, Vector2(0, -1))
# Animate based on last state and velocity
if velocity.x > 0 and _animated_sprite.flip_h != true:
_animated_sprite.flip_h = true
_animated_sprite.offset.x = 0
$PlayerDetection.cast_to = Vector2(20,0)
if velocity.x < 0 and _animated_sprite.flip_h != false:
_animated_sprite.flip_h = false
_animated_sprite.offset.x = -18
$PlayerDetection.cast_to = Vector2(-20,0)
# forced state changes like falling an gitting hurt
if velocity.y > 0 and player_state != STATE.JUMP and player_state != STATE.FALL:
print("STATE_TRANSITION: Fall")
player_state = STATE.FALL
if $PlayerDetection.is_colliding():
player_state = STATE.ATTACK
player_last_state = null
velocity.x = 0
# Each state should trigger its own animation
match player_state:
STATE.IDLE:
# Transitions
if velocity.y == -JUMP_SPEED:
print("STATE_TRANSITION: Jump")
player_last_state = STATE.IDLE
player_state = STATE.JUMP
elif velocity.x != 0:
print("STATE_TRANSITION: Wander")
player_last_state = STATE.IDLE
player_state = STATE.WANDER
# Animation
if player_last_state != STATE.IDLE:
_animated_sprite.play("idle")
player_last_state = STATE.IDLE
$IdleTimeout.start()
STATE.JUMP:
# Transitions
if is_on_floor():
print("STATE_TRANSITION: Idle")
_animated_sprite.play("idle")
player_last_state = STATE.JUMP
player_state = STATE.IDLE
# Animation
if player_last_state != STATE.JUMP:
_animated_sprite.play("jump")
player_last_state = STATE.JUMP
STATE.FALL:
# Transitions
if is_on_floor():
print("STATE_TRANSITION: Idle")
_animated_sprite.play("idle")
player_last_state = STATE.FALL
player_state = STATE.IDLE
# Animation
if player_last_state != STATE.FALL:
#_animated_sprite.animation = "jump"
_animated_sprite.frame = 8
_animated_sprite.stop()
player_last_state = STATE.FALL
STATE.WANDER:
# print (_animated_sprite.animation ) # apparentl playing doesn't stop when loop is disabled.
# Transitions
if velocity.y == -JUMP_SPEED:
print("STATE_TRANSITION: Jump")
player_last_state = STATE.WANDER
player_state = STATE.JUMP
elif velocity.x == 0:
print("STATE_TRANSITION: Idle")
player_last_state = STATE.WANDER
player_state = STATE.IDLE
# Animation
if player_last_state != STATE.WANDER:
$IdleTimeout.start()
_animated_sprite.play("walk")
player_last_state = STATE.WANDER
if $IdleTimeout.time_left == 0:
$IdleTimeout.start()
velocity.x = 0
player_last_state = STATE.WANDER
player_state = STATE.IDLE
STATE.ATTACK:
# Animation
if player_last_state != STATE.ATTACK:
$IdleTimeout.start()
_animated_sprite.play("attack")
player_last_state = STATE.ATTACK
if $IdleTimeout.time_left == 0:
$IdleTimeout.start()
velocity.x = 0
player_last_state = STATE.ATTACK
player_state = STATE.IDLE
func _on_AnimatedSprite_animation_finished():
animation_play_finished = true
#print($AnimatedSprite.animation," anim over ", $IdleTimeout.time_left, animation_play_finished)

159
Enemy.tscn Normal file
View File

@ -0,0 +1,159 @@
[gd_scene load_steps=24 format=2]
[ext_resource path="res://Enemy-KinematicBody2D.gd" type="Script" id=1]
[sub_resource type="StreamTexture" id=75]
load_path = "res://.import/botEnemy.png-46efd539a38730ff15fb4ddb087329c6.stex"
[sub_resource type="AtlasTexture" id=76]
atlas = SubResource( 75 )
region = Rect2( 192, 48, 48, 48 )
[sub_resource type="AtlasTexture" id=77]
atlas = SubResource( 75 )
region = Rect2( 0, 96, 48, 48 )
[sub_resource type="AtlasTexture" id=78]
atlas = SubResource( 75 )
region = Rect2( 48, 96, 48, 48 )
[sub_resource type="AtlasTexture" id=79]
atlas = SubResource( 75 )
region = Rect2( 96, 96, 48, 48 )
[sub_resource type="AtlasTexture" id=80]
atlas = SubResource( 75 )
region = Rect2( 144, 96, 48, 48 )
[sub_resource type="AtlasTexture" id=81]
atlas = SubResource( 75 )
region = Rect2( 0, 144, 48, 48 )
[sub_resource type="AtlasTexture" id=82]
atlas = SubResource( 75 )
region = Rect2( 48, 144, 48, 48 )
[sub_resource type="AtlasTexture" id=83]
atlas = SubResource( 75 )
region = Rect2( 96, 144, 48, 48 )
[sub_resource type="AtlasTexture" id=84]
atlas = SubResource( 75 )
region = Rect2( 192, 96, 48, 48 )
[sub_resource type="AtlasTexture" id=85]
atlas = SubResource( 75 )
region = Rect2( 0, 0, 48, 48 )
[sub_resource type="AtlasTexture" id=86]
atlas = SubResource( 75 )
region = Rect2( 48, 0, 48, 48 )
[sub_resource type="AtlasTexture" id=87]
atlas = SubResource( 75 )
region = Rect2( 96, 0, 48, 48 )
[sub_resource type="AtlasTexture" id=88]
atlas = SubResource( 75 )
region = Rect2( 144, 0, 48, 48 )
[sub_resource type="AtlasTexture" id=89]
atlas = SubResource( 75 )
region = Rect2( 192, 0, 48, 48 )
[sub_resource type="AtlasTexture" id=90]
atlas = SubResource( 75 )
region = Rect2( 0, 48, 48, 48 )
[sub_resource type="AtlasTexture" id=91]
atlas = SubResource( 75 )
region = Rect2( 48, 48, 48, 48 )
[sub_resource type="AtlasTexture" id=92]
atlas = SubResource( 75 )
region = Rect2( 96, 48, 48, 48 )
[sub_resource type="AtlasTexture" id=93]
atlas = SubResource( 75 )
region = Rect2( 144, 48, 48, 48 )
[sub_resource type="SpriteFrames" id=94]
animations = [ {
"frames": [ SubResource( 76 ), SubResource( 77 ), SubResource( 78 ), SubResource( 79 ), SubResource( 80 ) ],
"loop": true,
"name": "attack",
"speed": 10.0
}, {
"frames": [ SubResource( 81 ), SubResource( 82 ), SubResource( 83 ) ],
"loop": true,
"name": "death",
"speed": 10.0
}, {
"frames": [ SubResource( 84 ) ],
"loop": true,
"name": "hurt",
"speed": 10.0
}, {
"frames": [ SubResource( 85 ), SubResource( 86 ), SubResource( 87 ) ],
"loop": true,
"name": "idle",
"speed": 10.0
}, {
"frames": [ SubResource( 88 ), SubResource( 89 ), SubResource( 90 ), SubResource( 91 ), SubResource( 92 ), SubResource( 93 ) ],
"loop": true,
"name": "walk",
"speed": 10.0
} ]
[sub_resource type="RectangleShape2D" id=74]
extents = Vector2( 12, 18.5 )
[sub_resource type="RectangleShape2D" id=95]
extents = Vector2( 9, 16.5 )
[node name="Enemy" type="KinematicBody2D"]
collision_layer = 4
script = ExtResource( 1 )
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
position = Vector2( 8, -8 )
frames = SubResource( 94 )
animation = "idle"
playing = true
flip_h = true
__meta__ = {
"_aseprite_wizard_config_": {
"layer": "",
"o_ex_p": "",
"o_folder": "res://assets",
"o_name": "",
"only_visible": true,
"op_exp": false,
"slice": "",
"source": "E:/Godot/Art/botEnemy.aseprite"
}
}
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2( -1, -3.5 )
shape = SubResource( 74 )
[node name="IdleTimeout" type="Timer" parent="."]
wait_time = 2.0
one_shot = true
[node name="PlayerDetection" type="RayCast2D" parent="."]
enabled = true
cast_to = Vector2( 20, 0 )
collision_mask = 2
[node name="HurtHitbox" type="Area2D" parent="."]
collision_layer = 160
collision_mask = 64
[node name="CollisionShape2D2" type="CollisionShape2D" parent="HurtHitbox"]
modulate = Color( 1, 0, 0, 1 )
position = Vector2( -1, -3.5 )
shape = SubResource( 95 )
[connection signal="animation_finished" from="AnimatedSprite" to="." method="_on_AnimatedSprite_animation_finished"]

76
Enemy2-KinematicBody2D.gd Normal file
View File

@ -0,0 +1,76 @@
class_name Enemy2 extends KinematicBody2D
var velocity = Vector2(0,0)
var direction = Vector2(1,0)
export var player_number: int = 1
onready var movement_animations: AnimatedSprite = $AnimatedSprite
onready var movement_state_machine: Node = $Controllers/state_machine
onready var player_move_component = $Controllers/decision_component
onready var player_hurtbox = $Hurtbox/CollisionShape2D
onready var enemy_hitbox = $Hitbox/CollisionShape2D
onready var player_detection = $PlayerDetection
onready var gun = $Gun
func _ready() -> void:
movement_state_machine.init(self, movement_animations, player_move_component)
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))
if direction.x < 0:
var t = Transform2D()
# Translation
t.origin = Vector2(gun.offset_position.x * -1, gun.offset_position.y)
gun.transform = t
player_detection.cast_to = Vector2(-20,0)
#var t2 = Transform2D.FLIP_Y
#enemy_hitbox.transform = Transform2D.FLIP_Y
$Hitbox.transform = Transform2D.FLIP_X
elif direction.x > 0:
var t = Transform2D()
# Translation
t.origin = Vector2(gun.offset_position.x, gun.offset_position.y)
gun.transform = t
player_detection.cast_to = Vector2(20,0)
#enemy_hitbox.transform = Transform2D.IDENTITY
$Hitbox.transform = Transform2D.IDENTITY
func _process(delta: float) -> void:
movement_state_machine.process_frame(delta)
player_move_component.current_state_name = movement_state_machine.current_state.name
func _on_AnimatedSprite_animation_finished():
if movement_animations.frames.get_animation_loop(movement_animations.animation) == false:
movement_state_machine.current_state.animation_index += 1
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
func set_hitbox(enabled: bool):
#player_hurtbox.disabled = enabled #nope
enemy_hitbox.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)
func _on_Hurtbox_body_entered(body):
print("Body Ouch. (Enemy)",body)
movement_state_machine.change_state($Controllers/state_machine/hurt)

257
Enemy2.tscn Normal file
View File

@ -0,0 +1,257 @@
[gd_scene load_steps=35 format=2]
[ext_resource path="res://Enemy2-KinematicBody2D.gd" type="Script" id=1]
[ext_resource path="res://src/states/enemy/fall.gd" type="Script" id=2]
[ext_resource path="res://state_machine.gd" type="Script" id=3]
[ext_resource path="res://src/states/enemy/jump.gd" type="Script" id=4]
[ext_resource path="res://src/states/enemy/move.gd" type="Script" id=5]
[ext_resource path="res://src/states/enemy/wander.gd" type="Script" id=6]
[ext_resource path="res://src/states/enemy/idle.gd" type="Script" id=7]
[ext_resource path="res://src/states/enemy/attack.gd" type="Script" id=8]
[ext_resource path="res://Gun.gd" type="Script" id=9]
[ext_resource path="res://src/states/enemy/hurt.gd" type="Script" id=10]
[ext_resource path="res://enemy_move_component.gd" type="Script" id=11]
[sub_resource type="StreamTexture" id=149]
load_path = "res://.import/botEnemy.png-46efd539a38730ff15fb4ddb087329c6.stex"
[sub_resource type="AtlasTexture" id=150]
atlas = SubResource( 149 )
region = Rect2( 192, 48, 48, 48 )
[sub_resource type="AtlasTexture" id=151]
atlas = SubResource( 149 )
region = Rect2( 0, 96, 48, 48 )
[sub_resource type="AtlasTexture" id=152]
atlas = SubResource( 149 )
region = Rect2( 48, 96, 48, 48 )
[sub_resource type="AtlasTexture" id=153]
atlas = SubResource( 149 )
region = Rect2( 96, 96, 48, 48 )
[sub_resource type="AtlasTexture" id=154]
atlas = SubResource( 149 )
region = Rect2( 144, 96, 48, 48 )
[sub_resource type="AtlasTexture" id=155]
atlas = SubResource( 149 )
region = Rect2( 0, 144, 48, 48 )
[sub_resource type="AtlasTexture" id=156]
atlas = SubResource( 149 )
region = Rect2( 48, 144, 48, 48 )
[sub_resource type="AtlasTexture" id=157]
atlas = SubResource( 149 )
region = Rect2( 96, 144, 48, 48 )
[sub_resource type="AtlasTexture" id=158]
atlas = SubResource( 149 )
region = Rect2( 192, 96, 48, 48 )
[sub_resource type="AtlasTexture" id=159]
atlas = SubResource( 149 )
region = Rect2( 0, 0, 48, 48 )
[sub_resource type="AtlasTexture" id=160]
atlas = SubResource( 149 )
region = Rect2( 48, 0, 48, 48 )
[sub_resource type="AtlasTexture" id=161]
atlas = SubResource( 149 )
region = Rect2( 96, 0, 48, 48 )
[sub_resource type="AtlasTexture" id=162]
atlas = SubResource( 149 )
region = Rect2( 144, 0, 48, 48 )
[sub_resource type="AtlasTexture" id=163]
atlas = SubResource( 149 )
region = Rect2( 192, 0, 48, 48 )
[sub_resource type="AtlasTexture" id=164]
atlas = SubResource( 149 )
region = Rect2( 0, 48, 48, 48 )
[sub_resource type="AtlasTexture" id=165]
atlas = SubResource( 149 )
region = Rect2( 48, 48, 48, 48 )
[sub_resource type="AtlasTexture" id=166]
atlas = SubResource( 149 )
region = Rect2( 96, 48, 48, 48 )
[sub_resource type="AtlasTexture" id=167]
atlas = SubResource( 149 )
region = Rect2( 144, 48, 48, 48 )
[sub_resource type="SpriteFrames" id=168]
animations = [ {
"frames": [ SubResource( 150 ), SubResource( 151 ), SubResource( 152 ), SubResource( 153 ), SubResource( 154 ) ],
"loop": true,
"name": "attack",
"speed": 10.0
}, {
"frames": [ SubResource( 155 ), SubResource( 156 ), SubResource( 157 ) ],
"loop": true,
"name": "death",
"speed": 10.0
}, {
"frames": [ SubResource( 158 ) ],
"loop": true,
"name": "hurt",
"speed": 10.0
}, {
"frames": [ SubResource( 159 ), SubResource( 160 ), SubResource( 161 ) ],
"loop": true,
"name": "idle",
"speed": 10.0
}, {
"frames": [ SubResource( 162 ), SubResource( 163 ), SubResource( 164 ), SubResource( 165 ), SubResource( 166 ), SubResource( 167 ) ],
"loop": true,
"name": "walk",
"speed": 10.0
} ]
[sub_resource type="RectangleShape2D" id=74]
extents = Vector2( 13.5, 16.5 )
[sub_resource type="RectangleShape2D" id=148]
extents = Vector2( 11.5, 14.5 )
[sub_resource type="RectangleShape2D" id=169]
extents = Vector2( 10, 3.5 )
[node name="Enemy" type="KinematicBody2D"]
collision_layer = 4
script = ExtResource( 1 )
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
position = Vector2( 8, -8 )
frames = SubResource( 168 )
animation = "idle"
frame = 2
playing = true
flip_h = true
__meta__ = {
"_aseprite_wizard_config_": {
"layer": "",
"o_ex_p": "",
"o_folder": "res://assets",
"o_name": "",
"only_visible": true,
"op_exp": false,
"slice": "",
"source": "E:/Godot/Art/botEnemy.aseprite"
}
}
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2( -0.5, -2.5 )
shape = SubResource( 74 )
[node name="Controllers" type="Node" parent="."]
[node name="state_machine" type="Node" parent="Controllers"]
script = ExtResource( 3 )
starting_state = NodePath("idle")
[node name="idle" type="Node" parent="Controllers/state_machine"]
script = ExtResource( 7 )
animation_name = "idle"
timeout_seconds = 1.0
jump_node = NodePath("../jump")
fall_node = NodePath("../fall")
fire_node = NodePath("../attack")
wander_node = NodePath("../wander")
attack_node = NodePath("../attack")
[node name="jump" type="Node" parent="Controllers/state_machine"]
script = ExtResource( 4 )
animation_name = "idle"
idle_node = NodePath("../idle")
fall_node = NodePath("../fall")
move_node = NodePath("../move")
[node name="move" type="Node" parent="Controllers/state_machine"]
script = ExtResource( 5 )
animation_name = "walk"
jump_node = NodePath("../jump")
fall_node = NodePath("../fall")
idle_node = NodePath("../idle")
[node name="wander" type="Node" parent="Controllers/state_machine"]
script = ExtResource( 6 )
animation_name = "walk"
timeout_seconds = 1.0
jump_node = NodePath("../jump")
fall_node = NodePath("../fall")
idle_node = NodePath("../idle")
attack_node = NodePath("../attack")
[node name="fall" type="Node" parent="Controllers/state_machine"]
script = ExtResource( 2 )
animation_name = "idle"
idle_node = NodePath("../idle")
move_node = NodePath("../move")
[node name="hurt" type="Node" parent="Controllers/state_machine"]
script = ExtResource( 10 )
animation_name = "hurt"
idle_node = NodePath("../idle")
[node name="attack" type="Node" parent="Controllers/state_machine"]
script = ExtResource( 8 )
animation_name = "attack"
idle_node = NodePath("../idle")
[node name="decision_component" type="Node" parent="Controllers"]
script = ExtResource( 11 )
[node name="IdleTimeout" type="Timer" parent="Controllers/decision_component"]
wait_time = 2.0
one_shot = true
autostart = true
[node name="Hurtbox" type="Area2D" parent="." groups=["enemy_hitboxes"]]
collision_layer = 160
collision_mask = 64
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hurtbox"]
self_modulate = Color( 1, 0, 0, 1 )
position = Vector2( 0, -1 )
shape = SubResource( 148 )
[node name="Gun" type="Position2D" parent="."]
physics_interpolation_mode = 1
position = Vector2( 25, -5 )
script = ExtResource( 9 )
[node name="Cooldown" type="Timer" parent="Gun"]
wait_time = 0.5
one_shot = true
[node name="Line2D" type="Line2D" parent="Gun"]
points = PoolVector2Array( -5, 0, 5, 0 )
width = 2.0
default_color = Color( 1, 0.607843, 0, 1 )
[node name="PlayerDetection" type="RayCast2D" parent="."]
enabled = true
cast_to = Vector2( 20, 0 )
collision_mask = 2
[node name="Hitbox" type="Area2D" parent="."]
collision_layer = 128
collision_mask = 0
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hitbox"]
modulate = Color( 1, 0, 0, 1 )
position = Vector2( 20, -10 )
shape = SubResource( 169 )
disabled = true
[connection signal="animation_finished" from="AnimatedSprite" to="." method="_on_AnimatedSprite_animation_finished"]
[connection signal="body_entered" from="Hurtbox" to="." method="_on_Hurtbox_body_entered"]

16
Floor.tscn Normal file
View File

@ -0,0 +1,16 @@
[gd_scene load_steps=2 format=2]
[sub_resource type="RectangleShape2D" id=1]
extents = Vector2( 135.5, 12.5 )
[node name="Floor" type="ColorRect"]
margin_left = 23.0
margin_top = 162.0
margin_right = 294.0
margin_bottom = 187.0
[node name="StaticBody2D" type="StaticBody2D" parent="."]
[node name="CollisionShape2D" type="CollisionShape2D" parent="StaticBody2D"]
position = Vector2( 135.5, 12.5 )
shape = SubResource( 1 )

47
Gun.gd Normal file
View File

@ -0,0 +1,47 @@
class_name Gun
extends Position2D
# Represents a weapon that spawns and shoots bullets.
# The Cooldown timer controls the cooldown duration between shots.
const BULLET_VELOCITY = 350
const Bullet = preload("res://Projectile.tscn")
#onready var sound_shoot = $Shoot
onready var timer = $Cooldown
onready var offset_position = Vector2(transform.origin.x, transform.origin.y)
# This method is only called by Player.gd.
func shoot(direction = 1):
#self.set_position(Vector2(position.x * direction, position.y))
#transform.x = transform.x * direction
#Transform2D.FLIP_Y
#transform.origin.x = transform.origin.x * direction
# if direction < 0:
# var t = Transform2D()
# # Translation
# t.origin = Vector2(position.x * -1, position.y)
# transform = t
# elif direction > 0:
# var t = Transform2D()
# # Translation
# t.origin = Vector2(position.x, position.y)
# transform = t
print("Fire Debug: ", direction, " Gun position: ", position, transform.origin)
# position.x = position.x * direction #shifting position before fire was unreliable
if not timer.is_stopped():
return false
var bullet = Bullet.instance()
# if (direction > 0):
# bullet.global_position = global_position
# else:
# bullet.global_position = global_position - Vector2(position.x * 2, 0)
bullet.global_position = global_position
bullet.linear_velocity = Vector2(direction * BULLET_VELOCITY, 0)
bullet.set_as_toplevel(true)
add_child(bullet)
# sound_shoot.play()
timer.start()
return true

98
KinematicBody2D-bak.gd Normal file
View File

@ -0,0 +1,98 @@
extends KinematicBody2D
enum STATE {IDLE, RUN, JUMP, FALL, HURT}
enum STATE_SECONDARY {NONE, SHOOT}
class StateMachine:
var primary = STATE.IDLE
var secondary = STATE_SECONDARY.NONE
onready var player_state = StateMachine.new()
onready var player_last_state = StateMachine.new()
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
onready var gravity = 60*9.8
onready var speed = Vector2((30*5), (gravity * 1/2))
#onready var gravity = ProjectSettings.get("physics/2d/default_gravity")
onready var _animated_sprite = $AnimatedSprite
var velocity = Vector2.ZERO
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
func get_direction():
return Vector2(
Input.get_axis("ui_left", "ui_right"),
-1 if is_on_floor() and Input.is_action_just_pressed("ui_accept") else 0
)
func calculate_move_velocity(
linear_velocity,
direction,
speed
):
var velocity = linear_velocity
velocity.x = speed.x * direction.x
if direction.y != 0.0:
velocity.y = speed.y * direction.y
return velocity
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _physics_process(delta):
var direction = get_direction()
# if not is_on_floor():
# velocity.y += gravity * delta
#
# # Handle jump.
# if Input.is_action_just_pressed("ui_accept") and is_on_floor():
# velocity.y += (gravity * -1) * delta
#
# # Get the input direction and handle the movement/deceleration.
# # As good practice, you should replace UI actions with custom gameplay actions.
# var direction = Input.get_axis("ui_left", "ui_right")
# if direction:
# velocity.x = direction * SPEED
# else:
# velocity.x = move_toward(velocity.x, 0, SPEED)
velocity = calculate_move_velocity(velocity, direction, speed)
move_and_slide(velocity, Vector2(0, -1))
# Apply Gravity
velocity.y += gravity * delta
#Animation
if direction.x > 0 and _animated_sprite.flip_h != true:
_animated_sprite.flip_h = true
if direction.x < 0 and _animated_sprite.flip_h != false:
_animated_sprite.flip_h = false
player_state.primary = STATE.IDLE
match player_state.primary:
STATE.IDLE:
if direction.y == 0:
player_state.primary = STATE.FALL
STATE.FALL:
print("Fall")
STATE.RUN:
print("Idle")
if not is_on_floor():
if _animated_sprite.animation != "jump":
_animated_sprite.play("jump")
else:
if direction and _animated_sprite.animation != "run":
print(_animated_sprite.animation, direction)
_animated_sprite.play("run")
elif not direction:
_animated_sprite.play("idle")

22
Main.gd Normal file
View File

@ -0,0 +1,22 @@
extends Node2D
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
var camera :Camera2D
# Called when the node enters the scene tree for the first time.
func _ready():
camera = $Path2D/PathFollow2D/Camera2D
camera.make_current()
for child in get_children():
print(child)
if child is Player:
camera = child.get_node("Camera2D")
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass

194
Main.tscn Normal file

File diff suppressed because one or more lines are too long

179
Player-KinematicBody2D.gd Normal file
View File

@ -0,0 +1,179 @@
class_name Player extends KinematicBody2D
var velocity = Vector2(0,0)
var direction = Vector2(0,0)
export var player_number: int = 1
onready var movement_animations: AnimatedSprite = $AnimatedSprite
onready var movement_state_machine: Node = $Controllers/state_machine
onready var player_move_component = $Controllers/move_component
onready var player_hurtbox = $Hurtbox/CollisionShape2D
onready var gun = $Gun
func _ready() -> void:
movement_state_machine.init(self, movement_animations, player_move_component)
player_move_component.player_number = player_number
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))
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
func _process(delta: float) -> void:
movement_state_machine.process_frame(delta)
PlayerInfo.player_position = global_position
func _on_AnimatedSprite_animation_finished():
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):
#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
func shoot_projectile():
var is_shooting = false
is_shooting = gun.shoot(direction.x)
#func _ready():
# # Static types are necessary here to avoid warnings.
# var camera: Camera2D = $Camera2D
# camera.custom_viewport = $"../.."
# yield(get_tree(), "idle_frame")
# camera.make_current()
#
#func _physics_process(delta):
# # Horizontal movement
# velocity.x = (Input.get_axis("ui_left", "ui_right") * WALK_MAX_SPEED)
#
# # Vertical movement code. Apply gravity.
# velocity.y += gravity * delta
#
# # Move based on the velocity and snap to the ground.
# #velocity = move_and_slide_with_snap(velocity, Vector2.DOWN, Vector2.UP)
# velocity = move_and_slide(velocity, Vector2(0, -1))
#
# # Check for jumping. is_on_floor() must be called after movement code.
# # Apply Jump velocity
# if is_on_floor() and Input.is_action_just_pressed("ui_accept"):
# velocity.y = -JUMP_SPEED
#
# # Animate based on last state and velocity
# if velocity.x > 0 and _animated_sprite.flip_h != true:
# _animated_sprite.flip_h = true
# if velocity.x < 0 and _animated_sprite.flip_h != false:
# _animated_sprite.flip_h = false
#
# # forced state changes like falling an gitting hurt
# if velocity.y > 0 and player_state != STATE.JUMP and player_state != STATE.FALL:
# print("STATE_TRANSITION: Fall")
# player_state = STATE.FALL
#
#
# # Each state should trigger its own animation
# match player_state:
# STATE.IDLE:
# # Transitions
# if velocity.y == -JUMP_SPEED:
# print("STATE_TRANSITION: Jump")
# player_last_state = STATE.IDLE
# player_state = STATE.JUMP
# elif velocity.x != 0:
# print("STATE_TRANSITION: Run")
# player_last_state = STATE.IDLE
# player_state = STATE.RUN
# # Animation
# if player_last_state != STATE.IDLE:
# $IdleTimeout.start()
# _animated_sprite.play("idle")
# player_last_state = STATE.IDLE
# if $IdleTimeout.time_left == 0 and _animated_sprite.animation != 'blink':
# _animated_sprite.play("blink")
# animation_play_finished = false
# if $IdleTimeout.time_left == 0 and animation_play_finished == true:
# $IdleTimeout.start()
# _animated_sprite.play("idle")
# print("blink over")
#
# STATE.JUMP:
# # Transitions
# if is_on_floor():
# print("STATE_TRANSITION: Idle")
# _animated_sprite.play("idle")
# player_last_state = STATE.JUMP
# player_state = STATE.IDLE
# # Animation
# if player_last_state != STATE.JUMP:
# _animated_sprite.play("jump")
# player_last_state = STATE.JUMP
#
# STATE.FALL:
# # Transitions
# if is_on_floor():
# print("STATE_TRANSITION: Idle")
# _animated_sprite.play("idle")
# player_last_state = STATE.FALL
# player_state = STATE.IDLE
# # Animation
# if player_last_state != STATE.FALL:
# _animated_sprite.animation = "jump"
# _animated_sprite.frame = 8
# _animated_sprite.stop()
# player_last_state = STATE.FALL
#
# STATE.RUN:
# # print (_animated_sprite.animation ) # apparentl playing doesn't stop when loop is disabled.
# # Transitions
# if velocity.y == -JUMP_SPEED:
# print("STATE_TRANSITION: Jump")
# _animated_sprite.play("jump")
# player_last_state = STATE.RUN
# player_state = STATE.JUMP
# elif velocity.x == 0:
# print("STATE_TRANSITION: Idle")
# _animated_sprite.play("idle")
# player_last_state = STATE.RUN
# player_state = STATE.IDLE
# # Animation
# if player_last_state == STATE.IDLE:
# _animated_sprite.play("step")
# animation_play_finished = false
# player_last_state = STATE.RUN
# elif animation_play_finished == true:
# _animated_sprite.play("run")
# animation_play_finished = false
#
#
#func _on_AnimatedSprite_animation_finished():
# animation_play_finished = true
# print($AnimatedSprite.animation," anim over ", $IdleTimeout.time_left, animation_play_finished)

512
Player.tscn Normal file
View File

@ -0,0 +1,512 @@
[gd_scene load_steps=86 format=2]
[ext_resource path="res://Player-KinematicBody2D.gd" type="Script" id=1]
[ext_resource path="res://idle.gd" type="Script" id=2]
[ext_resource path="res://state_machine.gd" type="Script" id=3]
[ext_resource path="res://fall.gd" type="Script" id=4]
[ext_resource path="res://move.gd" type="Script" id=5]
[ext_resource path="res://player_move_component.gd" type="Script" id=6]
[ext_resource path="res://jump.gd" type="Script" id=7]
[ext_resource path="res://hurt.gd" type="Script" id=8]
[ext_resource path="res://Gun.gd" type="Script" id=9]
[ext_resource path="res://fire.gd" type="Script" id=10]
[sub_resource type="StreamTexture" id=75]
load_path = "res://.import/MegaMan.png-dc2c293e5a0f5d183ee961942ac90e4a.stex"
[sub_resource type="AtlasTexture" id=76]
atlas = SubResource( 75 )
region = Rect2( 256, 64, 64, 64 )
[sub_resource type="AtlasTexture" id=77]
atlas = SubResource( 75 )
region = Rect2( 384, 64, 64, 64 )
[sub_resource type="AtlasTexture" id=78]
atlas = SubResource( 75 )
region = Rect2( 448, 64, 64, 64 )
[sub_resource type="AtlasTexture" id=79]
atlas = SubResource( 75 )
region = Rect2( 320, 256, 64, 64 )
[sub_resource type="AtlasTexture" id=80]
atlas = SubResource( 75 )
region = Rect2( 384, 256, 64, 64 )
[sub_resource type="AtlasTexture" id=81]
atlas = SubResource( 75 )
region = Rect2( 448, 256, 64, 64 )
[sub_resource type="AtlasTexture" id=82]
atlas = SubResource( 75 )
region = Rect2( 512, 256, 64, 64 )
[sub_resource type="AtlasTexture" id=83]
atlas = SubResource( 75 )
region = Rect2( 0, 320, 64, 64 )
[sub_resource type="AtlasTexture" id=84]
atlas = SubResource( 75 )
region = Rect2( 64, 320, 64, 64 )
[sub_resource type="AtlasTexture" id=85]
atlas = SubResource( 75 )
region = Rect2( 128, 320, 64, 64 )
[sub_resource type="AtlasTexture" id=86]
atlas = SubResource( 75 )
region = Rect2( 320, 128, 64, 64 )
[sub_resource type="AtlasTexture" id=87]
atlas = SubResource( 75 )
region = Rect2( 384, 128, 64, 64 )
[sub_resource type="AtlasTexture" id=88]
atlas = SubResource( 75 )
region = Rect2( 448, 128, 64, 64 )
[sub_resource type="AtlasTexture" id=89]
atlas = SubResource( 75 )
region = Rect2( 256, 384, 64, 64 )
[sub_resource type="AtlasTexture" id=90]
atlas = SubResource( 75 )
region = Rect2( 320, 384, 64, 64 )
[sub_resource type="AtlasTexture" id=91]
atlas = SubResource( 75 )
region = Rect2( 384, 384, 64, 64 )
[sub_resource type="AtlasTexture" id=92]
atlas = SubResource( 75 )
region = Rect2( 448, 384, 64, 64 )
[sub_resource type="AtlasTexture" id=93]
atlas = SubResource( 75 )
region = Rect2( 64, 0, 64, 64 )
[sub_resource type="AtlasTexture" id=94]
atlas = SubResource( 75 )
region = Rect2( 512, 320, 64, 64 )
[sub_resource type="AtlasTexture" id=95]
atlas = SubResource( 75 )
region = Rect2( 0, 384, 64, 64 )
[sub_resource type="AtlasTexture" id=96]
atlas = SubResource( 75 )
region = Rect2( 64, 384, 64, 64 )
[sub_resource type="AtlasTexture" id=97]
atlas = SubResource( 75 )
region = Rect2( 128, 384, 64, 64 )
[sub_resource type="AtlasTexture" id=98]
atlas = SubResource( 75 )
region = Rect2( 192, 384, 64, 64 )
[sub_resource type="AtlasTexture" id=99]
atlas = SubResource( 75 )
region = Rect2( 0, 192, 64, 64 )
[sub_resource type="AtlasTexture" id=100]
atlas = SubResource( 75 )
region = Rect2( 192, 320, 64, 64 )
[sub_resource type="AtlasTexture" id=101]
atlas = SubResource( 75 )
region = Rect2( 256, 320, 64, 64 )
[sub_resource type="AtlasTexture" id=102]
atlas = SubResource( 75 )
region = Rect2( 320, 320, 64, 64 )
[sub_resource type="AtlasTexture" id=103]
atlas = SubResource( 75 )
region = Rect2( 384, 320, 64, 64 )
[sub_resource type="AtlasTexture" id=104]
atlas = SubResource( 75 )
region = Rect2( 448, 320, 64, 64 )
[sub_resource type="AtlasTexture" id=105]
atlas = SubResource( 75 )
region = Rect2( 128, 64, 64, 64 )
[sub_resource type="AtlasTexture" id=106]
atlas = SubResource( 75 )
region = Rect2( 192, 64, 64, 64 )
[sub_resource type="AtlasTexture" id=107]
atlas = SubResource( 75 )
region = Rect2( 320, 64, 64, 64 )
[sub_resource type="AtlasTexture" id=108]
atlas = SubResource( 75 )
region = Rect2( 128, 0, 64, 64 )
[sub_resource type="AtlasTexture" id=109]
atlas = SubResource( 75 )
region = Rect2( 192, 0, 64, 64 )
[sub_resource type="AtlasTexture" id=110]
atlas = SubResource( 75 )
region = Rect2( 256, 0, 64, 64 )
[sub_resource type="AtlasTexture" id=111]
atlas = SubResource( 75 )
region = Rect2( 320, 0, 64, 64 )
[sub_resource type="AtlasTexture" id=112]
atlas = SubResource( 75 )
region = Rect2( 384, 0, 64, 64 )
[sub_resource type="AtlasTexture" id=113]
atlas = SubResource( 75 )
region = Rect2( 448, 0, 64, 64 )
[sub_resource type="AtlasTexture" id=114]
atlas = SubResource( 75 )
region = Rect2( 512, 0, 64, 64 )
[sub_resource type="AtlasTexture" id=115]
atlas = SubResource( 75 )
region = Rect2( 0, 64, 64, 64 )
[sub_resource type="AtlasTexture" id=116]
atlas = SubResource( 75 )
region = Rect2( 64, 64, 64, 64 )
[sub_resource type="AtlasTexture" id=117]
atlas = SubResource( 75 )
region = Rect2( 64, 192, 64, 64 )
[sub_resource type="AtlasTexture" id=118]
atlas = SubResource( 75 )
region = Rect2( 128, 192, 64, 64 )
[sub_resource type="AtlasTexture" id=119]
atlas = SubResource( 75 )
region = Rect2( 192, 192, 64, 64 )
[sub_resource type="AtlasTexture" id=120]
atlas = SubResource( 75 )
region = Rect2( 256, 192, 64, 64 )
[sub_resource type="AtlasTexture" id=121]
atlas = SubResource( 75 )
region = Rect2( 320, 192, 64, 64 )
[sub_resource type="AtlasTexture" id=122]
atlas = SubResource( 75 )
region = Rect2( 384, 192, 64, 64 )
[sub_resource type="AtlasTexture" id=123]
atlas = SubResource( 75 )
region = Rect2( 448, 192, 64, 64 )
[sub_resource type="AtlasTexture" id=124]
atlas = SubResource( 75 )
region = Rect2( 512, 192, 64, 64 )
[sub_resource type="AtlasTexture" id=125]
atlas = SubResource( 75 )
region = Rect2( 0, 256, 64, 64 )
[sub_resource type="AtlasTexture" id=126]
atlas = SubResource( 75 )
region = Rect2( 128, 448, 64, 64 )
[sub_resource type="AtlasTexture" id=127]
atlas = SubResource( 75 )
region = Rect2( 192, 448, 64, 64 )
[sub_resource type="AtlasTexture" id=128]
atlas = SubResource( 75 )
region = Rect2( 256, 448, 64, 64 )
[sub_resource type="AtlasTexture" id=129]
atlas = SubResource( 75 )
region = Rect2( 320, 448, 64, 64 )
[sub_resource type="AtlasTexture" id=130]
atlas = SubResource( 75 )
region = Rect2( 384, 448, 64, 64 )
[sub_resource type="AtlasTexture" id=131]
atlas = SubResource( 75 )
region = Rect2( 448, 448, 64, 64 )
[sub_resource type="AtlasTexture" id=132]
atlas = SubResource( 75 )
region = Rect2( 0, 0, 64, 64 )
[sub_resource type="AtlasTexture" id=133]
atlas = SubResource( 75 )
region = Rect2( 512, 128, 64, 64 )
[sub_resource type="AtlasTexture" id=134]
atlas = SubResource( 75 )
region = Rect2( 512, 384, 64, 64 )
[sub_resource type="AtlasTexture" id=135]
atlas = SubResource( 75 )
region = Rect2( 0, 448, 64, 64 )
[sub_resource type="AtlasTexture" id=136]
atlas = SubResource( 75 )
region = Rect2( 64, 448, 64, 64 )
[sub_resource type="AtlasTexture" id=137]
atlas = SubResource( 75 )
region = Rect2( 512, 64, 64, 64 )
[sub_resource type="AtlasTexture" id=138]
atlas = SubResource( 75 )
region = Rect2( 0, 128, 64, 64 )
[sub_resource type="AtlasTexture" id=139]
atlas = SubResource( 75 )
region = Rect2( 64, 128, 64, 64 )
[sub_resource type="AtlasTexture" id=140]
atlas = SubResource( 75 )
region = Rect2( 128, 128, 64, 64 )
[sub_resource type="AtlasTexture" id=141]
atlas = SubResource( 75 )
region = Rect2( 192, 128, 64, 64 )
[sub_resource type="AtlasTexture" id=142]
atlas = SubResource( 75 )
region = Rect2( 256, 128, 64, 64 )
[sub_resource type="AtlasTexture" id=143]
atlas = SubResource( 75 )
region = Rect2( 64, 256, 64, 64 )
[sub_resource type="AtlasTexture" id=144]
atlas = SubResource( 75 )
region = Rect2( 128, 256, 64, 64 )
[sub_resource type="AtlasTexture" id=145]
atlas = SubResource( 75 )
region = Rect2( 192, 256, 64, 64 )
[sub_resource type="AtlasTexture" id=146]
atlas = SubResource( 75 )
region = Rect2( 256, 256, 64, 64 )
[sub_resource type="SpriteFrames" id=147]
animations = [ {
"frames": [ SubResource( 76 ), SubResource( 77 ), SubResource( 78 ) ],
"loop": true,
"name": "blink",
"speed": 10.0
}, {
"frames": [ SubResource( 79 ), SubResource( 80 ), SubResource( 81 ), SubResource( 82 ) ],
"loop": true,
"name": "climb",
"speed": 10.0
}, {
"frames": [ SubResource( 83 ), SubResource( 84 ) ],
"loop": true,
"name": "climb_end",
"speed": 10.0
}, {
"frames": [ SubResource( 85 ) ],
"loop": true,
"name": "climb_fire",
"speed": 10.0
}, {
"frames": [ SubResource( 86 ), SubResource( 87 ), SubResource( 88 ), SubResource( 86 ) ],
"loop": true,
"name": "fire",
"speed": 10.0
}, {
"frames": [ SubResource( 89 ), SubResource( 90 ), SubResource( 89 ), SubResource( 91 ), SubResource( 92 ) ],
"loop": true,
"name": "hit",
"speed": 10.0
}, {
"frames": [ SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 76 ), SubResource( 77 ), SubResource( 78 ) ],
"loop": true,
"name": "idle",
"speed": 10.0
}, {
"frames": [ SubResource( 93 ), SubResource( 94 ), SubResource( 95 ), SubResource( 96 ), SubResource( 97 ), SubResource( 98 ), SubResource( 98 ), SubResource( 97 ), SubResource( 96 ), SubResource( 95 ), SubResource( 94 ), SubResource( 93 ) ],
"loop": true,
"name": "jump",
"speed": 10.0
}, {
"frames": [ SubResource( 99 ), SubResource( 100 ), SubResource( 101 ), SubResource( 102 ), SubResource( 103 ), SubResource( 104 ) ],
"loop": true,
"name": "jump_fire",
"speed": 10.0
}, {
"frames": [ SubResource( 105 ), SubResource( 106 ), SubResource( 105 ), SubResource( 76 ), SubResource( 107 ) ],
"loop": true,
"name": "look",
"speed": 10.0
}, {
"frames": [ SubResource( 93 ), SubResource( 108 ), SubResource( 109 ), SubResource( 110 ), SubResource( 111 ), SubResource( 112 ), SubResource( 113 ), SubResource( 114 ), SubResource( 115 ), SubResource( 116 ) ],
"loop": true,
"name": "run",
"speed": 10.0
}, {
"frames": [ SubResource( 99 ), SubResource( 117 ), SubResource( 118 ), SubResource( 119 ), SubResource( 120 ), SubResource( 121 ), SubResource( 122 ), SubResource( 123 ), SubResource( 124 ), SubResource( 125 ) ],
"loop": true,
"name": "run_fire",
"speed": 10.0
}, {
"frames": [ SubResource( 126 ), SubResource( 127 ), SubResource( 126 ), SubResource( 128 ) ],
"loop": true,
"name": "slide",
"speed": 10.0
}, {
"frames": [ SubResource( 129 ), SubResource( 130 ), SubResource( 131 ) ],
"loop": true,
"name": "slide_hit",
"speed": 10.0
}, {
"frames": [ SubResource( 132 ) ],
"loop": false,
"name": "step",
"speed": 10.0
}, {
"frames": [ SubResource( 133 ) ],
"loop": true,
"name": "stepfire",
"speed": 10.0
}, {
"frames": [ SubResource( 134 ), SubResource( 135 ), SubResource( 136 ), SubResource( 135 ) ],
"loop": true,
"name": "stun",
"speed": 10.0
}, {
"frames": [ SubResource( 137 ), SubResource( 138 ), SubResource( 139 ), SubResource( 140 ), SubResource( 141 ), SubResource( 142 ) ],
"loop": true,
"name": "teleport",
"speed": 10.0
}, {
"frames": [ SubResource( 143 ), SubResource( 144 ), SubResource( 145 ), SubResource( 146 ) ],
"loop": true,
"name": "throw",
"speed": 10.0
} ]
[sub_resource type="RectangleShape2D" id=74]
extents = Vector2( 14, 18.5 )
[sub_resource type="RectangleShape2D" id=148]
extents = Vector2( 11.5, 14.5 )
[node name="Player" type="KinematicBody2D"]
collision_layer = 2
script = ExtResource( 1 )
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
frames = SubResource( 147 )
animation = "idle"
frame = 6
playing = true
flip_h = true
__meta__ = {
"_aseprite_wizard_config_": {
"layer": "",
"o_ex_p": "",
"o_folder": "res://assets",
"o_name": "",
"only_visible": true,
"op_exp": false,
"slice": "",
"source": "E:/Godot/Art/MegaMan.aseprite"
}
}
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2( 0, -3.5 )
shape = SubResource( 74 )
[node name="Controllers" type="Node" parent="."]
[node name="state_machine" type="Node" parent="Controllers"]
script = ExtResource( 3 )
starting_state = NodePath("idle")
[node name="idle" type="Node" parent="Controllers/state_machine"]
script = ExtResource( 2 )
animation_name = "idle"
move_speed = 90.0
jump_node = NodePath("../jump")
fall_node = NodePath("../fall")
move_node = NodePath("../move")
fire_node = NodePath("../fire")
[node name="jump" type="Node" parent="Controllers/state_machine"]
script = ExtResource( 7 )
animation_name = "jump"
move_speed = 90.0
idle_node = NodePath("../idle")
fall_node = NodePath("../fall")
move_node = NodePath("../move")
jump_force = 270.0
[node name="move" type="Node" parent="Controllers/state_machine"]
script = ExtResource( 5 )
move_speed = 90.0
animation_sequence = [ "step", "run" ]
jump_node = NodePath("../jump")
fall_node = NodePath("../fall")
idle_node = NodePath("../idle")
dash_node = NodePath(".")
[node name="fall" type="Node" parent="Controllers/state_machine"]
script = ExtResource( 4 )
animation_name = "jump"
move_speed = 90.0
idle_node = NodePath("../idle")
move_node = NodePath("../move")
[node name="hurt" type="Node" parent="Controllers/state_machine"]
script = ExtResource( 8 )
animation_name = "hit"
move_speed = -25.0
timeout_seconds = 1.0
idle_node = NodePath("../idle")
[node name="fire" type="Node" parent="Controllers/state_machine"]
script = ExtResource( 10 )
animation_name = "fire"
timeout_seconds = 1.0
idle_node = NodePath("../idle")
[node name="move_component" type="Node" parent="Controllers"]
script = ExtResource( 6 )
[node name="Hurtbox" type="Area2D" parent="."]
collision_layer = 16
collision_mask = 128
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hurtbox"]
self_modulate = Color( 1, 0, 0, 1 )
position = Vector2( 0, -4 )
shape = SubResource( 148 )
[node name="Gun" type="Position2D" parent="."]
physics_interpolation_mode = 1
position = Vector2( 25, -5 )
script = ExtResource( 9 )
[node name="Cooldown" type="Timer" parent="Gun"]
wait_time = 0.5
one_shot = true
[node name="Line2D" type="Line2D" parent="Gun"]
points = PoolVector2Array( -5, 0, 5, 0 )
width = 2.0
default_color = Color( 1, 0.607843, 0, 1 )
[connection signal="animation_finished" from="AnimatedSprite" to="." method="_on_AnimatedSprite_animation_finished"]
[connection signal="area_entered" from="Hurtbox" to="." method="_on_Hurtbox_area_entered"]

95
Position2D.gd Normal file
View File

@ -0,0 +1,95 @@
extends Position2D
export(String) var LINE_COLOR_HEX = '#FFEB3B'
var grid_position = Vector2()
var grid_size = Vector2()
var t = 0.0
onready var parent = get_node("../Player")
#onready var parent = $Player
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)
#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()
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)
#func _draw():
# var color = Color(LINE_COLOR_HEX)
# draw_line( $Left.position, $Left.cast_to, color, 3.0)
# draw_line( Vector2(0,0), Vector2(200,200), color, 3.0)
func update_grid_position():
var new_grid_position = calculate_grid_position()
# if $Left.is_colliding():
# print("Oh God! No!")
# if grid_position == new_grid_position:
# return
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():
# this needs to heavily round off the parents position
var x_offset = floor(parent.position.x / grid_size.x)
var y_offset = floor(parent.position.y / grid_size.y)
var x = round(x_offset)
#var x = (((grid_position.x * grid_size.x) + ((grid_position.x + 1) * grid_size.x))/2)
var y = round(y_offset)
#var y = round(parent.position.y / grid_size.y)
return Vector2(x, y)
func jump_to_grid_position():
#var x_pos = (((grid_position.x * grid_size.x) + ((grid_position.x + 1) * grid_size.x))/2)
# rounding or flooring position seems to just cause a lot of jitter
var x_pos = (parent.position.x - grid_size.x/2)
# if (x_pos - grid_size.x/2) < 0:
# x_pos = grid_size.x/2
# if x_pos < 0:
# x_pos = 0
if $Left.is_colliding():
#print("Oh God! No! ", $Left.get_collision_point().x, $Left.global_position)
$Camera2D.limit_left = $Left.get_collision_point().x
# attempts to just change the position to the collision point created a
# ghosting behavior, now I just set the limit of the camera to the point
#x_pos = $Left.get_collision_point().x+1
#position = Vector2($Left.get_collision_point().x+1, grid_position.y * grid_size.y)
else:
$Camera2D.limit_left = -10000000
if $Right.is_colliding():
print("Oh God! No! ", $Right.get_collision_point().x, $Right.global_position)
$Camera2D.limit_right = $Right.get_collision_point().x
else:
$Camera2D.limit_right = 10000000
position = Vector2( x_pos ,grid_position.y * grid_size.y)
#$Camera2D.force_update_scroll()
#position = Vector2( grid_position * grid_size)
#print("Camera Move: ",grid_position, position)
#func _physics_process(delta):
#
# $Sprite2D.position = $A.position.lerp($B.position, t)

18
Projectile.gd Normal file
View File

@ -0,0 +1,18 @@
extends RigidBody2D
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
# Called when the node enters the scene tree for the first time.
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
if $Timer.time_left == 0:
queue_free()
func _on_Projectile_body_entered(body):
queue_free()

36
Projectile.tscn Normal file
View File

@ -0,0 +1,36 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://assets/bullet.png" type="Texture" id=1]
[ext_resource path="res://Projectile.gd" type="Script" id=2]
[sub_resource type="SpriteFrames" id=1]
animations = [ {
"frames": [ ExtResource( 1 ) ],
"loop": true,
"name": "default",
"speed": 5.0
} ]
[sub_resource type="CircleShape2D" id=2]
radius = 4.0
[node name="Projectile" type="RigidBody2D"]
collision_layer = 64
collision_mask = 33
gravity_scale = 0.0
contacts_reported = 2
contact_monitor = true
script = ExtResource( 2 )
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
frames = SubResource( 1 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource( 2 )
[node name="Timer" type="Timer" parent="."]
wait_time = 3.0
one_shot = true
autostart = true
[connection signal="body_entered" from="." to="." method="_on_Projectile_body_entered"]

BIN
Smiley.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

35
Smiley.png.import Normal file
View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/Smiley.png-21025cc2924b94a90cc7095293287091.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Smiley.png"
dest_files=[ "res://.import/Smiley.png-21025cc2924b94a90cc7095293287091.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
assets/MegaMan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

35
assets/MegaMan.png.import Normal file
View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/MegaMan.png-dc2c293e5a0f5d183ee961942ac90e4a.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/MegaMan.png"
dest_files=[ "res://.import/MegaMan.png-dc2c293e5a0f5d183ee961942ac90e4a.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/Assets.png-f03a88d0aba2c7e14cf1d8ccdd16c54e.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/Tiles/Assets/Assets.png"
dest_files=[ "res://.import/Assets.png-f03a88d0aba2c7e14cf1d8ccdd16c54e.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/Background_1.png-600dd5a1e98ec11e29cfe251fc823b28.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/Tiles/Assets/Background_1.png"
dest_files=[ "res://.import/Background_1.png-600dd5a1e98ec11e29cfe251fc823b28.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/Background_2.png-cbaf6c4c26cf00b90452d6cbf7c69b70.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/Tiles/Assets/Background_2.png"
dest_files=[ "res://.import/Background_2.png-cbaf6c4c26cf00b90452d6cbf7c69b70.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View File

@ -0,0 +1,11 @@
all the assets here are totally free for commercial use and the like.
credits are optional but appreciated.
if there is any change of shape or color, no credit shall be given to the original creator (I)
characters, monsters as well as boss and other types of creatures will be distributed exclusively to patron's subscribers above 5 dollars
the patreon: https://www.patreon.com/Anokolisa
each month two new packages are distributed to patreons above 3 dollars

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 KiB

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/Assets.png-7e32500502bf22704b43171f4c163c27.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/Tiles/Social/Assets.png"
dest_files=[ "res://.import/Assets.png-7e32500502bf22704b43171f4c163c27.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/Mine.png-8b11efea6fd046fa6c9da946e8741d9c.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/Tiles/Social/Mine.png"
dest_files=[ "res://.import/Mine.png-8b11efea6fd046fa6c9da946e8741d9c.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/entrance.png-1d00c022b610d166b8cdaa56ef893a27.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/Tiles/Social/entrance.png"
dest_files=[ "res://.import/entrance.png-1d00c022b610d166b8cdaa56ef893a27.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/trees.png-e262d7dea8f1c2c97d5cab0a124f6a24.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/Tiles/Social/trees.png"
dest_files=[ "res://.import/trees.png-e262d7dea8f1c2c97d5cab0a124f6a24.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
assets/botEnemy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/botEnemy.png-46efd539a38730ff15fb4ddb087329c6.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/botEnemy.png"
dest_files=[ "res://.import/botEnemy.png-46efd539a38730ff15fb4ddb087329c6.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
assets/bullet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

35
assets/bullet.png.import Normal file
View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/bullet.png-c68d06721d4ad8b0013707b0a51654af.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/bullet.png"
dest_files=[ "res://.import/bullet.png-c68d06721d4ad8b0013707b0a51654af.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

45
dash.gd Normal file
View File

@ -0,0 +1,45 @@
# You could also declare a class_name for the move state
# so you don't have to reference the script directly
extends 'res://src/state_machine/states/move.gd'
@export
var move_state: State
@export
var time_to_dash := 0.5
var dash_timer := 0.0
var direction := 1.0
func enter() -> void:
super()
dash_timer = time_to_dash
# Simple check for which direction to dash towards
if animations.flip_h:
direction = -1
else:
direction = 1
# Just to be safe, disable any other inputs
func process_input(event: InputEvent) -> State:
return null
func process_physics(delta: float) -> State:
dash_timer -= delta
if dash_timer <= 0.0:
# Fall back on the default input implementation to
# determine where to go next
if super.get_movement_input() != 0.0:
return move_state
return idle_state
# At this point, run 'process_physics' in the move script as written
return super(delta)
# Override movement inputs
func get_movement_input() -> float:
return direction
func get_jump() -> bool:
return false

7
default_env.tres Normal file
View File

@ -0,0 +1,7 @@
[gd_resource type="Environment" load_steps=2 format=2]
[sub_resource type="ProceduralSky" id=1]
[resource]
background_mode = 2
background_sky = SubResource( 1 )

46
enemy_move_component.gd Normal file
View File

@ -0,0 +1,46 @@
extends Node
export var flipped_sprite: bool = true
onready var idle_timeout = $IdleTimeout
var desired_movement_vector: Vector2
var flip_flop = false
var wandering = false
var current_state_name: String = ""
# 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 Input.get_axis('move_left', 'move_right')
if current_state_name == "idle" and idle_timeout.time_left == 0:
if flip_flop:
flip_flop = false
desired_movement_vector.x = 1.0
idle_timeout.start()
else:
flip_flop = true
desired_movement_vector.x = -1.0
idle_timeout.start()
if current_state_name == "move" and idle_timeout.time_left == 0:
idle_timeout.start()
desired_movement_vector.x = 0.0
return 0.0
# Return a boolean indicating if the character wants to jump
func wants_jump() -> bool:
return false
# if Input.is_action_just_pressed("jump_" + str(player_number)):
# desired_movement_vector.y = 1
# return true
# else:
# return false
# Return a boolean indicating if the character wants to jump
func wants_shoot() -> bool:
# if Input.is_action_just_pressed("shoot_" + str(player_number)):
# return true
# else:
# return false
return false

42
fall.gd Normal file
View File

@ -0,0 +1,42 @@
extends State
export (NodePath) var idle_node
export (NodePath) var move_node
onready var idle_state: State = get_node(idle_node)
onready var move_state: State = get_node(move_node)
func enter() -> void:
.enter()
animations.frame = 6
func process_input(_event: InputEvent) -> 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:
# parent.direction.x = parent.velocity.x
if parent.velocity.x > 0:
parent.direction.x = 1
elif parent.velocity.x < 0:
parent.direction.x = -1
if move_component.flipped_sprite == true:
animations.flip_h = parent.direction.x > 0
else:
animations.flip_h = parent.direction.x < 0
if parent.is_on_floor():
if parent.velocity.x == 0:
return move_state
return idle_state
return null

47
fire.gd Normal file
View File

@ -0,0 +1,47 @@
extends State
export (NodePath) var idle_node
onready var idle_state: State = get_node(idle_node)
var can_fire = true
func enter() -> void:
.enter()
parent.set_hurtbox(false)
state_timeout.start()
can_fire = true
func process_input(_event: InputEvent) -> State:
# if move_component.get_movement_direction() != 0.0:
# return move_state
# move_component.wants_jump()
move_component.get_movement_direction()
# if Input.is_action_just_pressed('dash'):
# return dash_state
return null
func process_frame(delta: float) -> State:
if state_timeout.time_left == 0:
return idle_state
return null
func process_physics(delta: float) -> State:
if can_fire: # trying to do this in the physics because irrecular behavior
parent.shoot_projectile()
can_fire = false
parent.velocity.y += gravity * delta
parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
# if move_component.flipped_sprite == true:
# animations.flip_h = parent.direction.x > 0
# else:
# animations.flip_h = parent.direction.x < 0
return null

36
hurt.gd Normal file
View File

@ -0,0 +1,36 @@
extends State
export (NodePath) var idle_node
onready var idle_state: State = get_node(idle_node)
func enter() -> void:
.enter()
parent.velocity.x = 0
parent.set_hurtbox(false)
#TODO: Error check if timer was actually instanced
state_timeout.start()
func process_input(_event: InputEvent) -> State:
# move_component.wants_jump()
move_component.get_movement_direction()
return null
func process_frame(delta: float) -> State:
if state_timeout.time_left == 0:
return idle_state
return null
func process_physics(delta: float) -> State:
parent.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))
return null

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

35
icon.png.import Normal file
View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.png"
dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

47
idle.gd Normal file
View File

@ -0,0 +1,47 @@
extends State
export (NodePath) var jump_node
export (NodePath) var fall_node
export (NodePath) var move_node
export (NodePath) var fire_node
onready var jump_state: State = get_node(jump_node)
onready var fall_state: State = get_node(fall_node)
onready var move_state: State = get_node(move_node)
onready var fire_state: State = get_node(fire_node)
func enter() -> void:
.enter()
parent.set_hurtbox(true)
parent.velocity.x = 0
func process_input(_event: InputEvent) -> 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
# move_component.wants_jump()
move_component.get_movement_direction()
# if Input.is_action_just_pressed('dash'):
# return dash_state
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))
if parent.velocity.x != 0.0:
return move_state
if !parent.is_on_floor():
return fall_state
return null

47
jump.gd Normal file
View File

@ -0,0 +1,47 @@
extends State
export (NodePath) var idle_node
export (NodePath) var fall_node
export (NodePath) var move_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)
export var jump_force: float = 900.0
func enter() -> void:
.enter()
parent.velocity.y = -jump_force
func process_input(_event: InputEvent) -> State:
move_component.get_movement_direction()
return null
func process_physics(delta: float) -> State:
parent.velocity.y += gravity * delta
if parent.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))
if parent.velocity.x > 0:
parent.direction.x = 1
elif parent.velocity.x < 0:
parent.direction.x = -1
if move_component.flipped_sprite == true:
animations.flip_h = parent.direction.x > 0
else:
animations.flip_h = parent.direction.x < 0
if parent.is_on_floor():
if parent.velocity.x == 0:
return move_state
return idle_state
return null

61
move.gd Normal file
View File

@ -0,0 +1,61 @@
extends State
export (NodePath) var jump_node
export (NodePath) var fall_node
export (NodePath) var idle_node
export (NodePath) var dash_node
onready var jump_state: State = get_node(jump_node)
onready var fall_state: State = get_node(fall_node)
onready var idle_state: State = get_node(idle_node)
onready var dash_state: State = get_node(dash_node)
func process_input(_event: InputEvent) -> 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:
# if move_component.wants_jump() and parent.is_on_floor():
# return jump_state
parent.velocity.y += gravity * delta
# var movement = move_component.get_movement_direction() * move_speed
#
# # only detecting input not actual movement
# if movement == 0:
# return idle_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))
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
if move_component.flipped_sprite == true:
animations.flip_h = parent.direction.x > 0
else:
animations.flip_h = parent.direction.x < 0
# Another approach of changing state based on actual achieved velocity
# if parent.velocity.x == 0:
# return idle_state
if !parent.is_on_floor():
return fall_state
return null

32
player_move_component.gd Normal file
View File

@ -0,0 +1,32 @@
class_name Movement
extends Node
export var flipped_sprite: bool = true
export var player_number: int = 1
var desired_movement_vector: Vector2
# 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 Input.get_axis('move_left', 'move_right')
desired_movement_vector.x = Input.get_axis("move_left_" + str(player_number), "move_right_" + str(player_number))
return Input.get_axis("move_left_" + str(player_number), "move_right_" + str(player_number))
# Return a boolean indicating if the character wants to jump
func wants_jump() -> bool:
if Input.is_action_just_pressed("jump_" + str(player_number)):
desired_movement_vector.y = 1
return true
else:
return false
# Return a boolean indicating if the character wants to jump
func wants_shoot() -> bool:
if Input.is_action_just_pressed("shoot_" + str(player_number)):
return true
else:
return false

146
project.godot Normal file
View File

@ -0,0 +1,146 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=4
_global_script_classes=[ {
"base": "KinematicBody2D",
"class": "Enemy",
"language": "GDScript",
"path": "res://Enemy-KinematicBody2D.gd"
}, {
"base": "KinematicBody2D",
"class": "Enemy2",
"language": "GDScript",
"path": "res://Enemy2-KinematicBody2D.gd"
}, {
"base": "Position2D",
"class": "Gun",
"language": "GDScript",
"path": "res://Gun.gd"
}, {
"base": "Node",
"class": "Movement",
"language": "GDScript",
"path": "res://player_move_component.gd"
}, {
"base": "KinematicBody2D",
"class": "Player",
"language": "GDScript",
"path": "res://Player-KinematicBody2D.gd"
}, {
"base": "Node",
"class": "State",
"language": "GDScript",
"path": "res://state.gd"
} ]
_global_script_class_icons={
"Enemy": "",
"Enemy2": "",
"Gun": "",
"Movement": "",
"Player": "",
"State": ""
}
[application]
config/name="Mega Moves"
run/main_scene="res://Main.tscn"
config/icon="res://icon.png"
[autoload]
PlayerInfo="*res://src/singleton_autoloads/PlayerInfo.gd"
[debug]
shapes/collision/shape_color=Color( 1, 1, 1, 0.419608 )
[display]
window/size/width=320
window/size/height=180
window/size/test_width=960
window/size/test_height=540
window/stretch/mode="viewport"
window/stretch/aspect="keep"
[editor_plugins]
enabled=PoolStringArray( "res://addons/AsepriteWizard/plugin.cfg" )
[gui]
common/drop_mouse_on_gui_input_disabled=true
[input]
move_left_1={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
move_right_1={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
jump_1={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":0,"physical_scancode":32,"unicode":0,"echo":false,"script":null)
]
}
move_left_2={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
move_right_2={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
jump_2={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":74,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
shoot_1={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":77,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
shoot_2={
"deadzone": 0.5,
"events": [ ]
}
[layer_names]
2d_physics/layer_1="World"
2d_physics/layer_2="Player"
2d_physics/layer_3="Enemies"
2d_physics/layer_5="PlayerHurtbox"
2d_physics/layer_6="EnemyHurtbox"
2d_physics/layer_7="PlayerHitbox"
2d_physics/layer_8="EnemyHitbox"
[mono]
project/assembly_name="Sprite Template"
[physics]
common/enable_pause_aware_picking=true
2d/default_gravity=600
[rendering]
quality/driver/driver_name="GLES2"
environment/default_environment="res://default_env.tres"

View File

@ -0,0 +1,17 @@
extends Node
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
var player_position: Vector2
var player_health: int
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

View File

@ -0,0 +1,33 @@
extends State
export (NodePath) var idle_node
onready var idle_state: State = get_node(idle_node)
var can_fire = true
func enter() -> void:
.enter()
parent.velocity.x = 0
parent.set_hitbox(false)
func process_frame(_delta: float) -> State:
if parent.player_detection.is_colliding() == false:
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))
return null
func exit() -> void:
parent.set_hitbox(false)

42
src/states/enemy/fall.gd Normal file
View File

@ -0,0 +1,42 @@
extends State
export (NodePath) var idle_node
export (NodePath) var move_node
onready var idle_state: State = get_node(idle_node)
onready var move_state: State = get_node(move_node)
func enter() -> void:
.enter()
animations.frame = 6
func process_frame(_delta: float) -> 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:
# parent.direction.x = parent.velocity.x
if parent.velocity.x > 0:
parent.direction.x = 1
elif parent.velocity.x < 0:
parent.direction.x = -1
if move_component.flipped_sprite == true:
animations.flip_h = parent.direction.x > 0
else:
animations.flip_h = parent.direction.x < 0
if parent.is_on_floor():
if parent.velocity.x == 0:
return move_state
return idle_state
return null

34
src/states/enemy/hurt.gd Normal file
View File

@ -0,0 +1,34 @@
extends State
export (NodePath) var idle_node
onready var idle_state: State = get_node(idle_node)
func enter() -> void:
.enter()
parent.velocity.x = 0
parent.set_hurtbox(false)
state_timeout = Timer.new()
state_timeout.wait_time = 1.0
state_timeout.one_shot = true
state_timeout.autostart = true
add_child(state_timeout)
func process_frame(delta: float) -> State:
# move_component.wants_jump()
move_component.get_movement_direction()
if state_timeout.time_left == 0:
return idle_state
return null
func process_physics(delta: float) -> State:
parent.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))
return null

54
src/states/enemy/idle.gd Normal file
View File

@ -0,0 +1,54 @@
extends State
export (NodePath) var jump_node
export (NodePath) var fall_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 fall_state: State = get_node(fall_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_frame(_delta: float) -> State:
if state_timeout.time_left == 0:
return wander_state
if parent.player_detection.is_colliding():
return attack_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
#
## move_component.wants_jump()
# move_component.get_movement_direction()
# if Input.is_action_just_pressed('dash'):
# return dash_state
return null
func process_physics(delta: float) -> State:
parent.velocity.y += gravity * delta
#parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
if !parent.is_on_floor():
return fall_state
return null

47
src/states/enemy/jump.gd Normal file
View File

@ -0,0 +1,47 @@
extends State
export (NodePath) var idle_node
export (NodePath) var fall_node
export (NodePath) var move_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)
export var jump_force: float = 900.0
func enter() -> void:
.enter()
parent.velocity.y = -jump_force
func process_frame(_delta: float) -> State:
move_component.get_movement_direction()
return null
func process_physics(delta: float) -> State:
parent.velocity.y += gravity * delta
if parent.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))
if parent.velocity.x > 0:
parent.direction.x = 1
elif parent.velocity.x < 0:
parent.direction.x = -1
if move_component.flipped_sprite == true:
animations.flip_h = parent.direction.x > 0
else:
animations.flip_h = parent.direction.x < 0
if parent.is_on_floor():
if parent.velocity.x == 0:
return move_state
return idle_state
return null

64
src/states/enemy/move.gd Normal file
View File

@ -0,0 +1,64 @@
extends State
export (NodePath) var jump_node
export (NodePath) var fall_node
export (NodePath) var idle_node
onready var jump_state: State = get_node(jump_node)
onready var fall_state: State = get_node(fall_node)
onready var idle_state: State = get_node(idle_node)
func process_frame(_delta: float) -> 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:
# if move_component.wants_jump() and parent.is_on_floor():
# return jump_state
parent.velocity.y += gravity * delta
# var movement = move_component.get_movement_direction() * move_speed
#
# # only detecting input not actual movement
# if movement == 0:
# return idle_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))
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
if move_component.flipped_sprite == true:
animations.flip_h = parent.direction.x > 0
if parent.direction.x < 0:
animations.offset.x = -18
else:
animations.offset.x = 0
else:
animations.flip_h = parent.direction.x < 0
animations.offset.x = 0
# Another approach of changing state based on actual achieved velocity
# if parent.velocity.x == 0:
# return idle_state
if !parent.is_on_floor():
return fall_state
return null

View File

@ -0,0 +1,81 @@
extends State
export (NodePath) var jump_node
export (NodePath) var fall_node
export (NodePath) var idle_node
export (NodePath) var attack_node
onready var jump_state: State = get_node(jump_node)
onready var fall_state: State = get_node(fall_node)
onready var idle_state: State = get_node(idle_node)
onready var attack_state: State = get_node(attack_node)
var flip_flop = false
var move_direction_x = 1.0
func enter() -> void:
.enter()
parent.set_hurtbox(true)
state_timeout.start()
if flip_flop:
flip_flop = false
move_direction_x = 1.0
else:
flip_flop = true
move_direction_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:
# if move_component.wants_jump() and parent.is_on_floor():
# return jump_state
parent.velocity.y += gravity * delta
# var movement = move_component.get_movement_direction() * move_speed
#
# # only detecting input not actual movement
# if movement == 0:
# return idle_state
# parent.velocity.x = movement
# parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
parent.velocity.x = move_direction_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
if move_component.flipped_sprite == true:
animations.flip_h = parent.direction.x > 0
if parent.direction.x < 0:
animations.offset.x = -18
else:
animations.offset.x = 0
else:
animations.flip_h = parent.direction.x < 0
animations.offset.x = 0
if !parent.is_on_floor():
return fall_state
return null

62
state.gd Normal file
View File

@ -0,0 +1,62 @@
class_name State
extends Node
export var animation_name: String
export var move_speed: float = 60
export var timeout_seconds: float = 0.0
export(Array, String) var animation_sequence
var animation_index: int = 0
var current_animation_sequence: int = 0
var gravity: int = ProjectSettings.get_setting("physics/2d/default_gravity")
var animations: AnimatedSprite
var move_component: Node
var parent: KinematicBody2D
#var animation_sequence_timer: Timer
var state_timeout: Timer
func _ready():
if(timeout_seconds > 0.0):
state_timeout = Timer.new()
state_timeout.wait_time = timeout_seconds
state_timeout.one_shot = true
state_timeout.autostart = false
add_child(state_timeout)
func enter() -> void:
print(parent.name, " entering State: ", self.name)
if animation_name != '':
animations.play(animation_name)
elif animation_sequence.size() > 0:
animation_index = 0
current_animation_sequence = 0
animations.play(animation_sequence[animation_index])
func exit() -> void:
pass
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 animation_index >= animation_sequence.size():
animation_index = 0
animations.play(animation_sequence[animation_index])
print("An animation sequence: ", animations.animation , animation_index)
current_animation_sequence = animation_index
return null
func process_physics(_delta: float) -> State:
return null
#func get_movement_input() -> float:
# return move_component.get_movement_direction()
#
#func get_jump() -> bool:
# return move_component.wants_jump()

41
state_machine.gd Normal file
View File

@ -0,0 +1,41 @@
extends Node
export (NodePath) var starting_state
var current_state: State
# Initialize the state machine by giving each child state a reference to the
# parent object it belongs to and enter the default starting_state.
func init(parent: KinematicBody2D, animations: AnimatedSprite, move_component) -> void:
for child in get_children():
child.parent = parent
child.animations = animations
child.move_component = move_component
# Initialize to the default state
change_state(get_node(starting_state))
# Change to the new state by first calling any exit logic on the current state.
func change_state(new_state: State) -> void:
if current_state:
current_state.exit()
current_state = new_state
current_state.enter()
# Pass through functions for the Player to call,
# handling state changes as needed.
func process_physics(delta: float) -> void:
var new_state = current_state.process_physics(delta)
if new_state:
change_state(new_state)
func process_input(event: InputEvent) -> void:
var new_state = current_state.process_input(event)
if new_state:
change_state(new_state)
func process_frame(delta: float) -> void:
var new_state = current_state.process_frame(delta)
if new_state:
change_state(new_state)

61
wander.gd Normal file
View File

@ -0,0 +1,61 @@
extends State
export (NodePath) var jump_node
export (NodePath) var fall_node
export (NodePath) var idle_node
export (NodePath) var dash_node
onready var jump_state: State = get_node(jump_node)
onready var fall_state: State = get_node(fall_node)
onready var idle_state: State = get_node(idle_node)
onready var dash_state: State = get_node(dash_node)
func process_input(_event: InputEvent) -> 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:
# if move_component.wants_jump() and parent.is_on_floor():
# return jump_state
parent.velocity.y += gravity * delta
# var movement = move_component.get_movement_direction() * move_speed
#
# # only detecting input not actual movement
# if movement == 0:
# return idle_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))
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
if move_component.flipped_sprite == true:
animations.flip_h = parent.direction.x > 0
else:
animations.flip_h = parent.direction.x < 0
# Another approach of changing state based on actual achieved velocity
# if parent.velocity.x == 0:
# return idle_state
if !parent.is_on_floor():
return fall_state
return null