![]() |
Zugriff auf Komponenten in einer anderen Unit
Hi Leute,
ich hoffe ich hab hier für mein Problem die richtige Kategorie erwischt und mir auch eine einigermaßen passende Überschrift einfallen lassen. Jedenfalls geht es darum, dass ich ein Billard-ähnliches Prog schreiben will. Allerdings ist das von Billard noch etwas entfernt. Ich möchte vielmehr auf einem Billardtisch (ein Image) ein paar Kugel rumspringen lassen. Die Kugelmenge soll beliebig wählbar sein und die Kugeln sollen sowohl von den Wänden als auch voneinander abprallen. Ich habe es schon so weit, dass die Kugeln von den Wänden reflektiert werden und ich auch beliebig viele Kugeln erstellen kann. Das habe ich so gelöst, dass ich in einer weiteren Unit "Kugeln" einen Typ TBall erstellt habe, der Prozeduren zum bewegen, darstellen, createn usw besitzt. Es sind auch Variablen enthalten, die die Position der Kugel etc beinhalten. In der Haupt-Unit ist die neue Unit eingebunden. Außerdem befindet sich dort ein dynamisches Array vom Typ TBall. So weit so gut. Das geht auch alles sehr schön. Das einzige Problem ist jetzt, dass jede Kugel die Möglichkeit haben muss, auf das besagte Array zuzugreifen, um zu erfahren, welche Kugeln noch existieren. Außerdem muss sie auf die anderen Kugeln zugreifen können, um dann deren Variablen auszulesen. Denn um eine Kollision festzustellen, muss ich von den anderen Kugeln die Koordinaten abfragen. Ich habe da keine wirkliche Lösung parat. Vor allem, weil ich es sauber programmieren möchte. Ich möchte die Kugel-Unit auch problemlos noch in andere Projekte integrieren können, um damit vielleicht noch ein richtiges Billard zu proggen oder so - oder ich erstelle einen Bildschirmschoner. Jedenfalls wäre es schön, wenn ihr mir helfen könntet. MfG, McDV. |
Re: Zugriff auf Komponenten in einer anderen Unit
Prozeduren, Funktionen und Variablen, die auch außerhalb einer Unit zur Verfügung stehen sollten, musst du im Interface-Teil deklarieren:
Delphi-Quellcode:
Also, die Funktion TestFunc und die Variable i sind auch außerhalb der Unit bearbeit- und verwendbar, TestFunc2 und j nicht.
unit Test;
interface funtion TestFunc: Integer; var i: Integer; implementation var j: Integer; function TestFunc: Integer; begin // end; function TestFunc2: Single; begin // end; end. Wenn du das ganze aber wirklich sauber lösen willst, dann mach das objektorientiert. Greetz alcaeus |
Re: Zugriff auf Komponenten in einer anderen Unit
Du brauchst mindestens 2 Klassen: TBall und TTisch.
TBall repräsentiert alle Eigenschaften eines Balles (x, y, Speed, Richtung, Farbe) TTisch enthält eine ObjektListe oder dyn. Array mit allen TBall-Objekten auf dem Tisch. Zusätzlich Länge und Breite des Tischs. Ausserdem gibt es die Methoden TTisch.MoveBalls(timeinterval:integer); TTisch.CollisionBande(ball:TBall); TTisch.CollisionBalls(ball1, ball2:TBall); TTisch.PaintBackground(canvas:TCanvas); TTisch.PaintBalls(canvas:TCanvas); Property TTisch.BallCount; Diese beiden Klassen werden beide in die Unit Billard reingepackt. |
Re: Zugriff auf Komponenten in einer anderen Unit
Hi.
Ganz genau! Ich möchte es auch objektorientiert machen. Das ist ja ein Schulprojekt. Nur eben, dass die anderen Schüler es nicht so komplex machen. Aber objektorientiert soll es ja schon sein. Und genau dafür suche ich eine Lösung. Wie gesagt: Ich möchte nicht auf irgendeine function oder so zugreifen, sondern lediglich auf eine Variable und eine Komponente (ist ja oben genauer beschrieben). Die Unterunit ist ja nur in die Haupt-Unit eingebunden, aber nicht umgekehrt. Das wäre ja auch wieder unsauber. Und die Unterunit enthält die Typendeklaration der Kugeln. Und ich brauche eine Möglichkeit, um aus dieser Typendeklaration heraus (also den Prozeduren der Unterunit) auf die anderen Komponenten vom Typ TKugel zuzugreifen. Die gesamten Kugeln werden dabei in einem Array der Hauptunit verarbeitet. Also einem solchen Array:
Delphi-Quellcode:
Ich kann euch auch mal gerade den gesamten Quellcode vorlegen. Vielleicht hilft das ja weiter:
Kugeln : array of TKugel;
Wundert euch aber bitte nicht über die komische Nomenklatur. Das ist recht albern, aber unser Lehrer möchte das so haben :| .
Delphi-Quellcode:
Und die zweite Unit:
unit mBaelle; //Dieses ist die Haupt-Unit.
interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, mBall; //mBall ist die zweite Unit, die die Typendeklaration für den Ball enthält type TFrmBaelle = class(TForm) ImTisch: TImage; BtnMove: TButton; TiBallMotor: TTimer; procedure BtnMoveClick(Sender: TObject); procedure TiBallMotorTimer(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private-Deklarationen } public Baelle : array of TBall; //das besagte Array { Public-Deklarationen } end; var FrmBaelle: TFrmBaelle; implementation {$R *.DFM} procedure TFrmBaelle.BtnMoveClick(Sender: TObject); //Schaltet den Timer ein und aus, ist also jetzt unwichtig begin TiBallMotor.Enabled := not(TiBallMotor.Enabled); end; procedure TFrmBaelle.TiBallMotorTimer(Sender: TObject); //Hinter diesem "Motor" verbirgt sich nur der Timer, der die Prozeduren zum bewegen der Bälle aufruft begin Baelle[0].Bewegen; //Ich weiß, dass das unschön ist. Aber es ist ja auch nur zum testen. Da kommt später eine vernünftige Schleife hin. Baelle[1].Bewegen; end; procedure TFrmBaelle.FormCreate(Sender: TObject); begin ImTisch.Top := 10; ImTisch.Left := 10; ImTisch.Height := Screen.Height-10-100; ImTisch.Width := Screen.Width - 20; ImTisch.Canvas.Rectangle(0,0,Imtisch.Width,ImTisch.Height); Setlength(Baelle,2); //Auch das hier ist nur ein Test Baelle[0] := TBall.Create(200,160,30,10,ImTisch,RGB(00,33,99)); Baelle[1] := TBall.Create(230,240,10,300,ImTisch,RGB(90,50,150)); end; end.
Delphi-Quellcode:
Wie ihr seht, fehlt auch noch die Prozedur zur Berechnung des Abprallwinkels zweier Kugeln. Aber dafür kann ich ja auch die Prozedur Reflektion einsetzen. Ich muss den Gegenwinkel eben nur über den ArcSin anhand der relativen Positionen zwischen den zwei Kugelmittelpunkten bestimmen. Das ist ja kein Problem. Auch die Feststellung einer Überschneidung ist nicht weiter schwer, da das ja dann gegeben ist, wenn die Distanz zwischen den Kugelmittelpunkten geringer ist als die Summe der Radien.
unit mBall;
interface uses classes, ExtCtrls, graphics, Math; type TBall = class(TObject) //Das ist der neue Objekttyp. protected xM,yM, Radius, Richtung : integer; //Mittelpunktskoordinaten des Balls kColor : TColor; //Variablem müssen vermutlich als public deklariert werden kTisch: TImage; //Der Billardtisch xmotion, ymotion : extended; procedure Darstellen; procedure Reflektion(Gegenwinkel : integer); //berechnet die Reflektion eines Balles procedure Zusammenstoesse_pruefen; public constructor Create(pX,pY,pRadius,pRichtung:integer; pTisch:TImage; Farbe : TColor); destructor Destroy; override; procedure Bewegen; end; implementation procedure TBall.Zusammenstoesse_pruefen; begin end; constructor TBall.Create(pX,pY,pRadius,pRichtung:integer; pTisch:TImage; Farbe : TColor); begin inherited Create; xM := px; yM := pY; Radius := pRadius; Richtung := pRichtung; kColor := Farbe; kTisch := pTisch; Darstellen end; destructor TBall.Destroy; begin inherited Destroy end; procedure TBall.Darstellen; begin with kTisch.Canvas do begin Pen.Mode := pmNotXOr; Pen.Color := clWhite; Brush.Color := kColor; Ellipse(xM-Radius,yM-Radius,xM+Radius,yM+Radius) end end; procedure TBall.Bewegen; var rem : extended; begin Darstellen; rem := sin(DegToRad(richtung)); ymotion := ymotion + 2.5*rem; rem := cos(DegToRad(richtung)); xmotion := xmotion + 2.5*rem; xm := xm + round(xmotion); xmotion := xmotion - round(xmotion); ym := ym + round(ymotion); ymotion := ymotion - round(ymotion); If xm+radius >= kTisch.Width then Reflektion(0); If ym+radius >= kTisch.Height then Reflektion(90); If xm-radius <= 0 then Reflektion(180); If ym-radius <= 0 then Reflektion(270); Darstellen; end; procedure TBall.Reflektion(Gegenwinkel : integer); //Der Gegenwinkel ist lediglich ein bezugswert zur Berechnung der Reflektion. Vielleicht habt ihr ja eine bessere Möglichkeit dafür. Die anderen Schüler lassen den Ball nur ohne Winkel in lediglich 4 Richtungen laufen. Deshalb habe ich mir ein vernünftiges System ausgedacht, damit der Ball auch in 360 verschiedene Richtungen wandern kann. begin richtung := (540 - richtung + 2*gegenwinkel) mod 360; end; end. Trotzdem bleibt das Problem: Wie kann der eine Ball wissen, wo der andere Ball ist? Und das nach Möglichkeit noch objektorientiert. Hat vielleicht auch jemand von euch zufällig eine gute Definition der Objektorientierten Programmierung parat? Schonmal danke im Voraus! MfG, Daniel. |
Re: Zugriff auf Komponenten in einer anderen Unit
@shima:
Hmm, das geht sicherlich, aber das muss auch einfacher gehen. Der Tisch hat ja schon einen Typ, nämlich TImage! Es müssen sich ja nur noch die Bälle untereinander kennen. Kann ich da nicht irgendwie mit der Komponentenliste arbeiten? Aber wie? Danke, Daniel. |
Re: Zugriff auf Komponenten in einer anderen Unit
Hi Daniel,
ich würde dem Konstruktor vom Ball eine Referenz auf den Tisch übergeben. Im Prinzip hast Du ja schon was ähnliches, nur das Du nicht auf das Objekt selbst sondern auf dessen Image verweist. Aus:
Delphi-Quellcode:
würde
constructor TBall.Create(pX,pY,pRadius,pRichtung:integer; pTisch:TImage; Farbe : TColor);
Delphi-Quellcode:
Bei der Erstellung der Bälle könnte man dann die Referenz auf den Tisch übergeben
constructor TBall.Create(pX,pY,pRadius,pRichtung:integer; pTisch:>>TFrmBaelle<<; Farbe : TColor);
Delphi-Quellcode:
und somit in der Klasse TBall auf alle öffentlichen Methoden der Klasse TFrmBaelle zugreifen.
Baelle[0] := TBall.Create(200,160,30,10,>>self<<,RGB(00,33,99));
Niels P.S. Gibt es eigentlich eine Möglichkeit in einem DelphiCode-Tag die Fettschrift einzuschalten? In der Voranzeige werden nur die Tags angezeigt. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:48 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz