Autor Beitrag
somebody
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 167
Erhaltene Danke: 2



BeitragVerfasst: So 10.01.10 01:01 
Hallo Leute, für die Schule sollen wir einen kleines Spiel Programmieren. Das ganze soll recht einfach sein, man hat eine Kanone, die man nach links und rechts bewegen kann. Außerdem kann diese auch Kugeln abschießen. Oben befindet sich ein "Raumschiff", welches man treffen kann.
Soweit auch kein problem. Zwei Bedingungen waren noch gegeben, das ganze soll Objektorientiert und mit Canvas gemacht werden. Auch noch kein Problem.

Jetzt ist nur die Frage, wie kann ich mit Canvas eine Kollisionsabfrage machen, also abfragen, ob die Kugel das "Raumschiff" berührt hat? Ich hatte schon probiert es so zu machen, dass ich gucke ob die y koordinaten der kugel und des Raumschiffes nahezu gleich sind, UND ob die x Koordinaten der Kugel und des Raumschiffes nahezu gleich sind, allerdings ist dieser Fall komischerweise nie eingetreten.
Die Kugel ist ein Canvas.Ellipse und das Raumschiff ein Canvas.Rectangle

Habt ihr eine Idde?

Gruß
somebody

P.S: Falls die Infos zu wenig waren, kann ich ja auch noch ein Stück Code posten.


Zuletzt bearbeitet von somebody am So 10.01.10 01:18, insgesamt 1-mal bearbeitet
MaPsTaR
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 90
Erhaltene Danke: 4

Win XP
Delphi 7 Enterprise
BeitragVerfasst: So 10.01.10 01:09 
Ich würde mir um das Raumschiff ein Rechteck oder anderes "denken" und dann anhand der Koordinaten des Geschosses berechnen, ob es sich in dem Rechteck befindet.

Aber wenn das bei dir nie eingetreten ist...

Am besten wäre du postest mal deinen Code.

_________________
Liebe Kinder, es stimmt ... solnage auch nur der ertse und lezte Bchutsabe rihctig ist und alle andreen Bcuhsatben irgendwie vorahnden sind,
dann knan man es dennonch lesen, also macht nur weiter so, wir verstehen euch schon
somebody Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 167
Erhaltene Danke: 2



BeitragVerfasst: So 10.01.10 01:18 
Oki, also hiermit bewege ich die Kugel

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
Canvas.Ellipse(Kugel.Bewegen_x(10,Kugel.x),Kugel.Bewegen_y(10,Kugel.y),20 + Kugel.Bewegen_x(10,Kugel.x),20 + Kugel.Bewegen_y(10,Kugel.y));

.
.
.

Function TKugel.Bewegen_Y(AVy: integer; AYalt: integer): Integer;
begin
     FYneu := AYalt + AVy;

     Result := FYNeu;
end;

function TKugel.Bewegen_X(AVx: integer; AXalt: integer): Integer;
begin
     FXneu := AXAlt + AVx;

     Result := FXneu;
end;


Und das Raumschiff bewegt sich so

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
Canvas.Rectangle(Raumschiff.Bewegen_x(Lok_x),20,50 + Raumschiff.Bewegen_x(Lok_x), 40);  //Lok_x ist eine Lokale variable, die man erhöht, damit sich das Raumschiff bewegt

.
.
.

function TRaumschiff.Bewegen_X(AVx: integer): Integer;
begin
     FXneu := FXneu + AVx;

     if FXneu >= 800 then   //wenn das Raumschiff aus dem Bildschirm fliegt, dann fängt es vorne wieder an 
     begin
          FXneu := -20;
     end
     else
     begin
          Result := FXneu;
     end;
end;


Und dann hatte ich halt versucht, die Koordinaten zu vergleichen, das sah dann ungefähr so aus.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
if (Kugel.y <= 8and (Kugel.x = Raumschiff.Bewegen_x(Lok_speicher) then  //Lok_speicher hat den gleichen Wert wie Lok_x, mit dem Unterschied, dass si global ist
begin
   Raumschiff.Destroy;
end;


Ich hoffe es bringt etwas...

Moderiert von user profile iconmatze: Code- durch Delphi-Tags ersetzt
MaPsTaR
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 90
Erhaltene Danke: 4

Win XP
Delphi 7 Enterprise
BeitragVerfasst: So 10.01.10 01:30 
Zitat:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
if (Kugel.y <= 8and (Kugel.x = Raumschiff.Bewegen_x(Lok_speicher) then  //Lok_speicher hat den gleichen Wert wie Lok_x, mit dem Unterschied, dass si global ist
begin
   Raumschiff.Destroy;
end;


Warum bewegst du das Raumschiff beim Testen nochmal?

Welche Felder hat Raumschiff denn?
X- und Y-Koordinate? Width? ...

ausblenden Delphi-Quelltext
1:
2:
3:
4:
if (Kugel.y <= 8and (Kugel.x > Raumschiff.x) and (Kugel.x < (Raumschiff.x + Raumschiff.width))  then  
begin
   Raumschiff.Destroy;
end;

_________________
Liebe Kinder, es stimmt ... solnage auch nur der ertse und lezte Bchutsabe rihctig ist und alle andreen Bcuhsatben irgendwie vorahnden sind,
dann knan man es dennonch lesen, also macht nur weiter so, wir verstehen euch schon
ub60
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 764
Erhaltene Danke: 127



BeitragVerfasst: So 10.01.10 01:39 
Die grobe Kollision gibt es mit IntersectRect (Schnittpunkt zweier Rechtecke), das "Finetuning" dann mit Masken.

ub60
somebody Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 167
Erhaltene Danke: 2



BeitragVerfasst: So 10.01.10 01:40 
Also ich bewege das Raumschiff nochmal, weil ich darüber die x Koordinate des Raumschiffes erhalte. Diese überprüfe ich dann... Man sieht die Bewegung aber nicht, da ich sie ja nicht zeichne.
Und das Raumschiff hat nur die Felder x und y.
MaPsTaR
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 90
Erhaltene Danke: 4

Win XP
Delphi 7 Enterprise
BeitragVerfasst: So 10.01.10 01:53 
Aber du müsstest die X-Koordinate doch auch in Lok_Speicher haben, oder?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
if (Kugel.y <= 8and (Kugel.x > Lok_speicher) and (Kugel.x < (Lok_speicher + 50))  then  
begin
   Raumschiff.Destroy;
end;


Wie kommst du eigentlich auf if (Kugel.y <= 8) ...

Müsste es nicht eher
ausblenden Delphi-Quelltext
1:
if (Kugel.y <= Raumschiff.y) ...					

heißen?

_________________
Liebe Kinder, es stimmt ... solnage auch nur der ertse und lezte Bchutsabe rihctig ist und alle andreen Bcuhsatben irgendwie vorahnden sind,
dann knan man es dennonch lesen, also macht nur weiter so, wir verstehen euch schon
Bergmann89
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: So 10.01.10 03:04 
Hey,

ich würd das so machen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
const
  TOLERANCE = 10;

if (Kugel.x + TOLERANCE > Raumschiff.x - TOLERANCE) and
   (Kugel.x - TOLERANCE < Raumschiff.x + TOLERANCE) and
   (Kugel.y + TOLERANCE > Raumschiff.y - TOLERANCE) and
   (Kugel.y - TOLERANCE < Raumschiff.y + TOLERANCE) then
  Raumschiff.Free;

skizze
das Bild zeigt jetzt die 2. überprüfung. Der Punkt sind die Koordinaten un das Viereck die Toleranz.

MfG Bergmann

Moderiert von user profile iconNarses: Bild als Anhang hochgeladen.
Einloggen, um Attachments anzusehen!
_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
somebody Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 167
Erhaltene Danke: 2



BeitragVerfasst: So 10.01.10 11:29 
Oki, Danke für die schnellen Antworten. Ich habe es jetzt mit Bergmans Variante versucht und es geht fast ohne Fehler. Das einzige Problem ist, dass wenn ich das Raumschiff getroffen habe, es nicht zerstört wird, sondern noch weiterlebt aber von Anfang an wieder startet. Wenn ich es dann ein Zweites mal treffen will, dann kommt eine Zugriffsverletzung, aber auch nur wenn ich das Raumschiff getroffen habe.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
procedure TForm1.Timer1Timer(Sender: TObject);
const toleranz = 10;
begin
     Timer2.Enabled := false;
     Paintbox1.refresh;

     Canvas.Ellipse(Kugel.Bewegen_x(10,Kugel.x),Kugel.Bewegen_y(10,Kugel.y),20 + Kugel.Bewegen_x(10,Kugel.x),20 + Kugel.Bewegen_y(10,Kugel.y));

     Canvas.Rectangle(Lok_speicher,20,50 + Lok_speicher, 40);  // hier zeichne ich das Raumschiff immer wieder, da man es sonst durch das Refresh nicht sehen würde. Der Timer ist aber 
                                                               // aus(siehe oben), das heíßt das Raumschiff bewegt sich solange nicht(Das soll das treffen erleichtern)
     Kugel.Y := Kugel.Y - 10;

     if Kugel.y <= 8 then                                     // Das Raumschiff bewegt sich nur in x Richtung, und die Y-Koordinate des Raumschiffs(8 [auch gleichzeitig der Spielfeldrand]) bleibt 
     begin                                                    // immer gleich
          if (Kugel.x + toleranz > Raumschiff.x - toleranz) and
             (Kugel.x - toleranz < Raumschiff.x + toleranz) then
          begin
               Raumschiff.Free;                              // hier hab ich es auch schon mit .Destroy versucht, der Fehler bleibt aber
               Timer2.Enabled := false;
          end
          else
          begin
               Timer2.Enabled := true;
               PaintBox1.Refresh;
               Kugel.Y := 650;
               Timer1.Enabled := false;
          end;
     end;
end;


Ich finde den Fehler irgendwie nicht, könnt ihr mir da weiterhelfen?

EDIT: Ich erzeuge das Raumschiff einfach nochmal, nachdem es getroffen wurde, damit nach einmal schießen nicht gleich alles vorbei ist. Das alte wird natürlich auch zerstört um speicher zu sparen.
Danke für eure hilfe!

Moderiert von user profile iconmatze: Code- durch Delphi-Tags ersetzt
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: So 10.01.10 12:12 
user profile iconBergmann89 hat folgendes geschrieben Zum zitierten Posting springen:
Hey,

ich würd das so machen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
const
  TOLERANCE = 10;

if (Kugel.x + TOLERANCE > Raumschiff.x - TOLERANCE) and
   (Kugel.x - TOLERANCE < Raumschiff.x + TOLERANCE) and
   (Kugel.y + TOLERANCE > Raumschiff.y - TOLERANCE) and
   (Kugel.y - TOLERANCE < Raumschiff.y + TOLERANCE) then
  Raumschiff.Free;

user defined image
das Bild zeigt jetzt die 2. überprüfung. Der Punkt sind die Koordinaten un das Viereck die Toleranz.

MfG Bergmann


ich würde die Toleranz auf der linken Seite weglassen. Sonst könnte man auch gleich schreiben:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
const
  TOLERANCE = 10;

if (Kugel.x > Raumschiff.x - TOLERANCE*2and
   (Kugel.x < Raumschiff.x + TOLERANCE*2and
   (Kugel.y > Raumschiff.y - TOLERANCE*2and
   (Kugel.y < Raumschiff.y + TOLERANCE*2then

und dann lässt man das *2 gleich weg und nimmt lieber ne größere Toleranz, falls es nicht reicht.
Das Projektil würde ich mir eher als Punkt vorstellen und das Raumschiff als Rechteck (in diesem Falle wäre es ein Quadrat).
Dann hast du halt nur noch die Punkt-In-Quadrat Prüfung zu machen.

Also eher wie das hier:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
if (Kugel.x > Raumschiff.x - Raumschiff.breite) and
   (Kugel.x < Raumschiff.x + Raumschiff.breite) and
   (Kugel.y > Raumschiff.y - Raumschiff.hoehe) and
   (Kugel.y < Raumschiff.y + Raumschiff.hoehe) then
  // KOLLISION

Und das mit der globalen Variable, in der du zusätzlich die Koordinate speicherst, ist nicht im Sinne der Objektorientierung.
In der Regel verzichtet man auf globale Variablen.
Ich würde das zu testende Projektil der Kollisions Funktion des Raumschiffs übergeben (oder umgekehrt):
ausblenden Delphi-Quelltext
1:
TRaumschiff.pruefeKollisionMit(projektil: TProjektil): boolean;					

oder:
ausblenden Delphi-Quelltext
1:
TProjektil.pruefeKollisionMit(raumschiff: TRaumschiff): boolean;					

Oder was hat es genau mit diesem Lok_Speicher auf sich?

mfg
Bergmann89
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: So 10.01.10 15:29 
Hey,

wie erzeugst du denn das Raumschiff, bzw wo? Weil das steht ja nich im Codeausschnitt.

MfG Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
somebody Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 167
Erhaltene Danke: 2



BeitragVerfasst: Mo 11.01.10 12:20 
Das Raumschiff erzeuge ich in formcreate. Danke zwar für die weiteren Fragen, aber das Problem hat sich schon erledigt. geht mittlerweile alles...
aber trotzdem danke für die hilfe ;)
Florian H.
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 29



BeitragVerfasst: Mo 11.01.10 18:35