From 2c5d588bc593929a96f0e58d7d1ab52f269add55 Mon Sep 17 00:00:00 2001
From: David Luevano Alvarado <david@luevano.xyz>
Date: Wed, 1 Jun 2022 03:27:11 -0600
Subject: make working basic snake, refactor code and made gif recorder its
 separate thing

---
 src/Main.tscn                                      | 32 +-------
 src/entities/actors/snake/scenes/Body.tscn         | 13 +++-
 src/entities/actors/snake/scenes/Head.tscn         | 12 ++-
 src/entities/actors/snake/scenes/Tail.tscn         | 12 ++-
 .../actors/snake/scripts/generic_segment.gd        |  5 +-
 src/entities/actors/snake/scripts/head.gd          | 32 ++++----
 src/entities/actors/snake/scripts/snake.gd         | 87 ++++++++++++++++++----
 src/event.gd                                       |  5 +-
 src/global.gd                                      |  4 +-
 src/project.godot                                  | 25 ++++---
 src/screen_recorder.gd                             | 13 ----
 src/tools/ScreenRecorder.tscn                      | 31 ++++++++
 src/tools/screen_recorder.gd                       | 13 ++++
 13 files changed, 193 insertions(+), 91 deletions(-)
 delete mode 100644 src/screen_recorder.gd
 create mode 100644 src/tools/ScreenRecorder.tscn
 create mode 100644 src/tools/screen_recorder.gd

(limited to 'src')

diff --git a/src/Main.tscn b/src/Main.tscn
index 5471565..ef84fce 100644
--- a/src/Main.tscn
+++ b/src/Main.tscn
@@ -1,10 +1,8 @@
-[gd_scene load_steps=6 format=2]
+[gd_scene load_steps=4 format=2]
 
 [ext_resource path="res://entities/actors/snake/scenes/Snake.tscn" type="PackedScene" id=1]
-[ext_resource path="res://addons/GifMaker/GifRecorder.gd" type="Script" id=2]
-[ext_resource path="res://addons/GifMaker/GifRectangle.gd" type="Script" id=3]
+[ext_resource path="res://tools/ScreenRecorder.tscn" type="PackedScene" id=2]
 [ext_resource path="res://main.gd" type="Script" id=4]
-[ext_resource path="res://screen_recorder.gd" type="Script" id=5]
 
 [node name="Main" type="Node2D"]
 script = ExtResource( 4 )
@@ -15,28 +13,4 @@ script = ExtResource( 4 )
 current = true
 zoom = Vector2( 0.5, 0.5 )
 
-[node name="ScreenRecorder" type="CanvasLayer" parent="."]
-script = ExtResource( 5 )
-
-[node name="Control" type="Control" parent="ScreenRecorder"]
-anchor_right = 1.0
-anchor_bottom = 1.0
-
-[node name="GifRectangle" type="ReferenceRect" parent="ScreenRecorder/Control"]
-anchor_left = 0.5
-anchor_top = 0.5
-anchor_right = 0.5
-anchor_bottom = 0.5
-margin_left = -64.0
-margin_top = -64.0
-margin_right = 64.0
-margin_bottom = 64.0
-script = ExtResource( 3 )
-
-[node name="GifRecorder" type="Viewport" parent="ScreenRecorder/Control"]
-size = Vector2( 128, 128 )
-script = ExtResource( 2 )
-render_type = 1
-seconds = 2.0
-autostart = true
-capture_node_path = NodePath("../GifRectangle")
+[node name="ScreenRecorder" parent="." instance=ExtResource( 2 )]
diff --git a/src/entities/actors/snake/scenes/Body.tscn b/src/entities/actors/snake/scenes/Body.tscn
index 93020b2..8e4a8a4 100644
--- a/src/entities/actors/snake/scenes/Body.tscn
+++ b/src/entities/actors/snake/scenes/Body.tscn
@@ -1,14 +1,23 @@
-[gd_scene load_steps=3 format=2]
+[gd_scene load_steps=4 format=2]
 
 [ext_resource path="res://entities/actors/snake/sprites/body.png" type="Texture" id=1]
 [ext_resource path="res://entities/actors/snake/scripts/generic_segment.gd" type="Script" id=2]
 
+[sub_resource type="CapsuleShape2D" id=1]
+radius = 5.99999
+height = 4.00002
+
 [node name="BodyPathFollow" type="PathFollow2D"]
 loop = false
 script = ExtResource( 2 )
 
-[node name="Body" type="Node2D" parent="."]
+[node name="Body" type="Area2D" parent="."]
 rotation = 1.5708
+collision_layer = 2
+collision_mask = 0
 
 [node name="Sprite" type="Sprite" parent="Body"]
 texture = ExtResource( 1 )
+
+[node name="Collision" type="CollisionShape2D" parent="Body"]
+shape = SubResource( 1 )
diff --git a/src/entities/actors/snake/scenes/Head.tscn b/src/entities/actors/snake/scenes/Head.tscn
index 2dc1666..22aa7e6 100644
--- a/src/entities/actors/snake/scenes/Head.tscn
+++ b/src/entities/actors/snake/scenes/Head.tscn
@@ -1,10 +1,18 @@
-[gd_scene load_steps=3 format=2]
+[gd_scene load_steps=4 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]
 
-[node name="HeadPoint" type="Node2D"]
+[sub_resource type="CircleShape2D" id=1]
+radius = 5.0
+
+[node name="Head" type="KinematicBody2D"]
+position = Vector2( -1, 0 )
+collision_mask = 0
 script = ExtResource( 2 )
 
 [node name="Sprite" type="Sprite" parent="."]
 texture = ExtResource( 1 )
+
+[node name="Collision" type="CollisionShape2D" parent="."]
+shape = SubResource( 1 )
diff --git a/src/entities/actors/snake/scenes/Tail.tscn b/src/entities/actors/snake/scenes/Tail.tscn
index bb30c42..17e8ec5 100644
--- a/src/entities/actors/snake/scenes/Tail.tscn
+++ b/src/entities/actors/snake/scenes/Tail.tscn
@@ -1,15 +1,23 @@
-[gd_scene load_steps=3 format=2]
+[gd_scene load_steps=4 format=2]
 
 [ext_resource path="res://entities/actors/snake/sprites/tail.png" type="Texture" id=1]
 [ext_resource path="res://entities/actors/snake/scripts/generic_segment.gd" type="Script" id=2]
 
+[sub_resource type="CircleShape2D" id=1]
+radius = 4.12311
+
 [node name="TailPathFollow" type="PathFollow2D"]
 loop = false
 script = ExtResource( 2 )
 TYPE = "tail"
 
-[node name="Tail" type="Node2D" parent="."]
+[node name="Tail" type="Area2D" parent="."]
 rotation = 1.5708
+collision_layer = 4
+collision_mask = 0
 
 [node name="Sprite" type="Sprite" parent="Tail"]
 texture = ExtResource( 1 )
+
+[node name="Collision" type="CollisionShape2D" parent="Tail"]
+shape = SubResource( 1 )
diff --git a/src/entities/actors/snake/scripts/generic_segment.gd b/src/entities/actors/snake/scripts/generic_segment.gd
index ec34f43..6c65d11 100644
--- a/src/entities/actors/snake/scripts/generic_segment.gd
+++ b/src/entities/actors/snake/scripts/generic_segment.gd
@@ -1,8 +1,7 @@
 extends PathFollow2D
 
 export(String, "body", "tail") var TYPE: String = "body"
-var speed: float = Global.SNAKE_SPEED
 
 
-func _process(delta: float) -> void:
-	offset += speed * delta
\ No newline at end of file
+func _physics_process(delta: float) -> void:
+	offset += Global.SNAKE_SPEED * delta
diff --git a/src/entities/actors/snake/scripts/head.gd b/src/entities/actors/snake/scripts/head.gd
index ea28f74..448802e 100644
--- a/src/entities/actors/snake/scripts/head.gd
+++ b/src/entities/actors/snake/scripts/head.gd
@@ -1,30 +1,36 @@
-extends Node2D
+extends KinematicBody2D
 
-var speed: float = Global.SNAKE_SPEED
-var rot_speed: float = Global.SNAKE_ROT_SPEED
-var position_update_interval: float = Global.SNAKE_POSITION_UPDATE_INTERVAL
+enum {
+	LEFT=-1,
+	RIGHT=1
+}
 
+var velocity: Vector2 = Vector2.ZERO
 var _direction: Vector2 = Vector2.UP
 var _time_elapsed: float = 0.0
 
 
-func _process(delta: float) -> void:
+func _physics_process(delta: float) -> void:
 	if Input.is_action_pressed("move_left"):
-		# _direction = _direction.rotated(deg2rad(-ROT_SPEED))
-		rotate(deg2rad(-rot_speed * delta))
+		_rotate_to(LEFT)
 	if Input.is_action_pressed("move_right"):
-		# _direction = _direction.rotated(deg2rad(ROT_SPEED))
-		rotate(deg2rad(rot_speed * delta))
+		_rotate_to(RIGHT)
 
-	move_local_x(_direction.x * speed * delta)
-	move_local_y(_direction.y * speed * delta)
+	velocity = _direction * Global.SNAKE_SPEED
 
+	# not sure if needed, worked wonders when using a Node2D instead of KB2D
+	velocity = move_and_slide(velocity)
 	_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()))
+
+
 # using a timer is not recommended for < 0.01
 func _handle_time_elapsed(delta: float) -> void:
-	if _time_elapsed >= position_update_interval:
-		Event.emit_signal("new_curve_point", global_position)
+	if _time_elapsed >= Global.SNAKE_POSITION_UPDATE_INTERVAL:
+		Event.emit_signal("snake_path_new_point", global_position)
 		_time_elapsed = 0.0
 	_time_elapsed += delta
diff --git a/src/entities/actors/snake/scripts/snake.gd b/src/entities/actors/snake/scripts/snake.gd
index e604011..76b8bee 100644
--- a/src/entities/actors/snake/scripts/snake.gd
+++ b/src/entities/actors/snake/scripts/snake.gd
@@ -7,12 +7,30 @@ export(PackedScene) var TAIL_SEGMENT_NP: PackedScene
 onready var path: Path2D = $Path
 
 var current_body_segments: int = 0
-var max_body_segments: int = 1
-var body_segment_size: float = 16.0
+var max_body_initial_segments: int = 1
+var body_segment_stack: Array
+var tail_segment: PathFollow2D
+# didn't konw how to name this, basically holds the current path lenght
+# 	whenever the add body segment, and we use this stack to add body parts
+var body_segment_queue: Array
 
 
 func _ready():
-	Event.connect("new_curve_point", self, "_on_Head_new_curve_point")
+	set_physics_process(false)
+	set_process_input(false)
+	Event.connect("snake_path_new_point", self, "_on_Head_snake_path_new_point")
+	Event.connect("snake_added_new_segment", self, "_on_Snake_snake_added_new_segment")
+	Event.connect("snake_added_initial_segments", self, "_on_Snake_snake_added_initial_segments")
+
+
+func _physics_process(delta: float) -> void:
+	if body_segment_queue.size() != 0:
+		_add_new_segment()
+
+
+func _input(event: InputEvent) -> void:
+	if event.is_action_pressed("add_body_part"):
+		_add_segment_to_queue()
 
 
 func _draw() -> void:
@@ -20,23 +38,62 @@ func _draw() -> void:
 		draw_polyline(path.curve.get_baked_points(), Color.aquamarine, 1, true)
 
 
-func add_point_to_curve(coordinates: Vector2) -> void:
-	path.curve.add_point(coordinates)
-	# update call is to draw curve as there are new points
-	update()
+func _add_new_segment() -> void:
+	var _path_length_threshold: float = body_segment_queue[0] + Global.SNAKE_SEGMENT_SIZE
+	if path.curve.get_baked_length() >= _path_length_threshold:
+		var _temp_body_segment: PathFollow2D = BODY_SEGMENT_NP.instance()
+		Event.emit_signal("snake_add_new_segment", "body")
+		var _new_body_offset: float = body_segment_stack.back().offset - Global.SNAKE_SEGMENT_SIZE
 
-	if current_body_segments < max_body_segments:
-		add_snake_segment(BODY_SEGMENT_NP)
-	elif current_body_segments == max_body_segments:
-		add_snake_segment(TAIL_SEGMENT_NP)
+		_temp_body_segment.offset = _new_body_offset
+		body_segment_stack.append(_temp_body_segment)
+		path.add_child(_temp_body_segment)
+		tail_segment.offset = body_segment_stack.back().offset - Global.SNAKE_SEGMENT_SIZE
 
+		body_segment_queue.pop_front()
+		current_body_segments += 1
+		Event.emit_signal("snake_added_new_segment", "body")
 
-func add_snake_segment(type: PackedScene) -> void:
-	if path.curve.get_baked_length() >= (current_body_segments + 1.0) * body_segment_size:
+
+func _add_initial_segment(type: PackedScene) -> void:
+	if path.curve.get_baked_length() >= (current_body_segments + 1.0) * Global.SNAKE_SEGMENT_SIZE:
 		var _temp_body_segment: PathFollow2D = type.instance()
+		Event.emit_signal("snake_add_new_segment", _temp_body_segment.TYPE)
+		if _temp_body_segment.TYPE == "body":
+			body_segment_stack.append(_temp_body_segment)
+		else:
+			tail_segment = _temp_body_segment
 		path.add_child(_temp_body_segment)
+
 		current_body_segments += 1
+		Event.emit_signal("snake_added_new_segment", _temp_body_segment.TYPE)
+
+
+func _add_segment_to_queue() -> void:
+	# need to have the queues in a fixed separation, else if the eating functionality
+	#	gets spammed, all next bodyparts will be spawned almost at the same spot
+	if body_segment_queue.size() == 0:
+		body_segment_queue.append(path.curve.get_baked_length())
+	else:
+		body_segment_queue.append(body_segment_queue.back() + Global.SNAKE_SEGMENT_SIZE)
+
+
+func _on_Head_snake_path_new_point(coordinates: Vector2) -> void:
+	path.curve.add_point(coordinates)
+	# update call is to draw curve as there are new points to the path's curve
+	update()
+
+	if current_body_segments < max_body_initial_segments:
+		_add_initial_segment(BODY_SEGMENT_NP)
+	elif current_body_segments == max_body_initial_segments:
+		_add_initial_segment(TAIL_SEGMENT_NP)
+
+
+func _on_Snake_snake_added_new_segment(type: String) -> void:
+	if type == "tail":
+		Event.emit_signal("snake_added_initial_segments")
 
 
-func _on_Head_new_curve_point(coordinates: Vector2) -> void:
-	add_point_to_curve(coordinates)
+func _on_Snake_snake_added_initial_segments() -> void:
+	set_physics_process(true)
+	set_process_input(true)
diff --git a/src/event.gd b/src/event.gd
index 845de39..e03c159 100644
--- a/src/event.gd
+++ b/src/event.gd
@@ -1,3 +1,6 @@
 extends Node
 
-signal new_curve_point(coordinates)
\ No newline at end of file
+signal snake_path_new_point(coordinates)
+signal snake_add_new_segment(type)
+signal snake_added_new_segment(type)
+signal snake_added_initial_segments
\ No newline at end of file
diff --git a/src/global.gd b/src/global.gd
index e121fd0..1682819 100644
--- a/src/global.gd
+++ b/src/global.gd
@@ -3,4 +3,6 @@ extends Node
 var SNAKE_SPEED: float = 50.0
 var SNAKE_ROT_SPEED: float = 200.0
 var SNAKE_SEGMENT_ROT_SPEED: float = 80.0
