From 2c5d588bc593929a96f0e58d7d1ab52f269add55 Mon Sep 17 00:00:00 2001 From: David Luevano Alvarado 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 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