AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Pong - Problem bei der Ballkollision

Ein Thema von .chicken · begonnen am 7. Dez 2006 · letzter Beitrag vom 12. Dez 2006
Antwort Antwort
Seite 1 von 5  1 23     Letzte »    
.chicken

Registriert seit: 5. Dez 2006
459 Beiträge
 
#1

Pong - Problem bei der Ballkollision

  Alt 7. Dez 2006, 21:59
Also ich weiss das Thema Pong wurde hier schon oft behandelt, aber ich habe zu meinem Problem nichts gefunden!

Hier erstmal mein Code:

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;

const
  Breite = 600;
  Hoehe = 400;
type
  TForm1 = class(TForm)
    Spielfeld: TPaintBox;
    Button1: TButton;
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Spielfeld_bemalen;
    procedure Tastendruck(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure Timer1Timer(Sender: TObject);
    procedure Ball_berechnen;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  Spielerposition: Array [1..2] of TPoint;
  Ballposition, Ballrichtung: TPoint;
  Spieler, Ball: TBitmap;

implementation

{$R *.dfm}


//----------------------------------
//FORM CREATE
//----------------------------------
procedure TForm1.FormCreate(Sender: TObject);
begin
  Form1.DoubleBuffered := True;
  Randomize;
end;
//----------------------------------


//----------------------------------
//FUNKTION ZUFALLSRICHTUNG
//----------------------------------
function Zufallsrichtung (i: Integer; j: Integer): TPoint;
var
x, y: Integer;
begin
  x := (Random(i - 1) + 1) * 5;
  y := Random(j) * 5;

  case Random(2) of
    0: x := x;
    1: x := -x;
  end;

  case Random(2) of
    0: y := y;
    1: y := -y;
  end;

  Result := Point(x, y);
end;
//----------------------------------


//----------------------------------
//SPIELFELD VORBEREITEN
//----------------------------------
procedure Spielfeld_vorbereiten;
begin
  //Bilder laden
  Spieler := TBitmap.Create;
  Spieler.LoadFromFile('Spieler.bmp');
  Ball := TBitmap.Create;
  Ball.LoadFromFile('Ball.bmp');
  Ball.TransparentColor := RGB(255, 255, 255);
  Ball.TransparentMode := tmFixed;
  Ball.Transparent := True;

  //Startpositionen festgelegt
  Spielerposition[1] := Point(10, (Hoehe div 2 - 30));
  Spielerposition[2] := Point((Breite - 10 - Spieler.Width), (Hoehe div 2 - 30));
  Ballposition := Point((Breite div 2 - (Ball.Width div 2)), (Hoehe div 2 - (Ball.Height div 2)));
  Ballrichtung := Zufallsrichtung(5, 5);
end;
//----------------------------------


//----------------------------------
//SPIELFELD BEMALEN
//----------------------------------
procedure TForm1.Spielfeld_bemalen;
var
i, x: Integer;
begin
  //Spielfeld wird gelöscht
  Spielfeld.Canvas.Brush.Color := clGray;
  Spielfeld.Canvas.FillRect(rect(0, 0, Breite, Hoehe));

  //Mittellinie
  Spielfeld.Canvas.Brush.Color := clBlack;
  x := 0;
  for i := 0 to Hoehe do begin
    Spielfeld.Canvas.FillRect(rect((Breite div 2 - 1), x, (Breite div 2 + 1), (x+2)));
    x := x + 6;
  end;

  //Spieler und Ball werden gezeichnet
  Spielfeld.Canvas.Draw(Spielerposition[1].X, Spielerposition[1].Y, Spieler);
  Spielfeld.Canvas.Draw(Spielerposition[2].X, Spielerposition[2].Y, Spieler);
  Spielfeld.Canvas.Draw(Ballposition.X, Ballposition.Y, Ball);
end;
//----------------------------------


//----------------------------------
//BUTTONKLICK
//----------------------------------
procedure TForm1.Button1Click(Sender: TObject);
begin
  Spielfeld_vorbereiten;
  Timer1.Enabled := True;
  Button1.Enabled := False;
end;
//----------------------------------


//----------------------------------
//TASTENDRUCK
//----------------------------------
procedure TForm1.Tastendruck(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  case Key of
    VK_Up: if (Spielerposition[1].Y - 10) > 0 then
            Spielerposition[1].Y := Spielerposition[1].Y - 10;
    VK_Down: if (Spielerposition[1].Y + 10 + Spieler.Height) < Hoehe then
              Spielerposition[1].Y := Spielerposition[1].Y + 10;
    VK_Left: if (Spielerposition[2].Y - 10) > 0 then
            Spielerposition[2].Y := Spielerposition[2].Y - 10;
    VK_Right: if (Spielerposition[2].Y + 10 + Spieler.Height) < Hoehe then
              Spielerposition[2].Y := Spielerposition[2].Y + 10;
  end;
end;
//----------------------------------


//----------------------------------
//TIMER
//----------------------------------
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Ball_berechnen;
  Spielfeld_bemalen;
end;
//----------------------------------


//----------------------------------
//BALL BERECHNEN
//----------------------------------
procedure TForm1.Ball_berechnen;
begin
  //Wand angestoßen?
  if Ballposition.Y <= 0 then
    Ballrichtung.Y := -Ballrichtung.Y;
  if Ballposition.Y >= Hoehe then
    Ballrichtung.Y := -Ballrichtung.Y;

  //Spieler angestoßen?
  if ((Ballposition.X <= Spielerposition[1].X + Spieler.Width) AND (Ballposition.Y + Ball.Height >= Spielerposition[1].Y) AND (Ballposition.Y <= Spielerposition[1].Y + Spieler.Height)) OR
     ((Ballposition.X + Ball.Width >= Spielerposition[2].X) AND (Ballposition.Y + Ball.Height >= Spielerposition[2].Y) AND (Ballposition.Y <= Spielerposition[2].Y + Spieler.Height)) then
          Ballrichtung.X := -Ballrichtung.X;

  //Gepunktet?
  //Sp1
  if Ballposition.X <= 0 then
    Timer1.Enabled := False;
    Button1.Enabled := True;
  //Sp2
  if Ballposition.X + Ball.Width >= Breite then
    Timer1.Enabled := False;
    Button1.Enabled := True;


  Ballposition := Point(Ballposition.X + Ballrichtung.X, Ballposition.Y + Ballrichtung.Y);
end;
//----------------------------------

end.
Also erstmal: das ist natuerlich alles noch nicht fertig!!!

Aber bei mir ist nun das Problem aufgetreten, dass der Ball bevor er die Richtung aendert oft schon auf dem Balken oder halb außerhalb des Spielfeldes ist, weil ich ja Pro Timer den Ball um zwischen 1 und 5 verschiebe!

Hoffe ihr versteht was ich meine...wie wuerdet ihr das lösen?

Und was habt ihr fuer Verbesserungsvorschlaege zu meinem Quelltext??
Bin noch nich solange am Arbeiten mit Delpih, machen es jetzt in der Schule aber unsern Lehrer kann man in der Pfeife rauchen also bring ichs mir selber bei...

Dazu danke dann erstmal an dieses (wirklich hilfreiche) Forum!


MfG, chicken!
  Mit Zitat antworten Zitat
Cöster

Registriert seit: 6. Jun 2006
589 Beiträge
 
Turbo Delphi für Win32
 
#2

Re: Pong - Problem bei der Ballkollision

  Alt 7. Dez 2006, 22:27
Was mir spontan an deinem Quelltext auffällt:

-den Bildschirm lieber im OnPaint der PaintBox aktualisieren und dies per Invalidate aufrufen
-Offscreen-Bitmaps(siehe Suchfunktion/machst du schon teilweise)
-statt die Spielerpositionen im KeyDown zu verändern, lieber im Timer (benögitgte Funktion: GetAsyncKeyState)

Zu deinem Problem:

Du könntest die Kugel bei der Kollision mit dem Spielfeldrand um 2mal soviel nach innen verschieben, wie sie aus dem Bildschirm hinausragt.
  Mit Zitat antworten Zitat
.chicken

Registriert seit: 5. Dez 2006
459 Beiträge
 
#3

Re: Pong - Problem bei der Ballkollision

  Alt 8. Dez 2006, 20:35
Also danke erstmal fuer deine Antwort!!!

Kannst du deine ersten beiden Punkte vielleicht nochmal erlaeutern? Die versteh ich ehrlich gesagt nich so ganz ^^!

Dann zum dritten Punkt, das werd ich mir ma ansehn, wenn ich nich klar komme melde mich mich nomma, wenns recht is =)


Und zu deiner letzten Antwort:
Du meinst also dass ich einfach bevor ich die Kugelposition erneuere die alte abfrage und dann einfach nur bis zum Rand "auffuelle"?!

MfG

Edit: Zum Thema GetAsyncKey - Soll ich dass dann für jede benötigte Taste abfragen oder hab ich das falsch verstanden??? Bei vielen Tasten waer das ja bisschen umstaendlich, igibts doch sicher ne einfachere Moeglichkeit!?
  Mit Zitat antworten Zitat
Cöster

Registriert seit: 6. Jun 2006
589 Beiträge
 
Turbo Delphi für Win32
 
#4

Re: Pong - Problem bei der Ballkollision

  Alt 8. Dez 2006, 21:16
Zitat von .chicken:
Kannst du deine ersten beiden Punkte vielleicht nochmal erlaeutern? Die versteh ich ehrlich gesagt nich so ganz ^^!
Zu 1:
Statt die Zeichen-Prozedur Spielfeld_bemalen im Timer aufzurufen, schlage ich vor stattdessen die Prozedur "Spielfeld.Invalidate" aufzurufen. Dies bewirkt, dass die PaintBox neu gezeichnet wird. Dadurch wird das Ereignis "OnPaint" der PaintBox aufgerufen. In diesem sollten dann deine Zeichenvorgänge geschehen (PaintBox auf Form anklicken, im OI auf Ereignisse gehen, ins Feld neben OnPaint doppelklicken, am Cursor im Quelltext dann den Zeichnen-Code einfügen).

Zu 2:
Es ist schneller, nicht alle Zeichen-Vorgänge direkt auf die Komponente (PaintBox) zu übertragen, sondern erst alles auf das Canvas eines Bitmaps im Speicher zu zeichnen und dies dann auf das Canvas der PaintBox zu kopieren. In diesem Post beschreibt SirThornberry wie's geht.

Zitat von .chicken:
Dann zum dritten Punkt, das werd ich mir ma ansehn, wenn ich nich klar komme melde mich mich nomma, wenns recht is =)
Klar ist's recht

Zitat von .chicken:
Du meinst also dass ich einfach bevor ich die Kugelposition erneuere die alte abfrage und dann einfach nur bis zum Rand "auffuelle"?!
Ich weiß nicht genau, was du mit auffüllen meinst, aber ich glaub nicht. Du verschiebst deine Kugel ganz normal. Wenn sie jetzt z.B. um 3 Pixel in den rechten Rand hineinragt, heißt das ja, dass sie eigentlich schon 3 Pixel vor jetzt kollidiert hätte. Das heißt, die 3 Pixel, die die Kugel weiter nach rechts gerollt ist, obwohl sie nicht durfte, hätte sie eigentlich nach links rollen müssen. Deswegen verschiebst du die Kugel dann wieder um 2*3=6 Pixel nach links.
Von diesen Berechnungen soll der Anwender später natürlich nichts mitkriegen, deswegen darf zwischendurch nicht neugezeichnet werden. Aber das Neuzeichnen sollte sowieso nur im Timer über Invalidate (s.o.) erfolgen.
  Mit Zitat antworten Zitat
.chicken

Registriert seit: 5. Dez 2006
459 Beiträge
 
#5

Re: Pong - Problem bei der Ballkollision

  Alt 8. Dez 2006, 21:26
Hm also zum ersten...is das einfach nur besserer Stil oder funktioniert das schneller oder was steckt dahinter?

Und dann zum letzten Punkt: Wie verhindere ich denn dass der Anwender das nicht mitkriegt?
Habe ja jetzt im Timer dass er immer nachdem die Position neu berechnet wurde zeichnet, weswegen der Anwender ja auch sieht dass der Ball kollidiert!

Danke fuer deine schnellen Antworten!
  Mit Zitat antworten Zitat
Cöster

Registriert seit: 6. Jun 2006
589 Beiträge
 
Turbo Delphi für Win32
 
#6

Re: Pong - Problem bei der Ballkollision

  Alt 8. Dez 2006, 21:54
Zitat von .chicken:
Hm also zum ersten...is das einfach nur besserer Stil oder funktioniert das schneller oder was steckt dahinter?
Also der Vorteil, der mir bekannt ist, ist folgender: Wenn z.B. ein Label über der PaintBox liegt, würde dies im Normalfall beim Neuzeichnen übermalt werden. Wenn es Transparent und unsichtbar ist und man es dann sichtbar macht, hat die Transparenz auch nur dann Wirkung, wenn das Zeichnen im OnPaint stattfindet. Sonst wird nämlich dort, wo sich das Label befindet die PaintBox in Form eines Rechtecks übermalt, trotz der Transparenz des Labels.
Ich glaube es gibt noch viel mehr Vorteile, welche genau weiß ich auch nicht.

Zitat von .chicken:
Und dann zum letzten Punkt: Wie verhindere ich denn dass der Anwender das nicht mitkriegt?
Habe ja jetzt im Timer dass er immer nachdem die Position neu berechnet wurde zeichnet, weswegen der Anwender ja auch sieht dass der Ball kollidiert!
Mit "nicht mitkriegt" meinte ich nur, dass der Anwender nicht sehen soll, dass die x-Position der Kugel zwischenzeitlich dort ist, wo sie eigentlich nicht sein darf. Aber wenn Invalidate erst dann aufgerufen wird, wenn alle Berechnungen durchgeführt wurden, sieht er das ja sowieso nicht.
  Mit Zitat antworten Zitat
.chicken

Registriert seit: 5. Dez 2006
459 Beiträge
 
#7

Re: Pong - Problem bei der Ballkollision

  Alt 9. Dez 2006, 09:00
OK, das mit onPaint und Invalidate hab ich soweit hinbekommen, flackert jezz sogar viel weniger, aber erst auf ein Bitmap zu zeichnen bekomme ich noch nicht wirklich hin >.<

Und dann zu der Sache mit der Kollision, meinste das so?

Delphi-Quellcode:
//----------------------------------
//BALL BERECHNEN
//----------------------------------
procedure TForm1.Ball_berechnen;
begin
  //Wand angestoßen?
  if Ballposition.Y <= 0 then
    Ballrichtung.Y := -Ballrichtung.Y;
  if Ballposition.Y >= Hoehe then
    Ballrichtung.Y := -Ballrichtung.Y;

  //Spieler angestoßen?
  if ((Ballposition.X <= Spielerposition[1].X + Spieler.Width) AND (Ballposition.Y + Ball.Height >= Spielerposition[1].Y) AND (Ballposition.Y <= Spielerposition[1].Y + Spieler.Height)) OR
     ((Ballposition.X + Ball.Width >= Spielerposition[2].X) AND (Ballposition.Y + Ball.Height >= Spielerposition[2].Y) AND (Ballposition.Y <= Spielerposition[2].Y + Spieler.Height)) then
          Ballrichtung.X := -Ballrichtung.X;

  //Gepunktet?
  //Sp1
  if Ballposition.X <= 0 then begin
    Timer1.Enabled := False;
    Button1.Enabled := True;
  end;
  //Sp2
  if Ballposition.X + Ball.Width >= Breite then begin
    Timer1.Enabled := False;
    Button1.Enabled := True;
  end;

  if Ballposition.X < Spielerposition[1].X + Spieler.Width then
    Ballposition.X := Spielerposition[1].X + Spieler.Width;
  if Ballposition.X + Ball.Width> Spielerposition[2].X then
    Ballposition.X := Spielerposition[2].X - Ball.Width;
  if Ballposition.Y < 0 then
    Ballposition.Y := 0;
  if Ballposition.Y + Ball.Height > Hoehe then
    Ballposition.Y := Hoehe - Ball.Height;


  Ballposition := Point(Ballposition.X + Ballrichtung.X, Ballposition.Y + Ballrichtung.Y);
end;
//----------------------------------

Sorry dass ich das net so schnell versteh

Edit: Mir is grad aufgefallen dass da so noch einige Fehler drin sind, aber generell zu diesem Teil

Delphi-Quellcode:
  if Ballposition.X < Spielerposition[1].X + Spieler.Width then
    Ballposition.X := Spielerposition[1].X + Spieler.Width;
  if Ballposition.X + Ball.Width> Spielerposition[2].X then
    Ballposition.X := Spielerposition[2].X - Ball.Width;
  if Ballposition.Y < 0 then
    Ballposition.Y := 0;
  if Ballposition.Y + Ball.Height > Hoehe then
    Ballposition.Y := Hoehe - Ball.Height;
So meinst du das?

Und dann noch was
Kann man die Kollision nich irgendwie eleganter lösen??? Weil wenn ich hitnerher noch berechnen will, dass wenn der Ball weiter rechts aufprallt er beschleunigt/verlangsamt wird, dann verlier ich mich ja in endlosen IF-Bedigungen...

Hab schon die SuFu dazu benutzt und bin öfter auf so Wurzel und Quadrat Funktionen gestoßen, hab aber echt keinen Plan was ich damit anstellen soll =)
  Mit Zitat antworten Zitat
Cöster

Registriert seit: 6. Jun 2006
589 Beiträge
 
Turbo Delphi für Win32
 
#8

Re: Pong - Problem bei der Ballkollision

  Alt 9. Dez 2006, 12:59
Mir ist noch ein Vorteil von OnPaint+Invalidate eingefallen: Das verhindert, dass man das Bild auf einer PaintBox nicht wegradieren kann, indem man andere Fenster drüberschiebt.

Wo liegt denn dein Problem mit dem Zeichnen auf ein Speicher-Bitmap? Wie hast du's denn versucht umzusetzen und was klappte dabei nicht? Zeig mal Code!

In Z. 9 deines Codes ist noch ein Fehler: BallPosition.Y + Ball.Height müsste es heißen.

Den Teil unten in deinem Code kann man im Grunde genommen so lösen.

Was du generell noch an deinem Code verbessern könntest: Einige Bedingungen fragst du mehrmals ab. Du könntest an vielen Stellen mehrere Bedingungen zusammenfassen.
In Zeile 7-10 passiert bei Zwei verschiedenen Bedingungen (von denen sowieso nur eine stimmen kann) das gleiche. Du könntest sie mit "or" verbinden. Dann braucht die zweite nämlich gar nicht mehr gelesen zu werden, wenn die erste zutrifft. Das brächte minimalen Zeitgewinn.



Zitat von .chicken:
Kann man die Kollision nich irgendwie eleganter lösen??? Weil wenn ich hitnerher noch berechnen will, dass wenn der Ball weiter rechts aufprallt er beschleunigt/verlangsamt wird, dann verlier ich mich ja in endlosen IF-Bedigungen...
Also rechts und links sind doch die Spieler, oder? Wieso sollte der Ball mehr beschleunigt werden, wenn er weiter rechts in den rechten Spieler stößt? Wohl eher, dass der Abprallwinkel davon abhängt, ob der Spieler mittig den Ball abstößt oder nur gerade noch mit dem Rand berührt.
  Mit Zitat antworten Zitat
.chicken

Registriert seit: 5. Dez 2006
459 Beiträge
 
#9

Re: Pong - Problem bei der Ballkollision

  Alt 9. Dez 2006, 15:46
Aso, dass hab ich falsch erklaert mit dem rechts und links, ich meinte wenn er weiter rechts auf dem schlaeger aufprallt (vom schlaeger aus gesehn) also weiter unten/oben...

Dass im Quelltext vieles noch nicht stimmte hatte ich ja auch erwaehnt, hab ihn nochmal überarbeitet aber das funzt trotzdem noch nich so ganz...

Delphi-Quellcode:
//----------------------------------
//BALL BERECHNEN
//----------------------------------
procedure TForm1.Ball_berechnen;
begin

  Ballposition := Point(Ballposition.X + Ballrichtung.X, Ballposition.Y + Ballrichtung.Y);

  Kollision;
end;
//----------------------------------


//----------------------------------
//KOLLISION
//----------------------------------
procedure TForm1.Kollision;
var
i: Integer;
begin
  //Wand angestoßen?
  if Ballposition.Y <= 0 then begin
    Ballposition.Y := 0;
    Ballrichtung.Y := -Ballrichtung.Y;
  end;
  if Ballposition.Y + Ball.Height >= Hoehe then begin
    Ballposition.Y := Hoehe - Ball.Height;
    Ballrichtung.Y := -Ballrichtung.Y;
  end;

  //Spieler1 angestoßen?
    //Vorne angestoßen?
  if (Ballposition.Y + Ball.Height >= Spielerposition[1].Y) AND (Ballposition.Y <= Spielerposition[1].Y + Spieler.Height) then
    if Ballposition.X <= Spielerposition[1].X + Spieler.Width then begin
      Ballposition.X := Spielerposition[1].X + Spieler.Width;
      Ballrichtung.X := -Ballrichtung.X;
  end
  else
    //Unten/Oben angestoßen?
  if (Ballposition.X <= Spielerposition[1].X + Spieler.Width) AND (Ballposition.X + Ball.Width >= Spielerposition[1].X) then begin
    if (Ballposition.Y + Ball.Height >= Spielerposition[1].Y) AND (Ballposition.Y + Ball.Height <= Spielerposition[1].Y + Spieler.Height div 2) then begin
      Ballposition.Y := Spielerposition[1].Y - Ball.Height;
      Ballrichtung.Y := -Ballrichtung.Y;
    end;
    if (Ballposition.Y <= Spielerposition[1].Y + Spieler.Height) AND (Ballposition.Y >= Spielerposition[1].Y + Spieler.Height div 2) then begin
      Ballposition.Y := Spielerposition[1].Y + Spieler.Height;
      Ballrichtung.Y := -Ballrichtung.Y;
    end;
  end;

  //Spieler2 angestoßen?
    //Vorne angestoßen?
  if (Ballposition.Y + Ball.Height >= Spielerposition[2].Y) AND (Ballposition.Y <= Spielerposition[2].Y + Spieler.Height) then
    if Ballposition.X + Ball.Width >= Spielerposition[2].X then begin
      Ballposition.X := Spielerposition[2].X - Spieler.Width;
      Ballrichtung.X := -Ballrichtung.X;
  end
  else
    //Unten/Oben angestoßen?
  if (Ballposition.X + Ball.Width >= Spielerposition[2].X) AND (Ballposition.X <= Spielerposition[1].X + Spieler.Width) then begin
    if (Ballposition.Y + Ball.Height >= Spielerposition[2].Y) AND (Ballposition.Y + Ball.Height <= Spielerposition[1].Y + Spieler.Height div 2) then begin
      Ballposition.Y := Spielerposition[2].Y - Ball.Height;
      Ballrichtung.Y := -Ballrichtung.Y;
    end;
    if (Ballposition.Y <= Spielerposition[2].Y + Spieler.Height) AND (Ballposition.Y >= Spielerposition[1].Y + Spieler.Height div 2) then begin
      Ballposition.Y := Spielerposition[2].Y + Spieler.Height;
      Ballrichtung.Y := -Ballrichtung.Y;
    end;
  end;

    //Gepunktet?
  //Sp1
  if Ballposition.X <= 0 then begin
    Timer1.Enabled := False;
    Button1.Enabled := True;
  end;
  //Sp2
  if Ballposition.X + Ball.Width >= Breite then begin
    Timer1.Enabled := False;
    Button1.Enabled := True;
  end;
end;
//----------------------------------
Kann man die Kollision denn eleganter abfragen? Denn nebenbei is der Ball ja rund, und ich habe aber ein eckiges Bild, dh die Abfrage ist nicht wirklich genau!


Für die Sache mit dem aufs Bitmap zeichnen:
Ich hab den Code jetzt nichtmehr, weil ich ihn wieder gelöscht habe als es nicht funktioniert hat, damit ich das Programm weiter benutzen kann.

Also immer wenn ich das Programm gestartet habe dann hat er einfach alles schwarz gemalt und is abgestuertzt.

Ich hab das ungefaehr so versucht umzusetzen:

Delphi-Quellcode:
Spielfeldpuffer := TBitmap.Create;
Spielfeldpuffer.Width := Breite;
Spielfeldpuffer.Height := Hoehe;

//dann in der onPaint Funktion die Spieler und den Ball mittels Draw auf den Canvas des Bilds gemalt //(das war sicher einer der Fehler) ungefaehr so
Spielfeldpuffer.Canvas.Draw(Spielerposition[1].X, Spielerposition[1].Y, Spieler);

//und dann in die Paintbox damit
Spielfeld.Canvas.Draw(0, 0, Spielfeldpuffer);
Denke mal da warn mehrere Fehlre drin!

MfG

Edit: (Kollision ueberarbeitet)
Bei der Kollision is mir noch was aufgefallen...die beiden Prüfungen ob oben oder vorne am Schlaeger angestoßen wird ueberpruefen beide nahezu dasselbe, deswegen aendert der Ball abundzu plötzlich ganz komisch die Richtung...hab aber keine Ahnung iwe ich nun unterscheiden soll ob der Ball von oben auf den Schlaeger oder von der Seite da drauf prallt (hoffe ich versteht was ich meine)



O
-
-
-
-
-

oder

-
-
- O
-
-

Hoffe das hilft etwas zum Verstaendnis
  Mit Zitat antworten Zitat
Cöster

Registriert seit: 6. Jun 2006
589 Beiträge
 
Turbo Delphi für Win32
 
#10

Re: Pong - Problem bei der Ballkollision

  Alt 9. Dez 2006, 18:07
Zitat von .chicken:
Denn nebenbei is der Ball ja rund, und ich habe aber ein eckiges Bild, dh die Abfrage ist nicht wirklich genau!
Dann überprüfst du halt erst, ob eine Kollision auf Höhe des Kugelmittelpunkts stattfindet. Nachher guckst du, ob die Entfernung vom Kugelmittelpunkt zu einer der Ecken des Spielerrechtecks kleiner ist als der Radius der Kugel. Dann gibt es nämlich eine Kollision mit einem Eckpunkt der Kugel. Zur Kollision von Kugeln mit Ecken findest du hier im Forum sämtliche Beiträge. Das wird allerdings dann etwas komplizierter.


So könntest du das Zeichen machen:

Delphi-Quellcode:
BitBlt(Spielfeld.Canvas.Handle, Spielerposition[1].X, Spielerposition[1].Y,
   Spieler.Width, Spieler.Height, Spieler.Canvas.Handle, 0, 0, SRCCOPY);
BitBlt(Spielfeld.Canvas.Handle, Spielerposition[2].X, Spielerposition[2].Y,
   Spieler.Width, Spieler.Height, Spieler.Canvas.Handle, 0, 0, SRCCOPY);
BitBlt(Spielfeld.Canvas.Handle, Ballposition.X, Ballposition.Y, Ball.Width,
   Ball.Height, Ball.Canvas.Handle, 0, 0, SRCCOPY);
Du brauchst also gar kein weiteres Bitmap im Hintergrund erstellen. Um das löschen des zuvorgezeichneten brauchst du dich auch nicht kümmern, weil das durch Invalidate + OnPaint sowieso gelöscht wird. Das, was du sonst noch so auf dem Bildschirm darstellen wirst, bleibt ja unverändert. Du könntest es also auf einem Image im Hintergrund darstellen, an dem du später nichts ändern brauchst. Du lädst einfach das Bitmap über den Objektinspektor in dein Image. Damit das Image sich nicht über der PaintBox befindet und diese verdeckt, kannst du auf es rechtsklicken und nach hinten setzen auswählen.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 5  1 23     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:40 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz