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.