Added basic movement in an arena
							parent
							
								
									73c838c2b3
								
							
						
					
					
						commit
						18aadc0c2d
					
				| 
						 | 
				
			
			@ -1,3 +1,3 @@
 | 
			
		|||
# Ouroboros
 | 
			
		||||
 | 
			
		||||
Game jam made for the GMTK 2025 Game Jam
 | 
			
		||||
Game jam made for the GMTK 2025 Game Jam
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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")
 | 
			
		||||
| 
						 | 
				
			
			@ -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)]]
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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()
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
uid://cn4hlmm4qa8fg
 | 
			
		||||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue