Problem z odczytem danych rekordów w oddzielnej formatce

0

Dzień dobry, na wstępie chciałem zaznaczyć, że nie jestem jakimś extra specjalistą w dziedzinie programowania, ale w celach
rekreacyjnych postanowiłem sobie nieco odświeżyć obiektowego pascala (nie ruszałem programowania od 11 lat) i zacząłem sobie dziś tworzyć klasę pod pseudo RPG'a w delphi XE8.

Podstawowe dane w pliku klasy (game.pas) umieściłem w rekordzie ze względu na czytelność kodu, a w przyszłości (kto wie) sporą ilość danych do przetworzenia.

Program testowy kompiluje się bez problemów, tylko problem pojawia się przy próbie odczytu zmiennych umieszczonych w rekordzie. Już podaję przykład kodu:

Z pliku game.pas (który jest rozszerzeniem głównej formatki i przechowuje funkcje i procedury typowo pod RPG'a)


type TPlayer = packed record

	var Health : integer;
	var Mana : integer;
	var Level : byte;
	var currentExp : integer;
	var ExpToNextLv : integer;
	var Gold : integer;
	var Attack : byte;
	var MagicAtk : byte;
	var Defence : byte;
	var MagicDef : byte;
	var Agility : byte;
	var Luck : byte;
	var HeroName : string;
	var HeroClass : string;
	var HeroDesc : string;

end;

Kiedy deklaruję ten rekord w głównej formatce (gameMain.pas) w ten sposób:

var Player : TPlayer; //Rekord z game.pas

To przy próbie odczytu

Label1.Caption := Format('[Lv. %d] %s (%d / %d) (%s)', [Player.Level, Player.HeroName, Player.currentExp, Player.ExpToNextLv, Player.pctView ]);

wszystkie wartości zwracają wartość 0 (zero) - a zmienne w rekordzie zmieniają wartości - za wyjątkiem funkcji player.pctView, która liczy procent zdobytego expa.
Natomiast po utworzeniu publicznych zmiennych w klasie i ustawianiu im wartości rekordów ich odczyt jest już poprawny, moje pytanie brzmi, co zepsułem w swojej klasie?
Załączam plik klasy do przejżenia, a tak wygląda sytuacja w kodzie głównej formatki:

unit gameMain;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, JvTimer, Vcl.ComCtrls,
  JvBaseDlg, JvProgressDialog, JvExComCtrls, JvProgressBar, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    ProgressBar: TJvProgressBar;
    Button1: TButton;
    JvTimer1: TJvTimer;
    procedure InitApplication(Sender: TObject);
    procedure JvTimer1Timer(Sender: TObject);
  private

  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses game;

var
  GameClass : TGame; //Klasa game
  Player : TPlayer; //Rekord TPlayer
{$R *.dfm}


procedure TForm1.InitApplication(Sender: TObject);
begin
  GameClass := TGame.Create;
  GameClass.Reset;
end;

procedure TForm1.JvTimer1Timer(Sender: TObject);
begin
GameClass.AddExp(1,1.2);
ProgressBar.Max := GameClass.ExpToNextLv;
ProgressBar.Position := GameClass.currentExp;
Label1.Caption := Format('[Lv. %d] %s (%d / %d) (%s)', [GameClass.Level, GameClass.HeroName, GameClass.currentExp, GameClass.ExpToNextLv, GameClass.pctView ]);
end;

end.

I w tej formie wszystko działa, ale jak GameClass zamienię na player, to już wartości są zerowe, mimo, iż dane w rekordzie się zmieniają.

2
Kamil Wabik napisał(a):

Podstawowe dane w pliku klasy (game.pas) umieściłem w rekordzie ze względu na czytelność kodu, a w przyszłości (kto wie) sporą ilość danych do przetworzenia.

Dlaczego w rekordzie i dlaczego w spakowanym rekordzie? No i dlaczego zadeklarowałeś pola tego rekordu jako zmienne (ze słówiem var), zamiast tak jak się to zwykle robi? Zresztą nieważne – klas użyj.

Kiedy deklaruję ten rekord w głównej formatce […]

Tego nie rób – dane dotyczące gry trzymaj w odpowiedzich klasach poza modułem formularza. Dalszej części nie będę komentował, dlatego że źle się za tę grę zabierasz. Ja rozumiem, że to nie ma być produkt komercyjny, a hobbystyczny projekt prostej gierki, ale zrób ją porządnie.

Najpierw odśwież sobie wiedzę z zakresu podstaw programowania (w tym obiektowego), bo masz małe braki. Później zastanów się i rozpisz sobie funkcjonalność tej gry, jeśli jest ona zbyt duża aby wszystko trzymać w głowie. A jak już to wszystko będzie zrobione to dopiero wtedy usiądź do pisania kodu.

Przy czym kod gry powinieneś sobie rozbić na wiele małych klas o pojedynczej odpowiedzialności, tak aby kod był czytelny, łatwy do opanowania i rozwijania. Nie pisz go na pałę, deklarując masę zmiennych globalnych gdzie popadnie, bo po tygodniu pracy trudno będzie się zorientować gdzie co jest i jak działa (o ile w ogóle działa).


Jeśli potrzebujesz inspiracji to możesz przejrzeć źródła mojej platformówki, którą też dla rozrywki piszę w Pascalu (projekt dla Lazarusa) i też w trybie okienkowym, bez używania dedykowanych bibliotek. Co nieco na temat tej gry możesz przeczytać w wątku Deep Platformer – technologiczne demo prostej platformówki, natomiast w tym poście znajdziesz świeże źródła projektu. Poczytaj je – zobaczysz mniej więcej o co chodzi.

0

Czyli krótko mówiąc, cała klasa do przepisania...

I teraz po kolei:
Czemu w rekordzie? Cytując z waszego portalu: Rekordy są zorganizowaną strukturą danych, połączona w jedną całość. Jest to jakby zestaw zawierający określone elementy.
Czemu spakowane? Tutaj po prostu puściłem wodze fantazji, następnie, czemu dodałem słówko kluczowe var? Po prostu zapomniałem to wykasować. No i tu masz 100% rację, wziąłem się za ten plik na przysłowiową pałę, kompletnie nic nie przemyślałem, plan był taki, aby zrobić dziś odczyt i przetwarzanie podstawowych perków bohatera. Ja mam świadomość, że to jest ekhm... Miernie napisane i będzie wymagać poprawek, sporo poprawek, ale ja nie wiążę z tym jakichkolwiek planów, to jest tylko dla zabicia czasu na urlopie. :) Swoją drogą, czy to aż taka istotna różnica, czy w rekordzie jest var zmienna : typ, czy po prostu zmienna:typ?

1
Kamil Wabik napisał(a):

Czyli krótko mówiąc, cała klasa do przepisania...

I teraz po kolei:
Czemu w rekordzie? Cytując z waszego portalu: Rekordy są zorganizowaną strukturą danych, połączona w jedną całość. Jest to jakby zestaw zawierający określone elementy.

Ty mnie nie tłumacz czym są rekordy, bo ja wiem czym są, tylko mi napisz dlaczego wybrałeś prymitywne struktury zamiast klas, które oprócz „zorganizowanej struktury zawierającej określone elementy” mają też masę innych przydatnych funkcjonalności, takich jak hermetyzacja czy dziedziczenie.

[…] następnie, czemu dodałem słówko kluczowe var? Po prostu zapomniałem to wykasować.

Błędem nie jest to że zapomniałeś ich wykasować, a to, że je tam w ogóle wpisałeś. Musisz poczytać materiały na temat podstaw programowania, żeby opierać się na wiedzy, a nie na fantazjach.

Ja mam świadomość, że to jest ekhm... Miernie napisane i będzie wymagać poprawek, sporo poprawek […]

To nawet nie że będzie trzeba poprawiać. Chodzi o to, że pisanie kodu bez żadnego planu/schematu/pomyślunku będzie oznaczać ciągłe poprawianie obecnego kodu, zamiast skupić się na dodawaniu kolejnych funkcji. W rezultacie urlop Ci się skończy i będziesz miał niedokończony kłębek w kółko poprawianego spagetii.

Swoją drogą, czy to aż taka istotna różnica, czy w rekordzie jest var zmienna : typ, czy po prostu zmienna:typ?

Gdyby różnicy nie było, to by Ci ten kod działał, a tego wątku by nie było. ;)

0

Ciekawe określenie, ale nie odpowiedziałeś na moje pytanie, jaka jest różnica między:

type personalData = record
var yourName : string;
end;

a

type personalData = record
yourName : string;
end;

Odpowiadając na Twoje pytanie czemu wybrałem takie metody... Zacznijmy od początku, ostatni kontakt z takim jako tako
bardziej zaawansowanym programowaniem miałem w studium (nawiasem mówiąc, kiepskim studium), jakoś w 2007, albo w 2008, nie pamiętam już dokładnie.
I nie było nic porządnie wytłumaczone albo przećwiczone z programowania obiektowego.
Teraz mamy 2019, od czasu zakończenia studium informatycznego (1 rok, a z samego programowania to zajęć było jakieś 10 godzin ) nie miałem nic zainstalowanego związanego z programowaniem, może po za n++ i jakieś tam proste skrypty PHP i trochę CSS, ale nie siadło mi to... Przez ponad dekadę komputer służył mi jako rozrywka (filmy, muzyka itp), dopiero nie dawno wpadłem na pomysł, by coś samemu ruszyć, na początek w pascalu, bo ani Unreal Engine, ani Unity nie ruszę - za stary już jestem :D
Braki w wiedzy zacząłem uzupełniać czytając poradniki, zarówno tu, jak i stackoverflow. Zaparłem się i zacząłem coś robić, wiadomo, poszło coś nie tak, przyszedłem po pomoc, no i okazało się, że zacząłem od nie tej strony co trzeba.

Dzięki za poświęcony czas i wskazanie właściwego toru, temat można uznać za zamknięty - wywaliłem ta klase do kosza. Za kilka dni spróbuję inaczej tą klasę zrobić, jak odświeżę sobie podstawy.
Bo za cholerę nie mam pojęcia co miałeś na myśli o hermetyzacji klasy.

0
Kamil Wabik napisał(a):

Ciekawe określenie, ale nie odpowiedziałeś na moje pytanie, jaka jest różnica między […]

Różnica w konstrukcji deklaracji pól jest opisana w dokumentacji:

Fields (Delphi)

The var keyword is optional. However, if it is not used, then all field declarations must occur before any property or method declarations. After any property or method declarations, the var may be used to introduce any additional field declarations.

W przypadku Twojego rekordu nie ma to znaczenia, dlatego powinieneś pola zadeklarować w standardowy sposób. Tym bardziej, że skoro nie wiesz jaka jest różnica pomiędzy tymi zapisami, to powinieneś wybrać ten podstawowy. ;)


Odpowiadając na Twoje pytanie czemu wybrałem takie metody... […] Braki w wiedzy zacząłem uzupełniać czytając poradniki, zarówno tu, jak i stackoverflow. Zaparłem się i zacząłem coś robić, wiadomo, poszło coś nie tak, przyszedłem po pomoc, no i okazało się, że zacząłem od nie tej strony co trzeba.

Spoko, działaj z tym projektem i nie zniechęcaj się – nie od razu Rzym zbudowano.

Za kilka dni spróbuję inaczej tą klasę zrobić, jak odświeżę sobie podstawy. Bo za cholerę nie mam pojęcia co miałeś na myśli o hermetyzacji klasy.

Hermetyzacja pozwala ukryć pewne składowe klasy, tak aby nie były widoczne na zewnątrz niej (np. z poziomu metod innej klasy czy z innego modułu), dzięki czemu pozostają wyłącznie do wewnętrznego użytku klasy.

0

Spędziłem noc nad podstawami, udało mi się przebudować tą klasę, przy okazji naprawiłem inne bugi :)
Dzięki @furious programming

1 użytkowników online, w tym zalogowanych: 0, gości: 1