Methoden anderer Units nutzen

Für Fragen von Einsteigern und Programmieranfängern...
tightTannic
Beiträge: 20
Registriert: Di 31. Jan 2017, 19:46
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Methoden anderer Units nutzen

Beitrag von tightTannic »

Hallo,
ich progge schon ein kleines Weilchen an einem Game herum;
Seit dem ich den Quellcode in 3 Units unterteilt habe (Verwaltung mehrer Units in einer Anwendung ist für mich ein neues Thema),
bekämpfe ich gerade zu eine Kaskade von Fehlerfluten die auf mich einstürzen. Weniger blümerant;
das Projekt lässt sich nicht mehr kompilieren :(

Die drei Units nutze ich grundlegend zur Strukturierung des Codes
unit3 : Sammlung von records und arrays
unit2 : Sammlung von kleineren Methoden, die in unit1 (quasi der Arbeitsplatz indem ich progge) der Übersichtlichkeit wegen nur stören würden.
in unit2 ist zudem Die Funktion, die beispielweise die arrays of Trecord füllt, was für mich vorübergehend ein externe Datei darstellt, in der die "GameData" gespeichert liegt.
unit1 : Hauptunit


In unit2 steht nun bei uses unit3, und bei unit1 bei uses unit2.
Wenn ich in unit1 nun eine Methode aus unit2 aufrufen möchte habe ich mir das so vorgestellt :

Code: Alles auswählen

 
unit unit1; // main
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  ComCtrls, StdCtrls,          Unit2;
 
type
  { TForm1 }
 
    TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
    procedure startGame;
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.lfm}
 
{ TForm1 }     
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  constructData; // aus unit2 eine procedure, die arrays aus unit3 mit Info vollstopft
 
  // andere Mehoden
  startGame;
end;
 

Wie erwartet hat das nicht gefunzt :

Code: Alles auswählen

// unit1.pas(108,3) Error: Identifier not found "constructData"


also TForm. vor constructData geklatscht : Zielgerade (?)...

Code: Alles auswählen

 
// [...]
procedure TForm1.FormCreate(Sender: TObject);
begin
  TFmain.constructData;
 
  // andere Mehoden
  startGame;
end;

... jedoch wider gegen die Leitplanke gefahren :

Code: Alles auswählen

// Projekt kompilieren, Ziel: project1.exe: Exit code 1, Fehler: 2
// unit1.pas(108,30) Error: Only class class methods, class properties and class variables can be accessed in class methods
// unit1.pas(108,30) Error: Only class methods, class properties and class variables can be referred with class references

Mit der Nachricht kann ich nicht viel anfangen :/

Was für einen Zugriffsfehler mache ich hier ? Lässt sich die procedure nicht einfach durch

Code: Alles auswählen

constructData;
aufrufen, wie z.Bsp. round() aus uses Math. ?

Bezüglich der Frage(n) bin ich sicherlich bei "Einsteigerfragen" im richtigen Forum ..
Habe vor ein paar Jahren Lazarus in der Schule kennengelernt und code nun "freiwillig" hier und da mal, glaube aber dass einige Bildungslücken entstanden sind, was Delphi angeht,
da ich außerhalb der Schule SEHR UNSTRUKTURIERT lerne :]


Größten Dank, wenn Ihr mir weiterhelfen könntet :oops:



Hier noch unit2 in gekürzter Version

Code: Alles auswählen

 
unit Unit2; // data
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,                 Unit3;
 
type
  { TFmain }
  TFmain = class(TForm)
  private
    { private declarations }
  public
    { public declarations }
    procedure constructData;
    procedure addSoil(map,field,soil:Integer);
    function giveRessource(ressource:Tressource;ammount:integer):Tres_ammount;
  end;
 
implementation
 
procedure TFmain.constructData;
begin
 // 400 lines
end;
 
procedure TFmain.addSoil(map, field, soil: Integer);
begin
  // 1liner
end;
 
function TFmain.giveRessource(ressource: Tressource; ammount: integer
  ): Tres_ammount;
  var res_ammount:Tres_ammount;
begin
 // 3lines
end;
end.
 

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Methoden anderer Units nutzen

Beitrag von Mathias »

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
//  TFmain.constructData;
  Fmain.constructData// ersetzen.
 
  // andere Mehoden
  startGame;
end;


Ich denke, das hast du unit2 zu stark kürzt eingestellt, irgendwo müsste da

Code: Alles auswählen

var
  Fmain: TFmain

stehen, ausser du hast es gelöscht, aber dann müsste ein Fehler bei deiner *.lpr kommen.


Es gibt schon eine Möglichkeit, direkt Txxx.xxx aufzurufen, mit dem Schlüsselwort class, aber dies wird nur in sehr seltenen Fällen gebraucht.

Code: Alles auswählen

  { TForm1 }
 
  TForm1 = class(TForm)
  private
 
  public
   class procedure Test;
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
class procedure TForm1.Test;
begin
end;
 
begin
  TForm1.Test;
end.   
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

tightTannic
Beiträge: 20
Registriert: Di 31. Jan 2017, 19:46
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: Methoden anderer Units nutzen

Beitrag von tightTannic »

Ob ich

Code: Alles auswählen

var
  Fmain: TForm;
in unit1, unit2 oder in beide schreibe macht von der Fehlermeldung her keinen Unterschied. Fehlt es gänzlich, beschwert er sich, weil Fmain undefniert ist (logisch =).

Jedoch war bis gerade eben noch der Fehler drin, dass einmal in unit1 von Form1 und in unit2 von Fmain die rede war.
Nun beschwert sich der Compiler an der selben Stelle auf andere Weise :
unit1

Code: Alles auswählen

 procedure TFmain.FormCreate(Sender: TObject);
begin
  Fmain.constructData; //unit1.pas(104,9) Error: identifier idents no member "constructData"
 
  startGame;
end;
... soll heißen die procedur constructData ist nicht identifizierbar (?), dabei habe ich diese doch in unit2 (Kopfzeile in interface, Code in implementation)
deklariert und unit2 steht bei unit1 in uses :/
Zuletzt geändert von tightTannic am Mi 1. Feb 2017, 18:45, insgesamt 1-mal geändert.

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Methoden anderer Units nutzen

Beitrag von Mathias »

in unit1, unit2 oder in beide schreibe macht von der Fehlermeldung her keinen Unterschied.

Normalerweise macht Lazarus dies selbst.

Was passiert, wen du "fmain." und 2-3 Sekunden wartest ?
Kommt dann constructData in der Auswahl ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

tightTannic
Beiträge: 20
Registriert: Di 31. Jan 2017, 19:46
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: Methoden anderer Units nutzen

Beitrag von tightTannic »

ich kann ein ganze Reihe an procedures, propertys, functions etc auswählen (wohl die Standards, die ich kaum kenne)
aber kein constructData :(, auch keine anderen Methoden aus unit2

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Methoden anderer Units nutzen

Beitrag von Mathias »

Poste doch mal die ganze Unit2, ohne die 400 Linien.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

tightTannic
Beiträge: 20
Registriert: Di 31. Jan 2017, 19:46
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: Methoden anderer Units nutzen

Beitrag von tightTannic »

unit2

Code: Alles auswählen

unit Unit2; // data
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,                 Unit3;
 
type
  { TFmain }
  TFmain = class(TForm)
  private
    { private declarations }
  public
    { public declarations }
    procedure constructData;
    procedure addSoil(map,field,soil:Integer);
    function giveRessource(ressource:Tressource;ammount:integer):Tres_ammount;
  end;
 
var
  Fmain: TForm;
  i:integer;
 
implementation
 
procedure TFmain.constructData;
begin
end;
 
procedure TFmain.addSoil(map, field, soil: Integer);
begin
  MapList[map].Field[field].Soil:=SoilList[soil-1];
end;
 
function TFmain.giveRessource(ressource: Tressource; ammount: integer
  ): Tres_ammount;
  var res_ammount:Tres_ammount;
begin
  res_ammount.Ressource:=ressource;
  res_ammount.Value:=ammount;
  result:=res_ammount;
end;
 
end.
 


unit3

Code: Alles auswählen

unit Unit3; // scaff records
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils;
 
// Object Scaff
  type Tcategory=record
    Name:String[32];
    Health,Regeneration,Stamina:Integer;
    RecrutionCosts,Nimbleness,Intelligence,Strength,Tactic,BuildingAttack:Integer;
    Workforce:real;
  end;
 
  type TvicinityAdaption=record
    Vicinity:String[32]; // Tsoil.Name
    Ammount:Integer;
  end;
 
  type Ttroop=record
    Category:Tcategory;
    Health,Regeneration,Stamina,RecrutionCosts,Level,Owner:Integer;
    Attack,Defence:Integer;
    VicinityAdaption:TvicinityAdaption;
  end;
 
  type Tressource=record
    Name:String[32];
  end;
 
  type Tres_ammount=record
    Ressource:Tressource;
    Value:integer;
  end;
 
  type Tsoil=record
    Name:String[32];
    Gold_M,Food_M,Material_M,GemStone_M:Integer;
    Clearing_Boni:array of Tres_ammount;
    Clearing_Result:String[32];
  end;
 
  type Tprop=record
    Name:String[32];
    EffectID:String[4]; // Wonder : wnd1, Market : mrkt
  end;
 
  type Tbuilding=record
    Name:String[32];
    Health:Integer;
    BuildingCosts:Tres_ammount;
    Props:array of Tprop;
  end;
 
  type Tfield=record
    Soil:Tsoil;
    Building:Tbuilding;
    Garnision:Ttroop;
  end;
 
  type Tmap=record
    Name:String[32];
    Map_Length:Integer;
    Field:array of Tfield;
  end;
 
  type Tplayer=record
    Name:String[32];
    Gold,Food,Material,GemStone:Integer;
    Rooster:array of Ttroop;
  end;
 
  type Tgame=record
    Name:String[32];
    Map:Tmap;
    Player:array of Tplayer;
  end;
 
// List & Main Objects / Props Scaff
    var
      i:integer;
      Game:Tgame;
                 MapList:array of TMap;
                 SoilList:array of Tsoil;
 
      RessourceList:array of Tressource;
 
      BuildingList:array of Tbuilding;     TroopList:array of Ttroop;
      PropList:array of Tprop;             CategoryList:array of Tcategory;
 
implementation
 
end.

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Methoden anderer Units nutzen

Beitrag von Mathias »

Darf ich die Unit1 auch noch sehen ?

Ist dieser Code in der Unit 1 ?

Code: Alles auswählen

procedure TFmain.FormCreate(Sender: TObject);
begin
  Fmain.constructData; //unit1.pas(104,9) Error: identifier idents no member "constructData"
 
  startGame;
end;


Hast du zufällig in eine Fmain ind der Unit1 und in der Unit2 ?
Sowas dürfte nicht sein.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

tightTannic
Beiträge: 20
Registriert: Di 31. Jan 2017, 19:46
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: Methoden anderer Units nutzen

Beitrag von tightTannic »

Mathias hat geschrieben:Ist dieser Code in der Unit 1 ?

Code: Alles auswählen

procedure TFmain.FormCreate(Sender: TObject);
begin
  Fmain.constructData; //unit1.pas(104,9) Error: identifier idents no member "constructData"
 
  startGame;
end;

Ja, der ist aus der unit1.

Unit1

Code: Alles auswählen

unit Unit1; // main
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  ComCtrls, StdCtrls,          Unit2, Unit3;
 
type
  { TFmain }
 
    TFmain = class(TForm)
    CBsettingsReady: TCheckBox;
    Egame_name: TEdit;
    Eplayer_name: TEdit;
    Irecruitment: TImage;
    Iupgrade: TImage;
    Ibuilding: TImage;
    Iadministration: TImage;
    Ispectator: TImage;
    Ig_field: TImage;
    Iplay: TImage;
    LstartDifficulty: TLabel;
    LBmaps: TListBox;
    Psettings: TPanel;
    Pg_m_navi: TPanel;
    Pg_field: TPanel;
    Pg_menu: TPanel;
    Pgame: TPanel;
    RBrecruitment: TRadioButton;
    RBupgrade: TRadioButton;
    RBbuilding: TRadioButton;
    RBadministration: TRadioButton;
    RBspectator: TRadioButton;
    RGnavi: TRadioGroup;
    TBviewpoint: TTrackBar;
    TBstartDifficulty: TTrackBar;
 
    procedure FormChangeBounds(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure IadministrationMouseDown(Sender: TObject);
    procedure IadministrationMouseEnter(Sender: TObject);
    procedure IadministrationMouseLeave(Sender: TObject);
    procedure IadministrationMouseUp(Sender: TObject);
    procedure IbuildingMouseDown(Sender: TObject);
    procedure IbuildingMouseEnter(Sender: TObject);
    procedure IbuildingMouseLeave(Sender: TObject);
    procedure IbuildingMouseUp(Sender: TObject);
    procedure IrecruitmentClick(Sender: TObject);
    procedure IrecruitmentMouseDown(Sender: TObject);
    procedure IrecruitmentMouseEnter(Sender: TObject);
    procedure IrecruitmentMouseLeave(Sender: TObject);
    procedure IrecruitmentMouseUp(Sender: TObject);
    procedure IspectatorMouseDown(Sender: TObject);
    procedure IspectatorMouseEnter(Sender: TObject);
    procedure IspectatorMouseLeave(Sender: TObject);
    procedure IspectatorMouseUp(Sender: TObject);
    procedure IupgradeMouseDown(Sender: TObject);
    procedure IupgradeMouseEnter(Sender: TObject);
    procedure IupgradeMouseLeave(Sender: TObject);
    procedure IupgradeMouseUp(Sender: TObject);
    procedure IplayClick(Sender: TObject);
    procedure IplayMouseDown(Sender: TObject);
    procedure IplayMouseEnter(Sender: TObject);
    procedure IplayMouseLeave(Sender: TObject);
    procedure IplayMouseUp(Sender: TObject);
    procedure LBmapsSelectionChange(Sender: TObject);
    procedure RGnaviChangeBounds(Sender: TObject);
    procedure TBstartDifficultyChange(Sender: TObject);
    procedure TBviewpointChange(Sender: TObject);
    procedure TBviewpointChangeBounds(Sender: TObject);
    procedure TBviewpointClick(Sender: TObject);
 
  private
    { private declarations }
  public
    { public declarations }
    procedure adjustMainPanel(panel: TPanel);
    procedure adjustGame;
 
    procedure startGame;
    procedure setStartValues(player,difficulty:integer);
    procedure resetSettings;
    procedure fadeAllNaviImages;
    procedure showPanel(panel:TPanel);
    procedure addAllAvailableMapsToList;
 
    procedure drawField(index:integer);
 
    function getVicinity(field:Tfield):String;
    function getVicinityBoni(troop:Ttroop;vicinity:String):Integer;
  end;
 
implementation
 
{$R *.lfm}
 
{ TFmain }
 
procedure TFmain.FormCreate(Sender: TObject);
begin
  Fmain.constructData;
 
  // loading Timages
  Iplay.Picture.loadFromFile('data\img\Timage\play_f.png');
 
  startGame;
end;
 
procedure TFmain.IadministrationMouseDown(Sender: TObject);
begin
  fadeAllNaviImages;
  Iadministration.Picture.loadFromFile('data\img\Timage\administration_f.png');
end;
 
procedure TFmain.IadministrationMouseEnter(Sender: TObject);
begin
  Iadministration.Picture.loadFromFile('data\img\Timage\administration_h.png');
end;
 
procedure TFmain.IadministrationMouseLeave(Sender: TObject);
begin
  if RBadministration.Checked=True then Iadministration.Picture.loadFromFile('data\img\Timage\administration.png')
    else Iadministration.Picture.loadFromFile('data\img\Timage\administration_f.png');
end;
 
procedure TFmain.IadministrationMouseUp(Sender: TObject);
begin
  Iadministration.Picture.loadFromFile('data\img\Timage\administration_h.png');
  RBadministration.Checked:=True;
end;
 
procedure TFmain.IbuildingMouseDown(Sender: TObject);
begin
  fadeAllNaviImages;
  Ibuilding.Picture.loadFromFile('data\img\Timage\building_f.png');
end;
 
procedure TFmain.IbuildingMouseEnter(Sender: TObject);
begin
  Ibuilding.Picture.loadFromFile('data\img\Timage\building_h.png');
end;
 
procedure TFmain.IbuildingMouseLeave(Sender: TObject);
begin
  if RBbuilding.Checked=True then Ibuilding.Picture.loadFromFile('data\img\Timage\building.png')
    else Ibuilding.Picture.loadFromFile('data\img\Timage\building_f.png');
end;
 
procedure TFmain.IbuildingMouseUp(Sender: TObject);
begin
  Ibuilding.Picture.loadFromFile('data\img\Timage\building_h.png');
  RBbuilding.Checked:=True;
end;
 
procedure TFmain.IrecruitmentClick(Sender: TObject);
begin
end;
 
procedure TFmain.IrecruitmentMouseDown(Sender: TObject);
begin
  fadeAllNaviImages;
  Irecruitment.Picture.loadFromFile('data\img\Timage\recruitment_f.png');
end;
 
procedure TFmain.IrecruitmentMouseEnter(Sender: TObject);
begin
  Irecruitment.Picture.loadFromFile('data\img\Timage\recruitment_h.png');
end;
 
procedure TFmain.IrecruitmentMouseLeave(Sender: TObject);
begin
  if RBrecruitment.Checked=True then Irecruitment.Picture.loadFromFile('data\img\Timage\recruitment.png')
    else Irecruitment.Picture.loadFromFile('data\img\Timage\recruitment_f.png');
end;
 
procedure TFmain.IrecruitmentMouseUp(Sender: TObject);
begin
  Irecruitment.Picture.loadFromFile('data\img\Timage\recruitment_h.png');
  RBrecruitment.Checked:=True;
end;
 
procedure TFmain.IspectatorMouseDown(Sender: TObject);
begin
  fadeAllNaviImages;
  Ispectator.Picture.loadFromFile('data\img\Timage\spectator_f.png');
end;
 
procedure TFmain.IspectatorMouseEnter(Sender: TObject);
begin
  Ispectator.Picture.loadFromFile('data\img\Timage\spectator_h.png');
end;
 
procedure TFmain.IspectatorMouseLeave(Sender: TObject);
begin
  if RBspectator.Checked=True then Ispectator.Picture.loadFromFile('data\img\Timage\spectator.png')
    else Ispectator.Picture.loadFromFile('data\img\Timage\spectator_f.png');
end;
 
procedure TFmain.IspectatorMouseUp(Sender: TObject);
begin
  Ispectator.Picture.loadFromFile('data\img\Timage\spectator_h.png');
  RBspectator.Checked:=True;
end;
 
procedure TFmain.IupgradeMouseDown(Sender: TObject);
begin
  fadeAllNaviImages;
  Iupgrade.Picture.loadFromFile('data\img\Timage\upgrade_f.png');
end;
 
procedure TFmain.IupgradeMouseEnter(Sender: TObject);
begin
  Iupgrade.Picture.loadFromFile('data\img\Timage\upgrade_h.png');
end;
 
procedure TFmain.IupgradeMouseLeave(Sender: TObject);
begin
  if RBupgrade.Checked=True then Iupgrade.Picture.loadFromFile('data\img\Timage\upgrade.png')
    else Iupgrade.Picture.loadFromFile('data\img\Timage\upgrade_f.png');
end;
 
procedure TFmain.IupgradeMouseUp(Sender: TObject);
begin
  Iupgrade.Picture.loadFromFile('data\img\Timage\upgrade_h.png');
  RBupgrade.Checked:=True;
end;
 
procedure TFmain.IplayClick(Sender: TObject);
begin
  if CBsettingsReady.Checked=True then begin
    Game.Name:=Egame_name.Text;
 
    // loading map
    for i := 0 to LBmaps.Items.Count -1 do
    begin
      if LBmaps.Selected[i] then begin
        Game.Map:=MapList[i];
      end;
    end;
 
    setLength(Game.Player, 1);
    Game.Player[0].Name:=Eplayer_name.Text;
    setStartValues(0, TBstartDifficulty.Position);
 
    TBviewpoint.Max:=Game.Map.Map_Length;
 
    fadeAllNaviImages;
    RBadministration.Checked:=True;
    Iadministration.Picture.loadFromFile('data\img\Timage\administration.png');
 
    showPanel(Pgame);
    //adjustMainPanel(Pgame);
  end;
end;
 
procedure TFmain.IplayMouseDown(Sender: TObject);
begin
  Iplay.Picture.loadFromFile('data\img\Timage\play_f.png');
end;
 
procedure TFmain.IplayMouseEnter(Sender: TObject);
begin
  Iplay.Picture.loadFromFile('data\img\Timage\play_h.png');
end;
 
procedure TFmain.IplayMouseLeave(Sender: TObject);
begin
  Iplay.Picture.loadFromFile('data\img\Timage\play.png');
end;
 
procedure TFmain.IplayMouseUp(Sender: TObject);
begin
  Iplay.Picture.loadFromFile('data\img\Timage\play_h.png');
end;
 
procedure TFmain.LBmapsSelectionChange(Sender: TObject);
begin
  for i := 0 to LBmaps.Items.Count -1 do
  begin
    if LBmaps.Selected[i] then begin
      CBsettingsReady.Checked:=True;
      Iplay.Picture.loadFromFile('data\img\Timage\play.png');
    end;
  end;
end;
 
procedure TFmain.RGnaviChangeBounds(Sender: TObject);
begin
  fadeAllNaviImages;
  if RBrecruitment.Checked=True then begin
    Irecruitment.Picture.loadFromFile('data\img\Timage\recruitment.png');
  end else if RBupgrade.Checked=True then begin
    Iupgrade.Picture.loadFromFile('data\img\Timage\upgrade.png');
  end else if RBbuilding.Checked=True then begin
    Ibuilding.Picture.loadFromFile('data\img\Timage\building.png');
  end else if RBadministration.Checked=True then begin
    Iadministration.Picture.loadFromFile('data\img\Timage\administration.png');;
  end else if RBspectator.Checked=True then begin
    Ispectator.Picture.loadFromFile('data\img\Timage\spectator.png');
  end;
end;
 
procedure TFmain.TBstartDifficultyChange(Sender: TObject);
begin
  case TBstartDifficulty.Position of
    1: LstartDifficulty.Caption:='Start Difficulty : Lush';
    2: LstartDifficulty.Caption:='Start Difficulty : Good';
    3: LstartDifficulty.Caption:='Start Difficulty : Medium';
    4: LstartDifficulty.Caption:='Start Difficulty : Rare';
    5: LstartDifficulty.Caption:='Start Difficulty : Barely';
  end;
end;
 
procedure TFmain.TBviewpointChange(Sender: TObject);
begin
  adjustGame;
end;
 
procedure TFmain.TBviewpointChangeBounds(Sender: TObject);
begin
  adjustGame;
end;
 
procedure TFmain.TBviewpointClick(Sender: TObject);
begin
  adjustGame;
end;
 
procedure TFmain.FormChangeBounds(Sender: TObject);
begin
  adjustGame;
end;
 
procedure TFmain.adjustMainPanel(panel: TPanel);
begin
  panel.Width:=Fmain.Width;
  panel.Height:=Fmain.Height;
  panel.Left:=0;
  panel.Top:=0;
end;
 
procedure TFmain.adjustGame;
begin
  adjustMainPanel(Pgame);
 
  // adjust Pgame_game
  begin
  Pg_menu.Width:=Pg_menu.Height;
  Pg_menu.Height:=Pgame.Height;
  Pg_menu.Left:=0;
  Pg_menu.Top:=0;
    Pg_m_navi.Height:=Pgame.Height;
    Pg_m_navi.Width:=trunc((Pg_m_navi.Height-12)/5*1)+4;
 
    Irecruitment.Width:=trunc((Pg_m_navi.Height-12)/5*1);
    Irecruitment.Height:=Irecruitment.Width;
    Irecruitment.Left:=2;
    Irecruitment.Top:=2;
 
    Iupgrade.Width:=Irecruitment.Width;
    Iupgrade.Height:=Irecruitment.Width;
    Iupgrade.Left:=2;
    Iupgrade.Top:=trunc((Pg_m_navi.Height-12)/5*1)+4;
 
    Ibuilding.Width:=Irecruitment.Width;
    Ibuilding.Height:=Irecruitment.Width;
    Ibuilding.Left:=2;
    Ibuilding.Top:=trunc((Pg_m_navi.Height-12)/5*2)+6;
 
    Iadministration.Width:=Irecruitment.Width;
    Iadministration.Height:=Irecruitment.Width;
    Iadministration.Left:=2;
    Iadministration.Top:=trunc((Pg_m_navi.Height-12)/5*3)+8;
 
    Ispectator.Width:=Irecruitment.Width;
    Ispectator.Height:=Irecruitment.Width;
    Ispectator.Left:=2;
    Ispectator.Top:=trunc((Pg_m_navi.Height-12)/5*4)+10;
 
  Pg_field.Width:=Pgame.Width-Pg_menu.Width;
  Pg_field.Height:=Pgame.Height;
  Pg_field.Left:=Pg_menu.Width;
  Pg_field.Top:=0;
    TBviewpoint.Width:=Pgame.Width-Pg_menu.Width-2;
    TBviewpoint.Top:=Pg_field.Height-(TBviewpoint.Height+4);
 
    Ig_field.Height:=Pg_field.Height-(TBviewpoint.Height+8);
    Ig_field.Width:=Game.Map.Map_Length*Ig_field.Height;
    Ig_field.Top:=2;
    Ig_field.Left:=(Screen.Width - Fmain.Width) div 2;
  end;
 
  //
 
  // clear canvas
  With Ig_field.Canvas do begin
    Brush.Color:=clBlack;
    FillRect(0,0,Width,Height);
  end;
 
  // redraw canvas (all fields)
  for i:=0 to Game.Map.Map_Length-1 do begin
    drawField(i);
  end;
end;
 
procedure TFmain.startGame;
begin
  resetSettings;
  showPanel(Psettings);
end;
 
procedure TFmain.setStartValues(player, difficulty: integer);
begin
  Game.Player[player].Food:=difficulty*100;
  Game.Player[player].GemStone:=difficulty*100-100;
  Game.Player[player].Gold:=difficulty*150;
  Game.Player[player].Material:=difficulty*50;
end;
 
procedure TFmain.resetSettings;
begin
  Egame_name.Text:='game '+FormatDateTime('yy-mm-dd-hh-nn-ss', now);
  Eplayer_name.Text:='player name';
  addAllAvailableMapsToList;
end;
 
procedure TFmain.fadeAllNaviImages;
begin
  Irecruitment.Picture.loadFromFile('data\img\Timage\recruitment_f.png');
  Iupgrade.Picture.loadFromFile('data\img\Timage\upgrade_f.png');
  Ibuilding.Picture.loadFromFile('data\img\Timage\building_f.png');
  Iadministration.Picture.loadFromFile('data\img\Timage\administration_f.png');
  Ispectator.Picture.loadFromFile('data\img\Timage\spectator_f.png');
end;
 
procedure TFmain.showPanel(panel: TPanel);
begin
  Pgame.Visible:=False;
  Psettings.Visible:=False;
 
  panel.Top:=0;
  panel.Left:=0;
  panel.Visible:=True;
 
  Fmain.Width:=panel.Width;
  Fmain.Height:=panel.Height;
end;
 
procedure TFmain.addAllAvailableMapsToList;
begin
  LBmaps.Items.Clear;
  for i:=0 to length(MapList)-1 do begin
    LBmaps.Items.Add(MapList[i].Name);
  end;
end;
 
procedure TFmain.drawField(index: integer);
begin
  // loading image material
  case Game.Map.Field[index].Soil.Name of
    'Meadow'                           : Ig_field.Canvas.Brush.Color:=RGBToColor(163,173,121);
    'Hill'                             : Ig_field.Canvas.Brush.Color:=RGBToColor(182,170,133);
    'Acre'                             : Ig_field.Canvas.Brush.Color:=RGBToColor(155,201,33);
    'Forest'                           : Ig_field.Canvas.Brush.Color:=RGBToColor(71,119,47);
    'Fertile Forest'                   : Ig_field.Canvas.Brush.Color:=RGBToColor(0,147,0);
    'Stone Deposit'                    : Ig_field.Canvas.Brush.Color:=RGBToColor(145,138,122);
    'Gold Deposit'                     : Ig_field.Canvas.Brush.Color:=RGBToColor(255,240,124);
    'Gem Stone Deposit'                      : Ig_field.Canvas.Brush.Color:=RGBToColor(163,228,255);
    'Swamp'                            : Ig_field.Canvas.Brush.Color:=RGBToColor(133,114,168);
    'Desert'                           : Ig_field.Canvas.Brush.Color:=RGBToColor(211,182,60);
    'Waters'                           : Ig_field.Canvas.Brush.Color:=RGBToColor(71,149,193);
  //else begin
  //    showMessage('ERROR : unknown Soil.Name in drawField('+intToStr(index)+') _ Intended Soil : '+Game.Map.Field[index].Soil.Name);
  //    exit;
  //  end;
  end;
 
  // placing image
  Ig_field.Canvas.FillRect(index*Ig_field.Height,0,index*Ig_field.Height+Ig_field.Height,Ig_field.Height);
 
end;
 
function TFmain.getVicinity(field: Tfield): String;
begin
  result:=field.Soil.Name;
end;
 
function TFmain.getVicinityBoni(troop: Ttroop; vicinity: String): Integer;
begin
  if troop.VicinityAdaption.Vicinity=vicinity then result:=troop.VicinityAdaption.Ammount else result:=0;
end;
 
end.

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Methoden anderer Units nutzen

Beitrag von Mathias »

Irgendwie fehlt folgende Deklaration in der Unit 1.

Code: Alles auswählen

var
  Fmain: TForm;


Lässt sich der Code Kompilieren, wen du folgendes weglässt ?

Code: Alles auswählen

Fmain.constructData; 
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

tightTannic
Beiträge: 20
Registriert: Di 31. Jan 2017, 19:46
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: Methoden anderer Units nutzen

Beitrag von tightTannic »

ich hab das Programm mit und ohne

Code: Alles auswählen

var
 Fmain: TForm;
in unit1 versucht zu kompilieren
führte alles zur oben beannten Fehlermeldung :
Unit1.pas(107,9) Error: identifier idents no member "constructData"

Wenn ich

Code: Alles auswählen

Fmain.constructData;
auskommentiere und dann kompiliere, öffnet sich ein Fenster mit der Caption "Debuggerausnahmen-Nachricht"
und der Meldung :
"Projekt project1 hat Exception-Klasse >>EReadError<< ausgelöst mit der Meldung:
Invalid value for property
Bei der Addresse 4388AB"


zudem habe ich dann die Möglichkeit "Halt" und "Fortsetzen"
Setzte ich fort kommt ein selbes Fenster mit :
"Projekt project1 hat Exception-Klasse >>EReadError<< ausgelöst mit der Meldung:
Error reading Fmain.OnChangeBounds: Invalid value for property
Bei der Addresse 4388AB"


bei "Halt" öffnet sich im Quelltexteditor "control.inc" mit dem Marker bei Zeile 3657

Code: Alles auswählen

procedure TControl.ReadState(Reader: TReader);
begin
  Include(FControlFlags, cfLoading);
  DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TControl.ReadState'){$ENDIF};
  try
    Include(FControlState, csReadingState);
    inherited ReadState(Reader)// Marker
  finally
    Exclude(FControlState, csReadingState);
    EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TControl.ReadState'){$ENDIF};
  end;
end


Also faktisch lässt sich die Anwendung kompilieren; führe ich sie dann aus, kommt eine Fehlermeldung betreffend der procedure Fmain.OnChangeBounds (siehe Anhang)
Dateianhänge
Fehlermeldung betreffend der procedure Fmain.OnChangeBounds beim Start der project1.exe
Fehlermeldung betreffend der procedure Fmain.OnChangeBounds beim Start der project1.exe
error#1.JPG (20.64 KiB) 2148 mal betrachtet

Jole
Beiträge: 114
Registriert: Fr 4. Jul 2014, 14:39
OS, Lazarus, FPC: Linux
CPU-Target: amd64

Re: Methoden anderer Units nutzen

Beitrag von Jole »

Ich hab mal ne blöde frage:
Was passiert eigentlich wenn in unit1 und unit2 für die Klassen ein der der selbe Bezeichner verwendet wird?
unit unit1:

Code: Alles auswählen

 
type
  { TFmain }
 
    TFmain = class(TForm)
 

unit unit2:

Code: Alles auswählen

 
type
  { TFmain }
  TFmain = class(TForm)
 

So wie ich das sehe, überschreibt die Klasse aus unit1 die Klasse aus unit2 und du kannst nicht mehr darauf zugreifen.

tightTannic
Beiträge: 20
Registriert: Di 31. Jan 2017, 19:46
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: Methoden anderer Units nutzen

Beitrag von tightTannic »

Jole hat geschrieben:Ich hab mal ne blöde frage:
Was passiert eigentlich wenn in unit1 und unit2 für die Klassen ein der der selbe Bezeichner verwendet wird?

So wie ich das sehe, überschreibt die Klasse aus unit1 die Klasse aus unit2 und du kannst nicht mehr darauf zugreifen.


So blöd finde ich die Frage gar nicht :)

Das Problem dabei ist nur, wenn ich aus unit1

Code: Alles auswählen

  { TFmain }
 
    TFmain = class(TForm)
entferne, dann kann der Compiler nichts mehr mit den folgendern Methoden usw. anfangen

Code: Alles auswählen

 
// wie beispielsweise
    Eplayer_name: TEdit;
    Irecruitment: TImage;
    RGnavi: TRadioGroup;
 
    procedure FormChangeBounds(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
    procedure adjustMainPanel(panel: TPanel);
    procedure adjustGame;
 
    procedure startGame;
    procedure setStartValues(player,difficulty:integer);
    procedure resetSettings;
 
    procedure drawField(index:integer);
    function getVicinityBoni(troop:Ttroop;vicinity:String):Integer;
  end;

Kann man einer vordefinierten Klasse aus einer anderen unit nachträglich wie oben Methoden usw. zufügen?, anderen Falls hat die unit2 hier kaum einen Sinn, wenn ich nicht die selbe Klasse bearbeiten kann ( !? =/ )

tightTannic
Beiträge: 20
Registriert: Di 31. Jan 2017, 19:46
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: Methoden anderer Units nutzen

Beitrag von tightTannic »

tightTannic hat geschrieben:Kann man einer vordefinierten Klasse aus einer anderen unit nachträglich wie oben Methoden usw. zufügen?, anderen Falls hat die unit2 hier kaum einen Sinn, wenn ich nicht die selbe Klasse bearbeiten kann ( !? =/ )
...
ich habs geschnallt, kann auch einfach eine andere Klasse in unit2 deklarieren und die Methoden in unit1 verwenden :oops:

Also :
unit1

Code: Alles auswählen

type
  { TFmain }
    TFmain = class(TForm)
    procedure FormCreate(Sender: TObject);

unit2

Code: Alles auswählen

type
  { TFside }
  Tside = class(TForm)
  private
    { private declarations }
  public
    { public declarations }
    procedure constructData;
end;


ich kann nun in FormCreate (unit1) Tside.constructData; schreiben (constructData findet er sogar, wenn ich Tside. eingebe und 2 Sekunden warte).
Das ganze führt wieder zum Problem :
Dateianhänge
Only class methods ... can be referred with class references
Only class methods ... can be referred with class references

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Methoden anderer Units nutzen

Beitrag von Mathias »

Was passiert eigentlich wenn in unit1 und unit2 für die Klassen ein der der selbe Bezeichner verwendet wird?

Ich weis nicht wie tightTannic das hingekriegt hat. Wen ich an 2 Forms, den gleichen Namen geben will, motzt die IDE da schon.
Und wen man es irgendwie manuell ändert, wird es spätestens in der *.lpr-Datei bei FormCreate Probleme geben.

@tightTannic
Kannst du nicht mal dein ganzes Project als ZIP reinstellen, ich denke dein ganzes Project hat einen Knoten.
Aber bitte vorher die EXE entfernen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten