Skip to content

Commit 103461d

Browse files
committed
Add a saving demo that uses custom resources
1 parent 3a38ab4 commit 103461d

File tree

15 files changed

+692
-0
lines changed

15 files changed

+692
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Normalize EOL for all files that Git considers text files.
2+
* text=auto eol=lf
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Godot 4+ specific ignores
2+
.godot/
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
extends CharacterBody2D
2+
class_name Character
3+
4+
const CHARACTER_GROUP := &"characters"
5+
6+
signal tagged(target : Character)
7+
8+
var move_direction : Vector2 = Vector2.ZERO
9+
var path_to_whose_it : NodePath = ^""
10+
var stunned : bool = false
11+
12+
@export var character_name := ""
13+
@export var player_controlled := false
14+
@export var base_speed : float = 100 # pixels per second
15+
@export var it_speed_multiplier : float = 2.0
16+
@export var stun_duration : float = 2.0 # seconds
17+
18+
@onready var timer := $StunTimer as Timer
19+
@onready var label := $Label as Label
20+
21+
22+
func _ready() -> void:
23+
label.text = character_name
24+
25+
26+
func _physics_process(_delta: float) -> void:
27+
if player_controlled:
28+
move_direction = Input.get_vector("left", "right", "up", "down")
29+
elif is_it():
30+
move_direction = position.direction_to(get_nearest_character().position)
31+
else:
32+
var whose_it := get_node(path_to_whose_it) as Character
33+
move_direction = -1 * position.direction_to(whose_it.position) # move away from whose it
34+
velocity = move_direction * get_speed()
35+
var collided : bool = move_and_slide()
36+
if not collided:
37+
return
38+
var collision : KinematicCollision2D = get_last_slide_collision()
39+
var collieder = collision.get_collider()
40+
if collieder is Character:
41+
if is_it() and not stunned:
42+
tagged.emit(collieder)
43+
44+
45+
func is_it() -> bool:
46+
return path_to_whose_it == get_path()
47+
48+
49+
func stun(duration : float) -> void:
50+
stunned = true
51+
timer.wait_time = duration
52+
timer.start()
53+
54+
55+
func get_speed() -> float:
56+
if stunned:
57+
return 0.0
58+
else:
59+
return base_speed * it_speed_multiplier if is_it() else base_speed
60+
61+
62+
func get_nearest_character() -> Character:
63+
var nearest_character : Character = self
64+
var nearest_dist_squared := INF
65+
var dist_squared := 0.0
66+
67+
var characters = get_tree().get_nodes_in_group(CHARACTER_GROUP)
68+
for character in characters as Array[Character]:
69+
dist_squared = position.distance_squared_to(character.position)
70+
if dist_squared > 0.0001 and dist_squared < nearest_dist_squared:
71+
nearest_dist_squared = dist_squared
72+
nearest_character = character
73+
return nearest_character
74+
75+
76+
func serialize() -> CharacterResource:
77+
var character_resource := CharacterResource.new()
78+
character_resource.character_name = character_name
79+
character_resource.position = position
80+
character_resource.move_direction = move_direction
81+
character_resource.base_speed = base_speed
82+
character_resource.it_speed_multiplier = it_speed_multiplier
83+
character_resource.path_to_whose_it = path_to_whose_it
84+
character_resource.player_controlled = player_controlled
85+
character_resource.stunned = stunned
86+
character_resource.stun_duration = stun_duration
87+
character_resource.stun_time_left = timer.time_left
88+
return character_resource
89+
90+
91+
func deserialize(character_resource : CharacterResource) -> void:
92+
if character_resource.stun_time_left > 0:
93+
timer.start(character_resource.stun_time_left)
94+
stun_duration = character_resource.stun_duration
95+
stunned = character_resource.stunned
96+
player_controlled = character_resource.player_controlled
97+
path_to_whose_it = character_resource.path_to_whose_it
98+
it_speed_multiplier = character_resource.it_speed_multiplier
99+
base_speed = character_resource.base_speed
100+
move_direction = character_resource.move_direction
101+
position = character_resource.position
102+
character_name = character_resource.character_name
103+
label.text = character_name
104+
105+
106+
func _on_stun_timer_timeout() -> void:
107+
stunned = false
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[gd_scene load_steps=4 format=3 uid="uid://djbgtqgci6is1"]
2+
3+
[ext_resource type="Texture2D" uid="uid://dkk04ow5f8clu" path="res://icon.svg" id="1_alri3"]
4+
[ext_resource type="Script" path="res://game/character.gd" id="1_dtr8n"]
5+
6+
[sub_resource type="RectangleShape2D" id="RectangleShape2D_tjudb"]
7+
size = Vector2(128, 128)
8+
9+
[node name="Character" type="CharacterBody2D"]
10+
collision_mask = 3
11+
motion_mode = 1
12+
script = ExtResource("1_dtr8n")
13+
14+
[node name="Sprite2D" type="Sprite2D" parent="."]
15+
texture = ExtResource("1_alri3")
16+
17+
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
18+
position = Vector2(-0.5, 0.5)
19+
shape = SubResource("RectangleShape2D_tjudb")
20+
21+
[node name="StunTimer" type="Timer" parent="."]
22+
one_shot = true
23+
24+
[node name="Label" type="Label" parent="."]
25+
offset_left = -64.0
26+
offset_top = 70.0
27+
offset_right = 64.0
28+
offset_bottom = 94.0
29+
horizontal_alignment = 1
30+
31+
[connection signal="timeout" from="StunTimer" to="." method="_on_stun_timer_timeout"]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
extends Label
2+
class_name Prompt
3+
4+
5+
func show_whose_it(it_name : String) -> void:
6+
match it_name:
7+
"you":
8+
text = "Tag, you are it!"
9+
_:
10+
text = "Tag, {0} is it!".format([it_name])
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[remap]
2+
3+
importer="texture"
4+
type="CompressedTexture2D"
5+
uid="uid://dkk04ow5f8clu"
6+
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
7+
metadata={
8+
"vram_texture": false
9+
}
10+
11+
[deps]
12+
13+
source_file="res://icon.svg"
14+
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
15+
16+
[params]
17+
18+
compress/mode=0
19+
compress/high_quality=false
20+
compress/lossy_quality=0.7
21+
compress/hdr_compression=1
22+
compress/normal_map=0
23+
compress/channel_pack=0
24+
mipmaps/generate=false
25+
mipmaps/limit=-1
26+
roughness/mode=0
27+
roughness/src_normal=""
28+
process/fix_alpha_border=true
29+
process/premult_alpha=false
30+
process/normal_map_invert_y=false
31+
process/hdr_as_srgb=false
32+
process/hdr_clamp_exposure=false
33+
process/size_limit=0
34+
detect_3d/compress_to=1
35+
svg/scale=1.0
36+
editor/scale_with_editor_scale=false
37+
editor/convert_colors_with_editor_theme=false
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
extends Node
2+
class_name Referee
3+
4+
var path_to_whose_it : NodePath
5+
6+
@export_file("*.tres; resource", "*.json; json") var save_file : String = "" #haven't done json yet
7+
@export_node_path("Character") var path_to_who_starts_as_it := ^"GameLayer/Player"
8+
9+
@onready var player := %Player as Character
10+
@onready var other_alice := %OtherAlice as Character
11+
@onready var other_bob := %OtherBob as Character
12+
13+
@onready var prompt := %Prompt as Prompt
14+
@onready var file_dialogue := %FileDialogue as FileDialog
15+
16+
17+
func _ready() -> void:
18+
var whose_it := get_node(path_to_who_starts_as_it) as Character
19+
update_whose_it(whose_it)
20+
21+
if save_file != "":
22+
open(save_file)
23+
24+
25+
func _unhandled_input(event: InputEvent) -> void:
26+
if event.is_action_pressed("save"):
27+
file_dialogue.file_mode = FileDialog.FILE_MODE_SAVE_FILE
28+
file_dialogue.visible = true
29+
elif event.is_action_pressed("open"):
30+
file_dialogue.file_mode = FileDialog.FILE_MODE_OPEN_FILE
31+
file_dialogue.visible = true
32+
33+
34+
func update_whose_it(whose_it : Character) -> void:
35+
prompt.show_whose_it(whose_it.character_name)
36+
path_to_whose_it = whose_it.get_path()
37+
var characters = get_tree().get_nodes_in_group(Character.CHARACTER_GROUP)
38+
for character in characters as Array[Character]:
39+
character.path_to_whose_it = path_to_whose_it
40+
41+
42+
func tag_character(character_tagged : Character) -> void:
43+
character_tagged.stun(character_tagged.stun_duration)
44+
update_whose_it(character_tagged)
45+
46+
47+
func serialize() -> RefereeResource:
48+
var referee_resource := RefereeResource.new()
49+
referee_resource.path_to_whose_it = path_to_whose_it
50+
referee_resource.path_to_who_starts_as_it = path_to_who_starts_as_it
51+
referee_resource.player_resource = player.serialize()
52+
referee_resource.other_alice_resource = other_alice.serialize()
53+
referee_resource.other_bob_resource = other_bob.serialize()
54+
referee_resource.prompt_text = prompt.text
55+
return referee_resource
56+
57+
58+
func deserialize(referee_resource : RefereeResource) -> void:
59+
prompt.text = referee_resource.prompt_text
60+
other_bob.deserialize(referee_resource.other_bob_resource)
61+
other_alice.deserialize(referee_resource.other_alice_resource)
62+
player.deserialize(referee_resource.player_resource)
63+
path_to_who_starts_as_it = referee_resource.path_to_who_starts_as_it
64+
path_to_whose_it = referee_resource.path_to_whose_it
65+
update_whose_it(get_node(path_to_whose_it))
66+
67+
68+
func save(file_name : String) -> void:
69+
var referee_resource : RefereeResource = serialize()
70+
ResourceSaver.save(referee_resource, file_name)
71+
72+
73+
func open(file_name : String) -> void:
74+
var referee_resource := load(file_name) as RefereeResource
75+
deserialize(referee_resource)
76+
77+
78+
func _on_player_tagged(target : Character) -> void:
79+
tag_character(target)
80+
81+
82+
func _on_other_alice_tagged(target : Character) -> void:
83+
tag_character(target)
84+
85+
86+
func _on_other_bob_tagged(target : Character) -> void:
87+
tag_character(target)
88+
89+
90+
func _on_file_dialogue_file_selected(path: String) -> void:
91+
match file_dialogue.file_mode:
92+
FileDialog.FILE_MODE_SAVE_FILE:
93+
save(path)
94+
FileDialog.FILE_MODE_OPEN_FILE:
95+
open(path)
96+
97+
98+
func _on_file_dialogue_visibility_changed() -> void:
99+
var pause : bool = file_dialogue.visible
100+
$GameLayer.process_mode = Node.PROCESS_MODE_DISABLED if pause else Node.PROCESS_MODE_INHERIT

0 commit comments

Comments
 (0)