ebSkola

5.2 JSON serializācija un Resource sistēma

Stundas uzdevums: Saglabāt sarežģītus datu struktūras, izmantojot JSON un Godot Resource klases.

SR 2.4.17. Failu SR 2.4.16. Datu struktūras

80 min plāns: Teorija un paraugs (~10 min) · 1. uzdevums (~20 min) - pārvērs Dictionary par JSON · 2. uzdevums (~25 min) - nolasi JSON atpakaļ · 3. uzdevums (~20 min) - apstrādā bojātu JSON · Iesniegšana (~5 min).

Pirms sāc: atceries no Programmēšanas I JSON failus. Godot to dara JSON klase. Priekšrocība pret 5.1 metodi: JSON failu var atvērt un izlasīt ar acīm.

Teorija: JSON un Resources

JSON (JavaScript Object Notation) ir cilvēkam un mašīnai lasāms datu formāts. Godot piedāvā JSON klasi tā parsēšanai.

using Godot;
using Godot.Collections;

// Dictionary -> JSON string
Dictionary saveData = new();
saveData["player_name"] = "Anna";
saveData["level"] = 5;
saveData["inventory"] = new Array(); // var saturēt vēl Dictionary

string jsonStr = Json.Stringify(saveData, "  ");  // 2-space indent

// JSON string -> Dictionary
Json json = new Json();
Error err = json.Parse(jsonStr);
if (err == Error.Ok)
{
    Dictionary loaded = json.Data.AsGodotDictionary();
    string name = loaded["player_name"].AsString();
}

Resource ir Godot iebūvēta klase resursu (audio, attēli, custom data) saglabāšanai .tres failos.

Kā šo izmantot projektā

Atceries: ar redzamu efektu editorā nepietiek. Paskaidro, kura C# klase glabā stāvokli, kura metode to maina un kā Godot node struktūra izmanto šo kodu.

Pārbaudi: C# kods pārbauda failu kļūdas, validē datus, izmanto versijas lauku un pamato algoritmu sarežģītību.

public class PersistenceCheckpoint
{
    public string Lesson = "5.2 JSON serializācija un Resource sistēma";
    public bool UsesCSharp = true;
    public bool HandlesMissingFile = true;
    public bool ValidatesData = true;
    public bool DocumentsComplexity = true;
}

Praktiskie uzdevumi

1. uzdevums -

Pārvērs Dictionary par JSON

Beigās tavs saglabātais fails būs salasāms cilvēkam.

  1. Pārliecinies, ka faila sākumā ir using Godot.Collections;.
  2. Izveido Godot.Collections.Dictionary saveData = new();.
  3. Pievieno tam player_name, level un score.
  4. Pārvērs to ar string jsonStr = Json.Stringify(saveData, " ");.
  5. Ieraksti rezultātu failā user://save.json.
  6. Atver failu teksta redaktorā un apskati saturu.
  7. Pieraksti, ko dara otrais stringify arguments.

Gatavs, kad: fails save.json ir salasāms ar atkāpēm un satur visas trīs vērtības.

2. uzdevums -

Nolasi JSON atpakaļ

Beigās spēle atjaunos stāvokli no salasāma faila.

  1. Nolasi faila saturu ar GetAsText().
  2. Izveido Json json = new(); un izsauc json.Parse(text);.
  3. Paņem rezultātu ar Dictionary d = json.Data.AsGodotDictionary();.
  4. Izdrukā visas trīs vērtības.
  5. Pārbaudi, vai skaitlis ielādējas kā skaitlis, nevis kā teksts.
  6. Nomaini failā ar roku līmeņa vērtību un palaid vēlreiz.
  7. Pieraksti, kāpēc tas ir gan ērti, gan bīstami.

Gatavs, kad: izdrukātās vērtības sakrīt ar failā redzamajām, arī pēc tam, kad failu izlaboji ar roku.

3. uzdevums -

Apstrādā bojātu JSON

Beigās bojāts fails vairs nenogāzīs spēli.

  1. Atver save.json un izdzēs vienu figūriekavu.
  2. Palaid spēli un pieraksti, kas notiek.
  3. Pievieno pārbaudi Error err = json.Parse(text);.
  4. Pārbaudi if (err != Error.Ok) un izdrukā brīdinājumu.
  5. Atgriez tādā gadījumā noklusējuma vērtības.
  6. Palaid ar bojātu failu vēlreiz un pārliecinies, ka spēle turpina darboties.
  7. Salabo failu un pārbaudi, ka ielāde atkal strādā.

Gatavs, kad: ar bojātu JSON spēle parāda brīdinājumu un sāk ar noklusējuma vērtībām, nevis avarē.

Papildu uzdevums - Saglabā sarakstu JSON failā

Ja pamatdarbs ir gatavs, saglabā vairākus rezultātus.

  1. Izveido Godot.Collections.Array highscores = new();.
  2. Pievieno tam trīs Dictionary ierakstus ar vārdu un punktiem.
  3. Ieliec masīvu galvenajā Dictionary un saglabā.
  4. Nolasi to atpakaļ un izdrukā ciklā.
  5. Sakārto rezultātus dilstošā secībā pirms izdrukas.

Gatavs, kad: failā ir trīs rezultāti, un ielādējot tie izdrukājas no lielākā uz mazāko.

Ko sagatavo

Stundas mērķis: Tava spēle saglabā stāvokli salasāmā JSON failā, ielādē to atpakaļ ar pareiziem datu tipiem un neapstājas, ja fails ir bojāts.

GitHub krātuvē jābūt:

  1. Fails save.json paraugs un C# kods ar Json.Stringify un Parse.
  2. Ekrānuzņēmums ar Output paneli, kurā redzams brīdinājums par bojātu failu un noklusējuma vērtības.
  3. README.md: kāpēc salasāms saglabāšanas fails ir gan ērts, gan bīstams.

Kā iesniedz: Veic commit un push. Skolotāja norādītajā vietā ievieto tikai GitHub krātuves saiti; visiem prasītajiem failiem, README.md pierakstiem un pierādījumiem jābūt pašā krātuvē.

Biežākās kļūdas

  • Crash, parse JSON: Tukšs vai bojāts fails. Pārbaudi err == OK vienmēr.
  • Dictionary keys nav konsistenti: Lieto strukturas vai konstantes (kods centra).
  • Resource fails neielādējas: Path nepareizs vai resurss bojāts.

Godot ekrānuzņēmumi

Teksta redaktors atvērts ar savegame.json saturu: pretty-printed JSON ar player_name, hp, level, inventory array.
Teksta redaktors atvērts ar savegame.json saturu: pretty-printed JSON ar player_name, hp, level, inventory array.
Godot Inspector ar custom ItemResource: Name, Icon (texture preview), Max Stack, Value.
Godot Inspector ar custom ItemResource: Name, Icon (texture preview), Max Stack, Value.

Koda piemērs (paplašināts)

using Godot;
using Godot.Collections;
using System.Collections.Generic;

public partial class Player : CharacterBody2D
{
    private string playerName;
    private int hp;
    private int maxHp;
    private int level;
    private int xp;
    private Dictionary<string, int> inventory = new();

    public Godot.Collections.Dictionary ToDict()
    {
        Godot.Collections.Dictionary data = new();
        data["name"] = playerName;
        data["hp"] = hp;
        data["max_hp"] = maxHp;
        data["level"] = level;
        data["xp"] = xp;
        data["position_x"] = Position.X;
        data["position_y"] = Position.Y;

        Array inv = new();
        foreach ((string item, int count) in inventory)
        {
            Godot.Collections.Dictionary entry = new();
            entry["item"] = item;
            entry["count"] = count;
            inv.Add(entry);
        }
        data["inventory"] = inv;
        return data;
    }

    public void FromDict(Godot.Collections.Dictionary data)
    {
        playerName = data["name"].AsString();
        hp = data["hp"].AsInt32();
        maxHp = data["max_hp"].AsInt32();
        level = data["level"].AsInt32();
        xp = data["xp"].AsInt32();
        Position = new Vector2(data["position_x"].AsSingle(), data["position_y"].AsSingle());
    }
}
Save fails saturēs JSON ar player datiem; pēc load - viss state atjaunots korekti.