-var SNAKE_POSITION_UPDATE_INTERVAL: float = 0.01
\ No newline at end of file
+var SNAKE_POSITION_UPDATE_INTERVAL: float = 0.01
+# this usually corresponds to the sprite size
+var SNAKE_SEGMENT_SIZE: float = 14.0
\ No newline at end of file
diff --git a/src/project.godot b/src/project.godot
index 4146dfd..941300b 100644
--- a/src/project.godot
+++ b/src/project.godot
@@ -77,16 +77,6 @@ texture={
 
 [input]
 
-move_up={
-"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":87,"unicode":0,"echo":false,"script":null)
- ]
-}
-move_down={
-"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":83,"unicode":0,"echo":false,"script":null)
- ]
-}
 move_left={
 "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":65,"unicode":0,"echo":false,"script":null)
@@ -97,7 +87,22 @@ move_right={
 "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":68,"unicode":0,"echo":false,"script":null)
  ]
 }
+add_body_part={
+"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)
+ ]
+}
+
+[layer_names]
+
+2d_physics/layer_1="snake_head"
+2d_physics/layer_2="snake_body"
+2d_physics/layer_3="snake_tail"
 
 [physics]
 
 common/enable_pause_aware_picking=true
+
+[rendering]
+
+threads/thread_model=2
diff --git a/src/screen_recorder.gd b/src/screen_recorder.gd
deleted file mode 100644
index 2ab77e5..0000000
--- a/src/screen_recorder.gd
+++ /dev/null
@@ -1,13 +0,0 @@
-extends CanvasLayer
-
-onready var gif_recorder: GifRecorder = $Control/GifRecorder
-
-
-func _input(event: InputEvent) -> void:
-	if event is InputEventKey and event.scancode == KEY_G and event.pressed:
-		print("Encoding GIF.")
-		gif_recorder.render_to_file("res://test.gif")
-		yield(gif_recorder, "done_encoding")
-		print("Done encoding GIF.")
-		gif_recorder.clear()
-		gif_recorder.start()
diff --git a/src/tools/ScreenRecorder.tscn b/src/tools/ScreenRecorder.tscn
new file mode 100644
index 0000000..d29753a
--- /dev/null
+++ b/src/tools/ScreenRecorder.tscn
@@ -0,0 +1,31 @@
+[gd_scene load_steps=4 format=2]
+
+[ext_resource path="res://addons/GifMaker/GifRectangle.gd" type="Script" id=1]
+[ext_resource path="res://tools/screen_recorder.gd" type="Script" id=2]
+[ext_resource path="res://addons/GifMaker/GifRecorder.gd" type="Script" id=3]
+
+[node name="ScreenRecorder" type="CanvasLayer"]
+script = ExtResource( 2 )
+
+[node name="Control" type="Control" parent="."]
+anchor_right = 1.0
+anchor_bottom = 1.0
+
+[node name="GifRectangle" type="ReferenceRect" parent="Control"]
+anchor_left = 0.5
+anchor_top = 0.5
+anchor_right = 0.5
+anchor_bottom = 0.5
+margin_left = -128.0
+margin_top = -128.0
+margin_right = 128.0
+margin_bottom = 128.0
+script = ExtResource( 1 )
+
+[node name="GifRecorder" type="Viewport" parent="Control"]
+size = Vector2( 2, 2 )
+script = ExtResource( 3 )
+render_type = 1
+seconds = 4.0
+autostart = true
+capture_node_path = NodePath("../GifRectangle")
diff --git a/src/tools/screen_recorder.gd b/src/tools/screen_recorder.gd
new file mode 100644
index 0000000..2ab77e5
--- /dev/null
+++ b/src/tools/screen_recorder.gd
@@ -0,0 +1,13 @@
+extends CanvasLayer
+
+onready var gif_recorder: GifRecorder = $Control/GifRecorder
+
+
+func _input(event: InputEvent) -> void:
+	if event is InputEventKey and event.scancode == KEY_G and event.pressed:
+		print("Encoding GIF.")
+		gif_recorder.render_to_file("res://test.gif")
+		yield(gif_recorder, "done_encoding")
+		print("Done encoding GIF.")
+		gif_recorder.clear()
+		gif_recorder.start()
-- 
cgit v1.2.3-70-g09d2