From c823c06188b302b9c2bedacdd80287846f3a0597 Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Sat, 7 Oct 2023 22:52:04 +0700 Subject: [PATCH] Got some wall jumping working. Created a basic FSM --- Godot/Code/Character.gd | 248 +++++++++++++++++++++++---------------- Godot/Scenes/Main.tscn | 18 ++- Godot/Scenes/Player.tscn | 2 +- 3 files changed, 163 insertions(+), 105 deletions(-) diff --git a/Godot/Code/Character.gd b/Godot/Code/Character.gd index 5538831..d6d14da 100644 --- a/Godot/Code/Character.gd +++ b/Godot/Code/Character.gd @@ -4,7 +4,7 @@ var gravity = 900 var gravity_mid = 500 var gravity_fall = 1300 const SPEED = 200.0 -const JUMP_VELOCITY = -400.0 +const JUMP_VELOCITY = -300.0 const roll_speed = 300 var roll_cooldown_time = 0.5 var colshape_stand = 30 @@ -17,6 +17,7 @@ var roll_time = 0 var roll_dir = 1 var side = 1 var state = State.Idle +var double_jump = false enum State { Idle, @@ -27,124 +28,167 @@ enum State { Land, Attack, Roll, + OnWall, } -func _physics_process(delta): +enum RState { + Grounded, + Aerial, + Combat, + Climbing +} + +# A state machine might be needed here because this is getting really messy? +# There are 4 major states; grounded, combat, aerial, climbing +var rstate = RState.Aerial + +func grounded(delta): + if land_time >= 0: + land_time -= delta + if roll_cooldown >= 0: + roll_cooldown -= delta + if roll_time >= 0: + roll_time -= delta + elif state == State.Roll: + $CollisionShape2D.shape.size.y = colshape_stand + $CollisionShape2D.position.y = colshape_stand / -2 + roll_cooldown = roll_cooldown_time + # state = State.Idle + if Input.is_action_just_pressed("attack"): - if is_on_floor(): - state = State.Attack - velocity = Vector2.ZERO - sprite.play("Attack1") + rstate = RState.Combat + return - if state == State.Attack: - await (sprite as AnimatedSprite2D).animation_finished - state = State.Idle - - else: - if not is_on_floor(): - if velocity.y > 50: - velocity.y += gravity_fall * delta - elif velocity.y < -50: - velocity.y += gravity * delta - else: - velocity.y += gravity_mid * delta - elif state == State.Jump or state == State.AirSpin: - state = State.Land - sprite.play("Land") - land_time = 0.16 + if Input.is_action_just_pressed("roll"): + if is_on_floor() and roll_time <= 0 and roll_cooldown <= 0: + # state = State.Roll + roll_time = 0.55 + roll_dir = -1 if sprite.flip_h else 1 + $CollisionShape2D.shape.size.y = colshape_stand / 2 + $CollisionShape2D.position.y = colshape_stand / -4 + sprite.play("GroundRoll") return + if Input.is_action_just_pressed("ui_accept") and state != State.Roll: + velocity.y = JUMP_VELOCITY + sprite.play("Jump") + rstate = RState.Aerial + sprite.pause() + sprite.set_frame_and_progress(0, 0) + return - if Input.is_action_just_pressed("roll"): - if is_on_floor() and roll_time <= 0 and roll_cooldown <= 0: - state = State.Roll - roll_time = 0.55 - roll_dir = -1 if sprite.flip_h else 1 - $CollisionShape2D.shape.size.y = colshape_stand / 2 - $CollisionShape2D.position.y = colshape_stand / -4 - sprite.play("GroundRoll") - if Input.is_action_just_pressed("ui_accept") and state != State.Roll: - if is_on_floor(): - velocity.y = JUMP_VELOCITY - sprite.play("Jump") - state = State.Jump - sprite.pause() - sprite.set_frame_and_progress(0, 0) - elif state != State.AirSpin: - sprite.play("AirSpin") - state = State.AirSpin - var boost = 0 if velocity.y > 0 else velocity.y / 3 - velocity.y = JUMP_VELOCITY / 1.4 + boost + # We ran off of a ledge + if not is_on_floor(): + rstate = RState.Aerial + return - if state == State.Roll: - velocity.x = roll_dir * roll_speed + if state == State.Roll: + velocity.x = roll_dir * roll_speed + else: + var speed = SPEED + if Input.is_key_pressed(KEY_SHIFT): + speed /= 3 + var direction = Input.get_axis("left", "right") + + if direction: + velocity.x = direction * speed else: - var speed = SPEED + # Decelerate + velocity.x = move_toward(velocity.x, 0, 25) + + if direction != 0: + sprite.flip_h = direction == -1 + + + if land_time <= 0: + if velocity.x != 0: if Input.is_key_pressed(KEY_SHIFT): - speed /= 3 - var direction = Input.get_axis("left", "right") - - if direction: - velocity.x = direction * speed + sprite.play("Walk") else: - # Decelerate - velocity.x = move_toward(velocity.x, 0, 25) + sprite.play("Run") + else: + sprite.play("Idle") - if direction != 0: - sprite.flip_h = direction == -1 +func aerial(delta): + if is_on_floor(): + # Transition to grounded + double_jump = false + rstate = RState.Grounded + sprite.play("Land") + land_time = 0.16 + return + + if is_on_wall(): + rstate = RState.Climbing + return - if land_time >= 0: - land_time -= delta - if roll_cooldown >= 0: - roll_cooldown -= delta - if roll_time >= 0: - roll_time -= delta - elif state == State.Roll: - $CollisionShape2D.shape.size.y = colshape_stand - $CollisionShape2D.position.y = colshape_stand / -2 - roll_cooldown = roll_cooldown_time - state = State.Idle + # if Input.is_action_just_pressed("ui_accept") and state != State.AirSpin: + if Input.is_action_just_pressed("ui_accept") and not double_jump: + sprite.play("AirSpin") + double_jump = true + # state = State.AirSpin + var boost = 0 if velocity.y > 0 else velocity.y / 3 + velocity.y = JUMP_VELOCITY / 1.4 + boost - if state == State.Jump: - if velocity.y > 50: - sprite.set_frame_and_progress(2,0) - elif velocity.y > -150: - sprite.set_frame_and_progress(1, 0) + if velocity.y > 50: + velocity.y += gravity_fall * delta + elif velocity.y < -50: + velocity.y += gravity * delta + else: + velocity.y += gravity_mid * delta - # If shift left/right then 2 * speed, play run - if land_time <= 0 and is_on_floor() and state != State.Jump and state != State.Roll: - if velocity.x != 0: - if Input.is_key_pressed(KEY_SHIFT): - sprite.play("Walk") - else: - sprite.play("Run") - else: - sprite.play("Idle") + var direction = Input.get_axis("left", "right") + if direction: + velocity.x = direction * SPEED * 0.9 + elif double_jump: + # Decelerate + velocity.x = move_toward(velocity.x, 0, 3) + else: + velocity.x = move_toward(velocity.x, 0, 9) + + if direction != 0: + sprite.flip_h = direction == -1 + + if not double_jump: + if velocity.y > 50: + sprite.set_frame_and_progress(2,0) + elif velocity.y > -150: + sprite.set_frame_and_progress(1, 0) + + +func combat(delta): + # state = State.Attack + velocity = Vector2.ZERO + sprite.play("Attack1") + await (sprite as AnimatedSprite2D).animation_finished + # state = State.Idle + rstate = RState.Grounded + +func climbing(delta): + if Input.is_action_just_pressed("ui_accept"): + rstate = RState.Aerial + velocity.x = -150 + velocity.y = -350 + return + velocity.x = 0 + velocity.y = 0 + +func _physics_process(delta): + match rstate: + RState.Grounded: + grounded(delta) + RState.Aerial: + aerial(delta) + RState.Combat: + combat(delta) + RState.Climbing: + climbing(delta) + + # if (state == State.Jump or state == State.AirSpin) and is_on_wall(): + # state = State.OnWall + # return move_and_slide() # Maybe later enum JumpState { } - -func _play_anim(state: State, velocity: Vector2): - match state: - State.Idle: - sprite.play("Idle") - State.Run: - sprite.play("Run") - State.Walk: - sprite.play("Walk") - State.Jump: - sprite.pause() - sprite.set_frame_and_progress(0, 0) - if velocity.y > 50: - sprite.set_frame_and_progress(2,0) - elif velocity.y > -150: - sprite.set_frame_and_progress(1, 0) - State.AirSpin: - pass - State.Land: - sprite.play("Land") - -func _process_velocity(state: State, delta): - pass diff --git a/Godot/Scenes/Main.tscn b/Godot/Scenes/Main.tscn index 3dd3fe8..6b18909 100644 --- a/Godot/Scenes/Main.tscn +++ b/Godot/Scenes/Main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=4 format=3 uid="uid://dr8vg4b1eh6i"] +[gd_scene load_steps=5 format=3 uid="uid://dr8vg4b1eh6i"] [ext_resource type="PackedScene" uid="uid://bjc6dwxaakqdg" path="res://Scenes/Player.tscn" id="1_ibeo8"] @@ -7,10 +7,12 @@ [sub_resource type="RectangleShape2D" id="RectangleShape2D_s46ls"] size = Vector2(500, 20) +[sub_resource type="QuadMesh" id="QuadMesh_jh5sp"] + [node name="Node2D" type="Node2D"] [node name="Player" parent="." instance=ExtResource("1_ibeo8")] -position = Vector2(251, 168) +position = Vector2(424, 202) metadata/_edit_group_ = true [node name="StaticBody2D" type="StaticBody2D" parent="."] @@ -24,6 +26,18 @@ mesh = SubResource("QuadMesh_n5vip") [node name="CollisionShape2D" type="CollisionShape2D" parent="StaticBody2D"] shape = SubResource("RectangleShape2D_s46ls") +[node name="StaticBody2D4" type="StaticBody2D" parent="."] +position = Vector2(505, 153) +scale = Vector2(0.04, 9.08) + +[node name="MeshInstance2D" type="MeshInstance2D" parent="StaticBody2D4"] +modulate = Color(0.168627, 0.678431, 0.701961, 1) +scale = Vector2(500, 20) +mesh = SubResource("QuadMesh_jh5sp") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="StaticBody2D4"] +shape = SubResource("RectangleShape2D_s46ls") + [node name="StaticBody2D2" type="StaticBody2D" parent="."] position = Vector2(331, 217) scale = Vector2(0.120002, 1) diff --git a/Godot/Scenes/Player.tscn b/Godot/Scenes/Player.tscn index 5f66aae..fd03731 100644 --- a/Godot/Scenes/Player.tscn +++ b/Godot/Scenes/Player.tscn @@ -571,7 +571,7 @@ script = ExtResource("1_23c20") texture_filter = 1 position = Vector2(0, -16) sprite_frames = SubResource("SpriteFrames_gvqqb") -animation = &"Idle" +animation = &"Attack2" autoplay = "Idle" metadata/_edit_lock_ = true