From 4b42a8ba26f21e2c6c766fa747c8b93a115a53b2 Mon Sep 17 00:00:00 2001 From: David Luevano Alvarado Date: Sun, 5 Jun 2022 09:18:35 -0600 Subject: added new tiles to ground tilemap, moved player to state machine paradigm --- src/entities/actors/snake/scenes/Head.tscn | 20 +++++- src/entities/actors/snake/scripts/dash_state.gd | 25 ++++++++ .../actors/snake/scripts/generic_segment.gd | 2 +- src/entities/actors/snake/scripts/head.gd | 61 +++++++++--------- src/entities/actors/snake/scripts/jump_state.gd | 27 ++++++++ src/entities/actors/snake/scripts/normal_state.gd | 28 +++++++++ src/entities/actors/snake/scripts/slow_state.gd | 27 ++++++++ src/entities/actors/snake/scripts/state_machine.gd | 72 ++++++++++++++++++++++ 8 files changed, 229 insertions(+), 33 deletions(-) create mode 100644 src/entities/actors/snake/scripts/dash_state.gd create mode 100644 src/entities/actors/snake/scripts/jump_state.gd create mode 100644 src/entities/actors/snake/scripts/normal_state.gd create mode 100644 src/entities/actors/snake/scripts/slow_state.gd create mode 100644 src/entities/actors/snake/scripts/state_machine.gd (limited to 'src/entities/actors') diff --git a/src/entities/actors/snake/scenes/Head.tscn b/src/entities/actors/snake/scenes/Head.tscn index a08197b..d69cbf8 100644 --- a/src/entities/actors/snake/scenes/Head.tscn +++ b/src/entities/actors/snake/scenes/Head.tscn @@ -1,8 +1,12 @@ -[gd_scene load_steps=10 format=2] +[gd_scene load_steps=14 format=2] [ext_resource path="res://entities/actors/snake/sprites/head.png" type="Texture" id=1] [ext_resource path="res://entities/actors/snake/scripts/head.gd" type="Script" id=2] [ext_resource path="res://entities/actors/snake/sprites/tongue.png" type="Texture" id=3] +[ext_resource path="res://entities/actors/snake/scripts/state_machine.gd" type="Script" id=4] +[ext_resource path="res://entities/actors/snake/scripts/normal_state.gd" type="Script" id=5] +[ext_resource path="res://entities/actors/snake/scripts/dash_state.gd" type="Script" id=6] +[ext_resource path="res://entities/actors/snake/scripts/slow_state.gd" type="Script" id=7] [sub_resource type="AtlasTexture" id=2] atlas = ExtResource( 3 ) @@ -35,6 +39,20 @@ radius = 2.0 collision_mask = 262 script = ExtResource( 2 ) +[node name="StateMachine" type="Node" parent="."] +script = ExtResource( 4 ) + +[node name="NormalState" type="Node" parent="StateMachine"] +script = ExtResource( 5 ) + +[node name="DashState" type="Node" parent="StateMachine"] +script = ExtResource( 6 ) + +[node name="SlowState" type="Node" parent="StateMachine"] +script = ExtResource( 7 ) + +[node name="JumpState" type="Node" parent="StateMachine"] + [node name="Tongue" type="AnimatedSprite" parent="."] position = Vector2( 0, -5 ) frames = SubResource( 6 ) diff --git a/src/entities/actors/snake/scripts/dash_state.gd b/src/entities/actors/snake/scripts/dash_state.gd new file mode 100644 index 0000000..3eb0bdf --- /dev/null +++ b/src/entities/actors/snake/scripts/dash_state.gd @@ -0,0 +1,25 @@ +extends Node + +var fsm: StateMachine + + +func enter(): + if fsm.DEBUG: + print("Got inside %s." % name) + Event.emit_signal("snake_started_dash") + Global.SNAKE_SPEED = Global.SNAKE_DASH_SPEED + yield(get_tree().create_timer(Global.SNAKE_DASH_TIME), "timeout") + exit() + + +func exit(): + Event.emit_signal("snake_finished_dash") + Global.SNAKE_SPEED = Global.SNAKE_SPEED_BACKUP + fsm.back() + + +func physics_process(delta: float) -> void: + fsm.player.velocity = fsm.player.direction * Global.SNAKE_SPEED + fsm.player.velocity = fsm.player.move_and_slide(fsm.player.velocity) + + fsm.slow_down_on_collisions(Global.SNAKE_DASH_SPEED) diff --git a/src/entities/actors/snake/scripts/generic_segment.gd b/src/entities/actors/snake/scripts/generic_segment.gd index d0bb944..a1a930a 100644 --- a/src/entities/actors/snake/scripts/generic_segment.gd +++ b/src/entities/actors/snake/scripts/generic_segment.gd @@ -21,4 +21,4 @@ func _on_body_entered(body: Node) -> void: func _on_snake_rotated() -> void: # this is just random, i need to offset a tiny bit whenever the snake rotates # so that the first body segmetn doesn't catch up with the head - offset -= Global.SNAKE_SPEED * pow(get_physics_process_delta_time(), 2) \ No newline at end of file + offset -= 0.75 * Global.SNAKE_SPEED * pow(get_physics_process_delta_time(), 2) \ No newline at end of file diff --git a/src/entities/actors/snake/scripts/head.gd b/src/entities/actors/snake/scripts/head.gd index 8747910..e6824a7 100644 --- a/src/entities/actors/snake/scripts/head.gd +++ b/src/entities/actors/snake/scripts/head.gd @@ -9,49 +9,30 @@ onready var tongue_sprite: AnimatedSprite = $Tongue var _initial_speed: float = Global.SNAKE_SPEED var velocity: Vector2 = Vector2.ZERO -var _direction: Vector2 = Vector2.UP +var direction: Vector2 = Vector2.UP var _time_elapsed: float = 0.0 +var can_dash: bool = true +var can_slow: bool = true +var can_jump: bool = true + func _ready() -> void: Event.connect("food_eaten", self, "_on_food_eaten") + Event.connect("snake_started_dash", self, "_on_snake_started_dash") + Event.connect("snake_started_slow", self, "_on_snake_started_slow") + Event.connect("snake_started_jump", self, "_on_snake_started_jump") tongue_sprite.visible = false -func _physics_process(delta: float) -> void: - if Input.is_action_pressed("move_left"): - _rotate_to(LEFT) - if Input.is_action_pressed("move_right"): - _rotate_to(RIGHT) - - velocity = _direction * Global.SNAKE_SPEED - - # not sure if needed, worked wonders when using a Node2D instead of KB2D - velocity = move_and_slide(velocity) - - # slow down on collisions, so it isn't as unfair - if get_last_slide_collision(): - var speed: float = velocity.length() - Global.SNAKE_SPEED = speed - else: - Global.SNAKE_SPEED = Global.SNAKE_SPEED_BACKUP - - # handle slow speeds - if Global.SNAKE_SPEED <= Global.SNAKE_SPEED_BACKUP / 4.0: - Global.SNAKE_SPEED = Global.SNAKE_SPEED_BACKUP - Event.emit_signal("game_over") - - _handle_time_elapsed(delta) - - -func _rotate_to(direction: int) -> void: - rotate(deg2rad(direction * Global.SNAKE_ROT_SPEED * get_physics_process_delta_time())) - _direction = _direction.rotated(deg2rad(direction * Global.SNAKE_ROT_SPEED * get_physics_process_delta_time())) +func rotate_to(_direction: int) -> void: + rotate(deg2rad(_direction * Global.SNAKE_ROT_SPEED * get_physics_process_delta_time())) + direction = direction.rotated(deg2rad(_direction * Global.SNAKE_ROT_SPEED * get_physics_process_delta_time())) Event.emit_signal("snake_rotated") # using a timer is not recommended for < 0.01 -func _handle_time_elapsed(delta: float) -> void: +func handle_time_elapsed(delta: float) -> void: if _time_elapsed >= Global.SNAKE_POSITION_UPDATE_INTERVAL: Event.emit_signal("snake_path_new_point", global_position) _time_elapsed = 0.0 @@ -65,3 +46,21 @@ func _on_food_eaten(properties: Dictionary) -> void: yield(tongue_sprite, "animation_finished") tongue_sprite.stop() tongue_sprite.frame = 0 + + +func _on_snake_started_dash() -> void: + can_dash = false + yield(get_tree().create_timer(Global.SNAKE_DASH_COOLDOWN), "timeout") + can_dash = true + + +func _on_snake_started_slow() -> void: + can_slow = false + yield(get_tree().create_timer(Global.SNAKE_SLOW_COOLDOWN), "timeout") + can_slow = true + + +func _on_snake_started_jump() -> void: + can_jump = false + yield(get_tree().create_timer(Global.SNAKE_JUMP_COOLDOWN), "timeout") + can_jump = true diff --git a/src/entities/actors/snake/scripts/jump_state.gd b/src/entities/actors/snake/scripts/jump_state.gd new file mode 100644 index 0000000..396ceb4 --- /dev/null +++ b/src/entities/actors/snake/scripts/jump_state.gd @@ -0,0 +1,27 @@ +extends Node + +var fsm: StateMachine + + +func enter(): + if fsm.DEBUG: + print("Got inside %s." % name) + Event.emit_signal("snake_started_dash") + Global.SNAKE_SPEED = Global.SNAKE_DASH_SPEED + yield(get_tree().create_timer(Global.SNAKE_DASH_TIME), "timeout") + exit() + + +func exit(): + Event.emit_signal("snake_finished_dash") + Global.SNAKE_SPEED = Global.SNAKE_SPEED_BACKUP + fsm.back() + + +func physics_process(delta: float) -> float: + fsm.player.velocity = fsm.player.direction * Global.SNAKE_SPEED + fsm.player.velocity = fsm.player.move_and_slide(fsm.player.velocity) + + fsm.slow_down_on_collisions(Global.SNAKE_DASH_SPEED) + + return delta diff --git a/src/entities/actors/snake/scripts/normal_state.gd b/src/entities/actors/snake/scripts/normal_state.gd new file mode 100644 index 0000000..11981a3 --- /dev/null +++ b/src/entities/actors/snake/scripts/normal_state.gd @@ -0,0 +1,28 @@ +extends Node + +var fsm: StateMachine + + +func enter(): + if fsm.DEBUG: + print("Got inside %s." % name) + + +func exit(next_state): + fsm.change_to(next_state) + + +func physics_process(delta: float) -> void: + fsm.player.velocity = fsm.player.direction * Global.SNAKE_SPEED + fsm.player.velocity = fsm.player.move_and_slide(fsm.player.velocity) + + fsm.slow_down_on_collisions(Global.SNAKE_SPEED_BACKUP) + + +func input(event: InputEvent) -> void: + if fsm.player.can_dash and event.is_action_pressed("dash"): + exit("DashState") + if fsm.player.can_slow and event.is_action_pressed("slow"): + exit("SlowState") + # if fsm.player.can_jump and event.is_action_pressed("jump"): + # exit("JumpState") diff --git a/src/entities/actors/snake/scripts/slow_state.gd b/src/entities/actors/snake/scripts/slow_state.gd new file mode 100644 index 0000000..8d54bfb --- /dev/null +++ b/src/entities/actors/snake/scripts/slow_state.gd @@ -0,0 +1,27 @@ +extends Node + +var fsm: StateMachine + + +func enter(): + if fsm.DEBUG: + print("Got inside %s." % name) + Event.emit_signal("snake_started_slow") + Global.SNAKE_SPEED = Global.SNAKE_SLOW_SPEED + yield(get_tree().create_timer(Global.SNAKE_SLOW_TIME), "timeout") + exit() + + +func exit(): + Event.emit_signal("snake_finished_dash") + Global.SNAKE_SPEED = Global.SNAKE_SPEED_BACKUP + fsm.back() + + +func physics_process(delta: float) -> float: + fsm.player.velocity = fsm.player.direction * Global.SNAKE_SPEED + fsm.player.velocity = fsm.player.move_and_slide(fsm.player.velocity) + + fsm.slow_down_on_collisions(Global.SNAKE_SLOW_SPEED) + + return delta diff --git a/src/entities/actors/snake/scripts/state_machine.gd b/src/entities/actors/snake/scripts/state_machine.gd new file mode 100644 index 0000000..b63f272 --- /dev/null +++ b/src/entities/actors/snake/scripts/state_machine.gd @@ -0,0 +1,72 @@ +class_name StateMachine +extends Node + +const DEBUG: bool = false + +var player: KinematicBody2D +var state: Node +var history: Array = [] + + +func _ready() -> void: + player = get_parent() + state = get_child(0) + _enter_state() + + +func change_to(new_state: String) -> void: + history.append(state.name) + state = get_node(new_state) + _enter_state() + + +func back() -> void: + if history.size() > 0: + state = get_node(history.pop_back()) + _enter_state() + + +func _enter_state() -> void: + if DEBUG: + print("Entering state %s" % state.name) + state.fsm = self + state.enter() + + +# routing game loop functions +func _process(delta: float) -> void: + if state.has_method("process"): + state.process(delta) + + +func _physics_process(delta: float) -> void: + if Input.is_action_pressed("move_left"): + player.rotate_to(player.LEFT) + if Input.is_action_pressed("move_right"): + player.rotate_to(player.RIGHT) + + # state specific code, move_and_slide is called here + if state.has_method("physics_process"): + state.physics_process(delta) + + handle_slow_speeds() + + player.handle_time_elapsed(delta) + + +func slow_down_on_collisions(speed_backup: float): + if player.get_last_slide_collision(): + Global.SNAKE_SPEED = player.velocity.length() + else: + Global.SNAKE_SPEED = speed_backup + + +func handle_slow_speeds() -> void: + if Global.SNAKE_SPEED <= Global.SNAKE_SPEED_BACKUP / 4.0: + Global.SNAKE_SPEED = Global.SNAKE_SPEED_BACKUP + Event.emit_signal("game_over") + + +func _input(event: InputEvent) -> void: + if state.has_method("input"): + state.input(event) -- cgit v1.2.3