From 18aadc0c2d33f35c3d11e12a96f1ef8fd40bbd79 Mon Sep 17 00:00:00 2001 From: TechieDamien Date: Wed, 30 Jul 2025 20:04:52 +0100 Subject: [PATCH] Added basic movement in an arena --- README.md | 2 +- Scenes/level.tscn | 27 ++++++++ Scenes/main.tscn | 20 ++++++ Scenes/snake_part.tscn | 34 ++++++++++ Scripts/snake_part.gd | 129 ++++++++++++++++++++++++++++++++++++++ Scripts/snake_part.gd.uid | 1 + project.godot | 27 ++++++++ 7 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 Scenes/level.tscn create mode 100644 Scenes/main.tscn create mode 100644 Scenes/snake_part.tscn create mode 100644 Scripts/snake_part.gd create mode 100644 Scripts/snake_part.gd.uid diff --git a/README.md b/README.md index f6c7651..c4e855a 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # Ouroboros -Game jam made for the GMTK 2025 Game Jam \ No newline at end of file +Game jam made for the GMTK 2025 Game Jam diff --git a/Scenes/level.tscn b/Scenes/level.tscn new file mode 100644 index 0000000..d11fc95 --- /dev/null +++ b/Scenes/level.tscn @@ -0,0 +1,27 @@ +[gd_scene load_steps=5 format=3 uid="uid://gkqku38yb2ng"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_51e2h"] + +[sub_resource type="QuadMesh" id="QuadMesh_tumq0"] +size = Vector2(21.5, 21.5) + +[sub_resource type="Gradient" id="Gradient_k5f4k"] +interpolation_mode = 2 +offsets = PackedFloat32Array(0, 0.928571, 0.961039, 1) +colors = PackedColorArray(0, 0, 0, 0, 0.819608, 0.819608, 0.819608, 0, 1, 1, 1, 1, 0.650865, 0.650865, 0.650865, 0) + +[sub_resource type="GradientTexture2D" id="GradientTexture2D_6phgx"] +gradient = SubResource("Gradient_k5f4k") +fill = 2 +fill_from = Vector2(0.5, 0.495413) +fill_to = Vector2(0, 0) + +[node name="Level" type="Area2D"] +monitorable = false + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("RectangleShape2D_51e2h") + +[node name="MeshInstance2D" type="MeshInstance2D" parent="CollisionShape2D"] +mesh = SubResource("QuadMesh_tumq0") +texture = SubResource("GradientTexture2D_6phgx") diff --git a/Scenes/main.tscn b/Scenes/main.tscn new file mode 100644 index 0000000..1c09971 --- /dev/null +++ b/Scenes/main.tscn @@ -0,0 +1,20 @@ +[gd_scene load_steps=3 format=3 uid="uid://bs6an72avch86"] + +[ext_resource type="PackedScene" uid="uid://gkqku38yb2ng" path="res://Scenes/level.tscn" id="1_bo1nx"] +[ext_resource type="PackedScene" uid="uid://d0okbjqyaoe0w" path="res://Scenes/snake_part.tscn" id="2_8gbba"] + +[node name="Main" type="Node2D"] + +[node name="Level" parent="." instance=ExtResource("1_bo1nx")] +position = Vector2(620, 320) +scale = Vector2(50, 30) + +[node name="Timer" type="Timer" parent="."] +wait_time = 0.3 +autostart = true + +[node name="SnakePart" parent="." instance=ExtResource("2_8gbba")] +position = Vector2(420, 240) + +[connection signal="area_exited" from="Level" to="SnakePart" method="_on_level_area_exited"] +[connection signal="timeout" from="Timer" to="SnakePart" method="process_movement" binds= [Vector2(0, 0)]] diff --git a/Scenes/snake_part.tscn b/Scenes/snake_part.tscn new file mode 100644 index 0000000..aab471a --- /dev/null +++ b/Scenes/snake_part.tscn @@ -0,0 +1,34 @@ +[gd_scene load_steps=4 format=3 uid="uid://d0okbjqyaoe0w"] + +[ext_resource type="Script" uid="uid://cn4hlmm4qa8fg" path="res://Scripts/snake_part.gd" id="1_iuiyg"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_hf2pu"] +size = Vector2(18, 18) + +[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_kum7e"] +size = Vector2(20, 20) + +[node name="SnakePart" type="Area2D"] +script = ExtResource("1_iuiyg") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("RectangleShape2D_hf2pu") + +[node name="Sprite2D" type="Sprite2D" parent="."] +texture = SubResource("PlaceholderTexture2D_kum7e") + +[node name="DownRayCast2D" type="RayCast2D" parent="."] +target_position = Vector2(0, 30) +collide_with_areas = true + +[node name="LeftRayCast2D" type="RayCast2D" parent="."] +target_position = Vector2(-30, 0) +collide_with_areas = true + +[node name="UpRayCast2D" type="RayCast2D" parent="."] +target_position = Vector2(0, -30) +collide_with_areas = true + +[node name="RightRayCast2D" type="RayCast2D" parent="."] +target_position = Vector2(30, 0) +collide_with_areas = true diff --git a/Scripts/snake_part.gd b/Scripts/snake_part.gd new file mode 100644 index 0000000..6d91bb5 --- /dev/null +++ b/Scripts/snake_part.gd @@ -0,0 +1,129 @@ +extends Area2D +class_name SnakePart + +const TILE_SIZE = 20 +enum PartTypes {HEAD, BODY, TAIL, DEAD} + +var part_type : PartTypes = PartTypes.HEAD +var current_direction : Vector2 = Vector2.RIGHT + +var inputs : Dictionary[String, Vector2] = {"right": Vector2.RIGHT, + "left": Vector2.LEFT, + "up": Vector2.UP, + "down": Vector2.DOWN} + + +@onready +var raycast_right = $RightRayCast2D +@onready +var raycast_left = $LeftRayCast2D +@onready +var raycast_up = $UpRayCast2D +@onready +var raycast_down = $DownRayCast2D + + +var snake_part_obj = preload("res://Scenes/snake_part.tscn") + +@onready +var timer_ref = $"../Timer" + +signal do_movement(new_dir) + +func _ready() -> void: + if part_type == PartTypes.HEAD: + + # Add to group for easy access from other nodes + add_to_group("Head") + + # Set up a body part + var body = snake_part_obj.instantiate() + body.part_type = PartTypes.BODY + body.position = (position - current_direction * TILE_SIZE).snapped(Vector2.ONE * TILE_SIZE) + get_parent().add_child.call_deferred(body) + do_movement.connect(body.process_movement) + + # Set up a tail part + var tail = snake_part_obj.instantiate() + tail.part_type = PartTypes.TAIL + tail.position = (position - current_direction * TILE_SIZE * 2).snapped(Vector2.ONE * TILE_SIZE) + get_parent().add_child.call_deferred(tail) + body.do_movement.connect(tail.process_movement) + else: + raycast_down.queue_free() + raycast_up.queue_free() + raycast_left.queue_free() + raycast_right.queue_free() + #elif part_type == PartTypes.BODY: + #area_entered.connect(_on_part_area_entered) + #elif part_type == PartTypes.TAIL: + #area_entered.connect(_on_part_area_entered) + + + +func process_movement(new_direction : Vector2) -> void: + if part_type == PartTypes.HEAD: + check_movement() + position = (position + current_direction * TILE_SIZE).snapped(Vector2.ONE * TILE_SIZE) + #process_collisions(); + do_movement.emit(current_direction) + if new_direction != Vector2.ZERO: + current_direction = new_direction + +func check_movement() -> void: + # Get the correct raycast for the direction we are moving + var raycast_to_use : RayCast2D + if current_direction == Vector2.RIGHT: + raycast_to_use = raycast_right + elif current_direction == Vector2.LEFT: + raycast_to_use = raycast_left + elif current_direction == Vector2.UP: + raycast_to_use = raycast_up + elif current_direction == Vector2.DOWN: + raycast_to_use = raycast_down + + # Look using the raycast for anything to collide with + var object_in_path : Object = raycast_to_use.get_collider() + if object_in_path == null: + return + if object_in_path is SnakePart: + match object_in_path.part_type: + PartTypes.BODY: + lose_game() + PartTypes.TAIL: + ouroboros() + +#func process_collisions() -> void: + #var colliding_areas = get_overlapping_areas() + #for area in colliding_areas: + #if area is SnakePart: + #match area.part_type: + #PartTypes.BODY: + #lose_game() + #PartTypes.TAIL: + #ouroboros() + +func lose_game() -> void: + # You lose! + print("Game lost") + timer_ref.stop() + +func ouroboros() -> void: + print("You have achieved the ouroboros!") + +func _unhandled_input(event: InputEvent) -> void: + if event is InputEventKey and part_type == PartTypes.HEAD: + for dir in inputs.keys(): + if event.is_action_pressed(dir): + current_direction = inputs[dir] + +#func _on_part_area_entered(area: Area2D) -> void: + #if area.get("part_type") != PartTypes.HEAD: + #return + #if part_type == PartTypes.BODY or part_type == PartTypes.DEAD: + #lose_game() + #elif part_type == PartTypes.TAIL: + #ouroboros() + +func _on_level_area_exited(area: Area2D) -> void: + lose_game() diff --git a/Scripts/snake_part.gd.uid b/Scripts/snake_part.gd.uid new file mode 100644 index 0000000..445c285 --- /dev/null +++ b/Scripts/snake_part.gd.uid @@ -0,0 +1 @@ +uid://cn4hlmm4qa8fg diff --git a/project.godot b/project.godot index c32482a..37c8b28 100644 --- a/project.godot +++ b/project.godot @@ -14,6 +14,33 @@ config/name="Ouroboros" config/features=PackedStringArray("4.4", "GL Compatibility") config/icon="res://icon.svg" +[input] + +right={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +left={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +down={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194322,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +up={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} + [rendering] renderer/rendering_method="gl_compatibility"