Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a saving demo that uses custom resources #924

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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