Skip to content

Commit

Permalink
Add a saving demo that uses custom resources
Browse files Browse the repository at this point in the history
  • Loading branch information
nlupugla committed May 28, 2023
1 parent 3a38ab4 commit edd252a
Show file tree
Hide file tree
Showing 15 changed files with 692 additions and 0 deletions.
2 changes: 2 additions & 0 deletions loading/serialization_custom_resources/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf
2 changes: 2 additions & 0 deletions loading/serialization_custom_resources/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Godot 4+ specific ignores
.godot/
107 changes: 107 additions & 0 deletions loading/serialization_custom_resources/game/character.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
extends CharacterBody2D
class_name Character

const CHARACTER_GROUP := &"characters"

signal tagged(target : Character)

var move_direction : Vector2 = Vector2.ZERO
var path_to_whose_it : NodePath = ^""
var stunned : bool = false

@export var character_name := ""
@export var player_controlled := false
@export var base_speed : float = 100 # pixels per second
@export var it_speed_multiplier : float = 2.0
@export var stun_duration : float = 2.0 # seconds

@onready var timer := $StunTimer as Timer
@onready var label := $Label as Label


func _ready() -> void:
label.text = character_name


func _physics_process(_delta: float) -> void:
if player_controlled:
move_direction = Input.get_vector("left", "right", "up", "down")
elif is_it():
move_direction = position.direction_to(get_nearest_character().position)
else:
var whose_it := get_node(path_to_whose_it) as Character
move_direction = -1 * position.direction_to(whose_it.position) # move away from whose it
velocity = move_direction * get_speed()
var collided : bool = move_and_slide()
if not collided:
return
var collision : KinematicCollision2D = get_last_slide_collision()
var collieder = collision.get_collider()
if collieder is Character:
if is_it() and not stunned:
tagged.emit(collieder)


func is_it() -> bool:
return path_to_whose_it == get_path()


func stun(duration : float) -> void:
stunned = true
timer.wait_time = duration
timer.start()


func get_speed() -> float:
if stunned:
return 0.0
else:
return base_speed * it_speed_multiplier if is_it() else base_speed


func get_nearest_character() -> Character:
var nearest_character : Character = self
var nearest_dist_squared := INF
var dist_squared := 0.0

var characters = get_tree().get_nodes_in_group(CHARACTER_GROUP)
for character in characters as Array[Character]:
dist_squared = position.distance_squared_to(character.position)
if dist_squared > 0.0001 and dist_squared < nearest_dist_squared:
nearest_dist_squared = dist_squared
nearest_character = character
return nearest_character


func serialize() -> CharacterResource:
var character_resource := CharacterResource.new()
character_resource.character_name = character_name
character_resource.position = position
character_resource.move_direction = move_direction
character_resource.base_speed = base_speed
character_resource.it_speed_multiplier = it_speed_multiplier
character_resource.path_to_whose_it = path_to_whose_it
character_resource.player_controlled = player_controlled
character_resource.stunned = stunned
character_resource.stun_duration = stun_duration
character_resource.stun_time_left = timer.time_left
return character_resource


func deserialize(character_resource : CharacterResource) -> void:
if character_resource.stun_time_left > 0:
timer.start(character_resource.stun_time_left)
stun_duration = character_resource.stun_duration
stunned = character_resource.stunned
player_controlled = character_resource.player_controlled
path_to_whose_it = character_resource.path_to_whose_it
it_speed_multiplier = character_resource.it_speed_multiplier
base_speed = character_resource.base_speed
move_direction = character_resource.move_direction
position = character_resource.position
character_name = character_resource.character_name
label.text = character_name


func _on_stun_timer_timeout() -> void:
stunned = false
31 changes: 31 additions & 0 deletions loading/serialization_custom_resources/game/character.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[gd_scene load_steps=4 format=3 uid="uid://djbgtqgci6is1"]

[ext_resource type="Texture2D" uid="uid://dkk04ow5f8clu" path="res://icon.svg" id="1_alri3"]
[ext_resource type="Script" path="res://game/character.gd" id="1_dtr8n"]

[sub_resource type="RectangleShape2D" id="RectangleShape2D_tjudb"]
size = Vector2(128, 128)

[node name="Character" type="CharacterBody2D"]
collision_mask = 3
motion_mode = 1
script = ExtResource("1_dtr8n")

[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("1_alri3")

[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(-0.5, 0.5)
shape = SubResource("RectangleShape2D_tjudb")

[node name="StunTimer" type="Timer" parent="."]
one_shot = true

[node name="Label" type="Label" parent="."]
offset_left = -64.0
offset_top = 70.0
offset_right = 64.0
offset_bottom = 94.0
horizontal_alignment = 1

[connection signal="timeout" from="StunTimer" to="." method="_on_stun_timer_timeout"]
10 changes: 10 additions & 0 deletions loading/serialization_custom_resources/game/prompt.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
extends Label
class_name Prompt


func show_whose_it(it_name : String) -> void:
match it_name:
"you":
text = "Tag, you are it!"
_:
text = "Tag, {0} is it!".format([it_name])
1 change: 1 addition & 0 deletions loading/serialization_custom_resources/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions loading/serialization_custom_resources/icon.svg.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[remap]

importer="texture"
type="CompressedTexture2D"
uid="uid://dkk04ow5f8clu"
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
metadata={
"vram_texture": false
}

[deps]

source_file="res://icon.svg"
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]

[params]

compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
100 changes: 100 additions & 0 deletions loading/serialization_custom_resources/main.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
extends Node
class_name Referee

var path_to_whose_it : NodePath

@export_file("*.tres; resource", "*.json; json") var save_file : String = "" #haven't done json yet
@export_node_path("Character") var path_to_who_starts_as_it := ^"GameLayer/Player"

@onready var player := %Player as Character
@onready var other_alice := %OtherAlice as Character
@onready var other_bob := %OtherBob as Character

@onready var prompt := %Prompt as Prompt
@onready var file_dialogue := %FileDialogue as FileDialog


func _ready() -> void:
var whose_it := get_node(path_to_who_starts_as_it) as Character
update_whose_it(whose_it)

if save_file != "":
open(save_file)


func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("save"):
file_dialogue.file_mode = FileDialog.FILE_MODE_SAVE_FILE
file_dialogue.visible = true
elif event.is_action_pressed("open"):
file_dialogue.file_mode = FileDialog.FILE_MODE_OPEN_FILE
file_dialogue.visible = true


func update_whose_it(whose_it : Character) -> void:
prompt.show_whose_it(whose_it.character_name)
path_to_whose_it = whose_it.get_path()
var characters = get_tree().get_nodes_in_group(Character.CHARACTER_GROUP)
for character in characters as Array[Character]:
character.path_to_whose_it = path_to_whose_it


func tag_character(character_tagged : Character) -> void:
character_tagged.stun(character_tagged.stun_duration)
update_whose_it(character_tagged)


func serialize() -> RefereeResource:
var referee_resource := RefereeResource.new()
referee_resource.path_to_whose_it = path_to_whose_it
referee_resource.path_to_who_starts_as_it = path_to_who_starts_as_it
referee_resource.player_resource = player.serialize()
referee_resource.other_alice_resource = other_alice.serialize()
referee_resource.other_bob_resource = other_bob.serialize()
referee_resource.prompt_text = prompt.text
return referee_resource


func deserialize(referee_resource : RefereeResource) -> void:
prompt.text = referee_resource.prompt_text
other_bob.deserialize(referee_resource.other_bob_resource)
other_alice.deserialize(referee_resource.other_alice_resource)
player.deserialize(referee_resource.player_resource)
path_to_who_starts_as_it = referee_resource.path_to_who_starts_as_it
path_to_whose_it = referee_resource.path_to_whose_it
update_whose_it(get_node(path_to_whose_it))


func save(file_name : String) -> void:
var referee_resource : RefereeResource = serialize()
ResourceSaver.save(referee_resource, file_name)


func open(file_name : String) -> void:
var referee_resource := load(file_name) as RefereeResource
deserialize(referee_resource)


func _on_player_tagged(target : Character) -> void:
tag_character(target)


func _on_other_alice_tagged(target : Character) -> void:
tag_character(target)


func _on_other_bob_tagged(target : Character) -> void:
tag_character(target)


func _on_file_dialogue_file_selected(path: String) -> void:
match file_dialogue.file_mode:
FileDialog.FILE_MODE_SAVE_FILE:
save(path)
FileDialog.FILE_MODE_OPEN_FILE:
open(path)


func _on_file_dialogue_visibility_changed() -> void:
var pause : bool = file_dialogue.visible
$GameLayer.process_mode = Node.PROCESS_MODE_DISABLED if pause else Node.PROCESS_MODE_INHERIT
Loading

0 comments on commit edd252a

Please sign in to comment.