Einzelnen Beitrag anzeigen

daniel-volk

Registriert seit: 16. Jul 2003
170 Beiträge
 
Delphi 6 Enterprise
 
#4

Re: Zugriff auf Komponenten in einer anderen Unit

  Alt 16. Jun 2004, 17:50
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:

  Kugeln : array of TKugel; Ich kann euch auch mal gerade den gesamten Quellcode vorlegen. Vielleicht hilft das ja weiter:
Wundert euch aber bitte nicht über die komische Nomenklatur. Das ist recht albern, aber unser Lehrer möchte das so haben .

Delphi-Quellcode:
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.
Und die zweite Unit:

Delphi-Quellcode:
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.
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.

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.
  Mit Zitat antworten Zitat