Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Break-Game, Kugel auf Rechtecklanden lassen ... (https://www.delphipraxis.net/116308-break-game-kugel-auf-rechtecklanden-lassen.html)

KleinAmann 26. Jun 2008 16:43


Break-Game, Kugel auf Rechtecklanden lassen ...
 
Hey Leutz,

Ich habe früher viel C++ Programmiert bin aber vor einiger Zeit auf Delphi umgestiegen.

Nun bin ich dabei ein naja einfaches Game zu schreiben, mein Problem liegtnach
if (bar.Top = Kugel.Top)
then if

vermute ich Code.

Und zwar soll, wenn der Ball auf das Rechteck fliegt wieder zurück kehren.
Dummerweiße erkennt mein Programm nicht dass der Ball die gleiche .left wie mein
Balken(Rechteck) hat. Dass rechteck hat eine Width von 25 darum auch immer +1/-1
da er ja , egal auf welcher Fläche er landet es Merken soll.

Ich hoffe ihr habts kapiert ...

Hier der Code :

Hey Leutz,

Ich habe früher viel C++ Programmiert bin aber vor einiger Zeit auf Delphi umgestiegen.

Nun bin ich dabei ein naja einfaches Game zu schreiben, mein Problem liegtnach
if (bar.Top = Kugel.Top)
then if

vermute ich Code.

Und zwar soll, wenn der Ball auf das Rechteck fliegt wieder zurück kehren.
Dummerweiße erkennt mein Programm nicht dass der Ball die gleiche .left wie mein
Balken(Rechteck) hat. Dass rechteck hat eine Width von 25 darum auch immer +1/-1
da er ja , egal auf welcher Fläche er landet es Merken soll.

Ich hoffe ihr habts kapiert ...

Hier der Code :

Delphi-Quellcode:
var
  Form1: TForm1;
  counter : integer;
  xK : integer;
  yK: integer;
  i : integer;

implementation

{$R *.dfm}


procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
yy : string;
xx : string;
begin
yy := IntToStr(Y);
xx := IntToStr(X);
aY.Caption := yy;
aX.Caption := xx;

if Y > 350 then if Y < 426 then bar.Top := Y;
if X < 501 then bar.Left := X;                // Bar der Maus nachlaufen lassen!
end;



procedure TForm1.FormActivate(Sender: TObject);
begin
counter := 1;
xK := 300;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
Kugel.Left := xK;
if (i = 1) then begin counter := counter +1;
                      yK := counter; end else
if (i = 2) then begin counter := counter -1;
                      yK := counter; end;

if (bar.Top = Kugel.Top)
  then if
   (bar.Left =
   (Kugel.Left) or (Kugel.Left +1) or (Kugel.Left -1) or
   (Kugel.Left +2) or (Kugel.Left -2) or (Kugel.Left +3) or (Kugel.Left -3) or
   (Kugel.Left +4) or (Kugel.Left -4) or (Kugel.Left +5) or (Kugel.Left -5) or
   (Kugel.Left +6) or (Kugel.Left -6) or (Kugel.Left +7) or (Kugel.Left -7) or
   (Kugel.Left +8) or (Kugel.Left -8) or (Kugel.Left +9) or (Kugel.Left -9) or
   (Kugel.Left +10) or (Kugel.Left -10) or (Kugel.Left +11) or (Kugel.Left -11) or
   (Kugel.Left +12) or (Kugel.Left -12) or (Kugel.Left +13) or (Kugel.Left -13) or
   (Kugel.Left +14) or (Kugel.Left -14) or (Kugel.Left +15) or (Kugel.Left -15) or
   (Kugel.Left +16) or (Kugel.Left -16) or (Kugel.Left +17) or (Kugel.Left -17) or
   (Kugel.Left +18) or (Kugel.Left -18) or (Kugel.Left +19) or (Kugel.Left -19) or
   (Kugel.Left +20) or (Kugel.Left -20) or (Kugel.Left +21) or (Kugel.Left -21) or
   (Kugel.Left +22) or (Kugel.Left -22) or (Kugel.Left +23) or (Kugel.Left -23) or
   (Kugel.Left +24) or (Kugel.Left -24) or (Kugel.Left +25) or (Kugel.Left -25))
    then begin
    i := 2; end;
if Kugel.Top < 410 then
begin
  Kugel.Top := Kugel.Top + yK;
end else begin
  yK := 160; xK := 372; Panel1.Visible := true;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
i := 1
end;

end.
Mfg KleinAmann

Die Muhkuh 26. Jun 2008 16:45

Re: Break
 
Hi,

mach mal bitte die [delphi][/delphi]-Tags um Deinen Code :)

KleinAmann 26. Jun 2008 16:51

Re: Break
 
hey sry ;(

DP-Maintenance 26. Jun 2008 16:52

DP-Maintenance
 
Dieses Thema wurde von "Matze" von "Programmieren allgemein" nach "Multimedia" verschoben.
Delphi-Frage ;)

DeddyH 26. Jun 2008 16:53

Re: Break
 
Das geht so nicht:
Zitat:

Delphi-Quellcode:
(bar.Left =
   (Kugel.Left) or (Kugel.Left +1) or (Kugel.Left -1)...

Was Du auf diese Art und Weise machst, ist ein Binärvergleich.

Die Muhkuh 26. Jun 2008 16:55

Re: Break
 
Hi,

macht nichts. Kann jedem mal passieren, so schauts aber deutlich besser aus.

Zum Einen:

Delphi-Quellcode:
if (bar.Top = Kugel.Top)
wäre vielleicht ein

Delphi-Quellcode:
if (Kugel.Top >= Bar.Top)
besser, da es sonst wirklich genau gleich sein muss.

Zum anderen das lange If-Gewurschtel. Das kannst Du sicher mit

Delphi-Quellcode:
if ((Kugel.Left - 25 >= Bar.left) or (Kugel.Left + 25 <= Bar.Left))
o.Ä. ersetzen.

KleinAmann 26. Jun 2008 17:02

Re: Break
 
hey,

erstmal STAUN danke für die schnellen Antworten bin ich nicht gewohnt in anderen Fourms ;) DANKE

so ich hab mal

then if
((Kugel.Left - 25 >= Bar.left) or (Kugel.Left + 25 <= Bar.Left))

ausprobiert, leider macht er es immer noch nicht =(


* noch ne Frage bei mir Debugt der Compiler also Borland Delphi 2005 nicht mehr,
bin mal ausversehna auf : run -> run with out debugging gekommen wie mach
ich dies Rückgängig?
*

Naja vielen Dank für die Antworten bis jetzt ;)

Mfg KleinAmann

Die Muhkuh 26. Jun 2008 17:09

Re: Break
 
Einfach auf Run -> Run klicken oder alternativ auf F9 drücken.

Es wäre besser, wenn Du den Code zuerst einmal debuggst, Dir die Werte anschaust und guckst, warum er nicht in die Abfrage springt. Sonst raten wir hier nur rum.

Und mein Beispielcode muss nicht zwingend genau das sein, was es zum Laufen bringt. Es sollte nur als ein Beispiel dienen.

KleinAmann 26. Jun 2008 17:29

Re: Break
 
Hey,

Leider stimmt was komplett nicht, unzwar macht er es nciht einmla wenn die Top also die Höhe übereinstimmt.
Das hat eigentlich immer funktioniert..
Delphi-Quellcode:
if (bar.Top = Kugel.Top)
  then //if
  //((Kugel.Left - 25 >= Bar.left) or (Kugel.Left + 25 <= Bar.Left))
   // then
    begin
    i := 2; Panel1.Visible := true; Panel1.Caption := 'test'; end;


Delphi-Quellcode:
unit game;

interface

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

type
  TForm1 = class(TForm)
    bar: TShape;
    aX: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    aY: TLabel;
    Kugel: TShape;
    Timer1: TTimer;
    Panel1: TPanel;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  counter : integer;
  xK : integer;
  yK: integer;
  i : integer;

implementation

{$R *.dfm}


procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
yy : string;
xx : string;
begin
yy := IntToStr(Y);
xx := IntToStr(X);
aY.Caption := yy;
aX.Caption := xx;

if Y > 350 then if Y < 426 then bar.Top := Y;
if X < 501 then bar.Left := X;                // Bar der Maus nachlaufen lassen!
end;



procedure TForm1.FormActivate(Sender: TObject);
begin
counter := 1;
xK := 300;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
Kugel.Left := xK;
if (i = 1) then begin counter := counter +1;
                      yK := counter; end else
if (i = 2) then begin counter := counter -1;
                      yK := counter; end;

if (bar.Top = Kugel.Top)
  then if
  ((Kugel.Left - 25 >= Bar.left) or (Kugel.Left + 25 <= Bar.Left))
    then begin
    i := 2; Panel1.Visible := true; Panel1.Caption := 'test'; end;
if Kugel.Top < 410 then
begin
  Kugel.Top := Kugel.Top + yK;
end else begin
  yK := 160; xK := 372; Panel1.Visible := true;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
i := 1;
end;

end.

Die Muhkuh 26. Jun 2008 17:31

Re: Break
 
Was passiert, wenn Du auf größer gleich und nicht auf Gleichheit überprüft? (Oder auch auf <=, je nach, ob sich das Shape oben oder unten befindet)

Sharky 26. Jun 2008 17:52

Re: Break
 
Hai KleinAmann,

bitte gebe deinem Thread einen Titel von dem man auch gleich auf den Inhalt der Frage schliessen kann.

Dafür musst Du nur auf den "Edit"-Button neben dem obersten Posting von Dir klicken.

Nur wenn ein Thread einen Titel hat der auf die Frage schliessen lässt haben andere die Möglichkeit, durch benutzen der Suchfunktion, eine Lösung für ähnliche Fragen zu finden.

Danke :!:

KleinAmann 26. Jun 2008 20:18

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
hey,

also wenn man das ungleich macht (<= | >=)
dann funtz es aber es ist wichtig dass es genau ist weil
sonst hat das Spiel dummerweiße keinen sinn :(

Bitte um weitere Hilfe


P.s ich schreibe so spät da unser Router den Geist aufgeben hat.
sry

Medium 27. Jun 2008 00:48

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
Liste der Anhänge anzeigen (Anzahl: 1)
Genau wird dein Ball jedoch in den seltensten Fällen treffen, da er sich wahrscheinlich meist um mehr als nur einen Pixel pro Step bewegt. Die genauste Möglichkeit das in den Griff zu bekommen ist es, wenn du den Flugvektor den Balles nimmst, und die Gerade die er erzeugt mit der Kollisionsgeraden schneidest. Liegt der Schnittpunkt innerhalb des unskalierten Flugvektors, tritt zwischen dem letzten und nächsten Step die Kollision ein. Dann kannst du den Flugverktor an der Normalen der Kollisionsgeraden im Schnittpunkt spiegeln (Reflexion), und ihn um den restlichen Betrag den der vorige Flugvektor über die Kollisionsgerade hinaus geht in die neue Richtung verschieben. Damit hast du dann die Kollision "zwischen" zwei Steps korrekt berechnet, obwohl der Ball den Schläger niemals sichtbar berührt.

Der einfachere und ungenauere (meist aber ausreichende) Weg ist es, den Ball sobald der über die Kollisionsgerade hinaus ist, genau über diese zu platzieren, und fortan den reflektierten alten Flugvektor zum aktuellen zu machen. Damit erspart man sich die Schnittpunktbestimmung, und die Verhältnisbildung des Schnittpunktes zum Flugvektor, sowie ein paar Additionen. Nachteil der Variante ist, dass man den tatsächlichen Schnittpunkt ja nur noch approximiert, und nicht die exakte Flugbahn einhält. Dadurch kann das gerade bei hohen Geschwindigkeiten zu ruckartigem unerwarteten Verhalten führen.

Gruß,
Medium

Edit: Hab mal noch n Bildchen zu obigem gemacht. In Worten ist das glaube ich schwer nachvollziehbar.

KleinAmann 27. Jun 2008 14:23

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
hey,

erstaml WOW für die geile Idee und für die Grafik.

Leider denk ich nicht dass ich das hingrieg, werd aber mal versucehn.

Vielen Dank nochmal an alle ich werd mich aufjedenfall melden ;)

Mfg Domi

KleinAmann 27. Jun 2008 18:20

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
hey,

Hab jetzt sehr viel ausprobiert aber bekomms einfach nicht hin =(

Könnt ihr mir ein Tipp geben?

Mfg
Domi

Die Muhkuh 28. Jun 2008 07:12

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
Morgen,

häng doch bitte mal das Projekt an.

KleinAmann 28. Jun 2008 10:37

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
Liste der Anhänge anzeigen (Anzahl: 1)
Morgen =),

Hier ist mein Code, und das ganze Projekt ist net grad das beste weil
in die richtung hab ich noch nichts gemacht.

Mfg Domi

P.s wenn ich in Delphi mein Priójekt abspeichern will, kommt oft
das ich eine Acess violation hab und dann noch was mit karasx2.dll.
kennt jemand das Problem, und kann helfen wäre
echt super nett =)

mimi 28. Jun 2008 13:40

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
es gibt auch noch ptinRect evlt. reicht das schon für deine Kollision Erkennung.

KleinAmann 29. Jun 2008 10:58

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
wie funktioniert die Funktion?

mimi 29. Jun 2008 11:44

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
Ganz einfach: Du übergibst zuerst ein TRect und dann ein TPoint.
Es dürften hier genügend beispiele geben. Für ein BreakOut Clone dürfte das ausreichen.

am besten währe es du schreibst dir eine Funktion die alle Objekte durch geht und die angeben Position vergleich.
Die Funktion prüft letztendlich nur ob ein Punkt in Viereck liegt. Wenn ja wird True zurück geben wenn nein wird False zurück geben.

Es gibt noch weitere nützliche Funktionen. z.b. eine die vergleich ob zwei Viereck sich schneiden.

PS:
Ich kann dir gerne mal meine 2D Engine geben bzw. die gibt es hier zum runter laden.
Allerdings geht sie nur in Verbindung mit Lazarus. Die Engine basiert komplett auf Canvas.

Oder du kannst auch noch Andorra nutzten, wie ich gesehen habe ist es damit auch recht einfach.
Aber vermutlich währe es für ein einfachen BreakOut Clone übertrieben(dort gibt es übrings schon einen als beispiel)

KleinAmann 29. Jun 2008 19:21

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
hey,

würde mich über eine 2D engine sehr freuen

wäre cool wenn du mla von beiden den Link postest.

Vielen Dank

Mfg Domi

mimi 29. Jun 2008 19:28

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
naja die engine läuft nur unter Lazarus. Ich habe sie hier gerade nichte gefunden.
ich lade sie später hoch. Aber ich weiß nicht so recht, ob sie dir weiter helfen wird.

mimi 29. Jun 2008 21:41

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
So hier habe ich die "2D Engine" gerade eben hochgeladen:
http://www.delphipraxis.net/posting.php#top

Ich habe zwar auch ein eigenen BreakOut Clone geschrieben, aber ich glaube den veröffentliche ich erst später, weil der auf das GamePack basiert, welches intern meine "2D Engine" nutzt.

Medium 30. Jun 2008 11:46

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
Wenn man mit PtInRect arbeitet muss man aber mindestens von einem der möglichen Kollisionspartner wirklich JEDEN Pixel einzeln überprüfen, oder aber eine geschlossene "Sensorlinie" abprüfen. Beides Gefummel und nicht wirklich performant, und wenn das Rect zu schmal ist, bzw. der Ball zu schnell kann er dir dabei immer noch einfach durchfliegen. Das lässt sich dann nur noch mit Schnittpunktbestimmung umgehen, welche zudem nicht nur die reine Kollision feststellt, sondern auch gleich Infos zur korrekten Reflexion liefert. Auf Pixeltests basierende Kollisionen halte ich für grausiges Gefrickel (zumindest wenn darauf hin etwas "abprallen" soll) :)

mimi 30. Jun 2008 11:53

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
Nein, das ist nicht so richtig.

Wenn du den Ball bewegen möchtest, weißt du ja wohin. Jetzt muss du nur noch in einer schleife prüfen ob dort schon ein Objekt ist oder nicht. Rate mal wie das Andorra macht ? oder ich bei meiner 2D Engine.

Die heutigen Rechner können das. und du wirst warscheinlich nicht 10000 Objekte haben. Wenn es hoch kommt wirst du evlt. gerade mal 100 oder 200 Objekte habe.

und die Funktion prüft auch nur ob im angeben Viereck ein Punkt liegt. Das ist sehr viel schneller als jeden Pixel zu prüfen.

Du hast ein Viereck und die Funktion prüft jetzt einfach nur noch ob in diesem Viereck die angeben Koordinaten liegen.
Mehr nicht. Das sollte bei den meisten Rechner überhaupt kein Problem da stellen.


Und wie möchtest du es sonst lösen ?
In deinen Fall könntest du auch noch ein zweites BitMap einfügen, wo du nur unbewegliche Objekte rein tust.
die werden dann in einer Farbe gezeichnet, der Rest in einer anderen.

Wenn du den Ball bewegt, könntest du einfach nach schauen ob dort frei ist oder nicht. mit Hilfe von Pixels von Canvas.
Aber diese Lösung wird viel mehr Speicher brauchen.

Zum Aprallen hier gibt es auch ein Beispiel in der "Code Lib" dazu:
http://www.delphipraxis.net/internal...ight=abprallen

Medium 30. Jun 2008 12:07

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
Zitat:

Zitat von mimi
Wenn du den Ball bewegen möchtest, weißt du ja wohin. Jetzt muss du nur noch in einer schleife prüfen ob dort schon ein Objekt ist oder nicht. Rate mal wie das Andorra macht ? oder ich bei meiner 2D Engine.

*schüttel* ("Weil hunderttausende Fliegen..." man kennt den Spruch ;)) Es geht halt auch ohne häßliche Pixelschritt-Schleife.

Zitat:

Zitat von mimi
Die heutigen Rechner können das. und du wirst warscheinlich nicht 10000 Objekte haben. Wenn es hoch kommt wirst du evlt. gerade mal 100 oder 200 Objekte habe.

Genau, deswegen schreibe ich auch erstmal in jedem meiner Programme mindestens 1GiB Schrott in den Speicher, weil die meisten haben ja genug davon.

Zitat:

Zitat von mimi
und die Funktion prüft auch nur ob im angeben Viereck ein Punkt liegt. Das ist sehr viel schneller als jeden Pixel zu prüfen.

Was ist aber, wenn der "Ball" in diesem Fall größer als nur einen Pixel ist? Es geht nicht um jedes Pixel im Rechteck, sondern in dem des zweiten Objektes.

Zitat:

Zitat von mimi
Du hast ein Viereck und die Funktion prüft jetzt einfach nur noch ob in diesem Viereck die angeben Koordinaten liegen.
Mehr nicht. Das sollte bei den meisten Rechner überhaupt kein Problem da stellen.

Wenn man es ein paar tausend bis zigtausend Mal pro Sekundenbruchteil macht schon, sei versichert.

Zitat:

Zitat von mimi
Und wie möchtest du es sonst lösen ?

So!

Zitat:

Zitat von mimi
Wenn du den Ball bewegt, könntest du einfach nach schauen ob dort frei ist oder nicht. mit Hilfe von Pixels von Canvas. Aber diese Lösung wird viel mehr Speicher brauchen.

Canvas.Pixels - genau der richtige Partner, wenn man einen PC mal so richtig ausbremsen möchte. (Und SO viel mehr Speicher braucht das nicht. Man hat ja so viel davon!)


Versteh mich nicht falsch, ich will niemanden einfach nur anmachen, aber was du da geschrieben hast ist imho eine echte Sammlung von no-gos, die man so nicht stehen lassen kann.

mimi 30. Jun 2008 13:04

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
Wenn du meinst. Man kann es auch übertreiben das stimmt. Ich habe mir den Code jetzt nicht angesehen, weil unter Linux kann ich noch nicht ohne weiteres neue Rar Formate entpacken. Ich habe nur ein Komandozeilen tool.
Wenn ich mal lust habe mache ich das.

Medium 30. Jun 2008 13:56

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
GIF <> RAR :gruebel:

mimi 30. Jun 2008 14:36

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
Hast recht, habe den falschen Anhang angeschaut.
Ich verstehe zwar das bild nicht so recht, aber ich glaube wie meinen im Grunde das gleiche, nur reden wir gerade aneinander vorbei. So wie das Bild aussieht meinte ich das eigentlich auch. So macht das ja auch ptinRect. Schau dir mal die Funktion an.

Medium 30. Jun 2008 15:24

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
PtInRect macht folgendes:
Es nimmt einen 2D-Punkt entgegen, und ein Rect. Dann wird die X-Koordinate des Punktes auf größer/kleiner mit der linken/rechten Begrenzung des Rects verglichen, sowie die Y-Koordinate mit der oberen/unteren Grenze. Das ergebnis ist die 4 Vergleiche and-verknüpft.
Das muss man nun für jeden Punkt des zu testenden Objektes machen, und für jeden Punkt den dieses im Laufe der Bewegung einnehmen wird.

Was ich mache ist etwas völlig anderes. Ich nehme den Richtungsvektor des beweglichen Objektes, und erstelle mir eine Gerade auf den Ballmittelpunkt gestütz, setzte diese gleich mit der Gerade die die Kollisionsoberfläche bildet, und erhalte nach lösen des kleinen LGS einen Parameter, der angibt wie oft ich den Richtungsverktor "malnehmen" muss, um auf die Oberfläche zu treffen. Ist der Parameter kleinergleich eins, tritt die Kollision im anstehenden Schritt auf, und mit den dann vorhandenen Daten kann man zudem leicht ein physikalisch korrektes Abprallverhalten trotz mögl. großschrittiger Bewegung errechnen.

Was man mit PtInRect macht ist Pixelweise rumfrickeln, was ich mache ist einfache lineare Algebra. Vorteile letztrer Variante:
- Konstanter Zeitverbrauch (man muss nicht u.U. alle Pixel in einer Diagonalen quer über den Bildschirm abstesten)
- Kollision wird IMMER gefunden, selbst wenn das Objekt so klein/schnell ist, dass es sonst weit über den Kollisionspartner "springen" würde
- Analytischer statt diskreter Ansatz
- Universell einsetzbar (Die Kollisionspartner müssen keine rechtwinkligen Vierecke oder Kugeln sein, auch wenn es die einfachsten Fälle sind)

Nachteile:
- Man muss in der Schule bei Vektorrechnung gerade wach gewesen sein, zumindest halb ;)


Und wie vorher schon erwähnt, kann man in diesem speziellen Fall einige sehr deutliche Vereinfachungen machen, da man immer mit horizontalen Linien Kollidiert, diese keine Eigenbewegung haben, und die Präzision sehr wahrscheinlich ausreichen wird. Wie, hatte ich ja auch schon geschrieben.

Der TE müsste nur mal ein wenig genauer werden als "geht nicht", dann könnte man vermutlich sogar konkret weiter helfen :roll:

KleinAmann 30. Jun 2008 15:58

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
okay,

dass war jetzt relativ viel aufeinmal.

Ich werds wenn ich daheim bin nochmla ganz in ruhe durchlesen

Vielen Dank fürs erste

Mfg Domi

mimi 1. Jul 2008 10:08

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
Zitat:

Das muss man nun für jeden Punkt des zu testenden Objektes machen
Nein das ist Unsinn, das muss nur für jedes Objekt gemacht werden, nicht für jeden Punkt. Du brauchst nur die linke obere ecke angeben.

Zitat:

Was man mit PtInRect macht ist Pixelweise rumfrickeln
nein, nein. Du hast mich anscheind immer noch nicht richtig verstanden.
Hier mal ein Beispiel, wie ich diese Funktion einsetzte:
Delphi-Quellcode:
function TPluto2SpriteManger.N_Collision(const ax, ay: Integer;
  const aEvent: Boolean; const aPixelcheck: boolean): TPluto2DSprite;
var
  i:Integer;
  sp:TPluto2DSprite;
  p:TPoint;
  r1:TRect;
begin
  sp:=nil; p:=Point(ax,ay); r1:=Engine.GameFehld;
  // Schauen ob die Positions Angabe im Spielb Rect Liegt
  if (PtInRect(r1,p)) then begin
    for i:=0 to fItems.Count-1 do begin
//      p:=Point(ax+Items[i].Width,ay+Items[i].Height);
      if PtInRect(Items[i].GetR,p) then begin
        if (not items[i].NoCollision) and (items[i].visible) then begin
          sp:=Items[i];
          //break;
        end;
      end;
    end; // for i
  end;

  if (aEvent) and (Assigned(Engine.onCollision) ) then begin
    Engine.onCollision(nil, sp);
  end;

  result:=sp;
end; // TPluto2SpriteManger.N_Collision
Ganz verstehe ich deine Methode immer noch nicht.

Medium 1. Jul 2008 11:47

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
Entweder bin ich gerade wirklich sehr blind, oder du prüfst hier doch nur, ob der Pixel (ax, ay) im Spielfeld liegt, und wenn ja, ob er in einem anderen Sprite liegt, dass die Kollisionsprüfung an hat, wobei du zudem davon ausgehst, dass ein Sprite immer rechteckig und nicht gedreht ist.
Wenn ich aber nicht die Kollision eines einzelnen Pixels (ax, ay), sondern z.B. eines Kreises prüfen will, wie erledigst du das?

edit: "aPixelcheck" klingt interessant, wird aber nirgends benutzt.

mimi 1. Jul 2008 12:21

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
Zitat:

edit: "aPixelcheck" klingt interessant, wird aber nirgends benutzt.
Ja das stimmt, ich habe aber andere Collisions Funktionen wo es genutzt wird.
Diese Stufe soll ja auch nur erstmal eine grobe Feststellung sein.

hier noch mal ein code wi aPixelCheck auch genutzt wird:
Delphi-Quellcode:
function TPluto2SpriteManger.N_Collision(const ax, ay:Integer; const aSprite: TPluto2DSprite;
  const aEvent: Boolean; const aPixelcheck: boolean): TPluto2DSprite;
var
  i:Integer;
  sp:TPluto2DSprite;
  p:TPoint;
  r1, r2, r3,r4,r5:TRect;
begin
  sp:=nil; p:=Point(ax,ay); r1:=Engine.GameFehld;
  r2:=Rect(ax, ay, ax+aSprite.Width, ay+aSprite.Height);
  r4:=rect(aSprite.Left,aSprite.Top,aSprite.Width,aSprite.Height);
  // Schauen ob die Positions Angabe im Spielb Rect Liegt
  if (PtInRect(r1,p)) then begin
    for i:=0 to fItems.Count-1 do begin
      if (aSprite.guid <> items[i].guid) then begin
        if IntersectRect(r3,items[i].GetR,r2) then begin
          if (not items[i].NoCollision) and (items[i].visible) then begin
            if not aPixelcheck then begin
              sp:=Items[i];
              break;
            end
            else begin
              r5:=rect(items[i].Left,items[i].Top,items[i].Width,items[i].Height);
              if kollision(r4,r5,aSprite.SpriteImage,items[i].SpriteImage) then begin
                sp:=Items[i];
                break;
              end; // if kollision(..)
            end; // else begin
          end; // if (not NoCollision)
        end; // if IntersectRect(..)
      end; // if asprite.guid <> items[i].guid
    end; // for i
  end;

  if (sp <> NIL) and (aEvent) and (Assigned(Engine.onCollision)) then begin
    Engine.onCollision(nil, sp);
  end;
  result:=sp;
end; // TPluto2SpriteManger.N_Collision  

{
  Autor: umpani, Michael Springwald
  Update:
  Freitag den 25.Janur.2008, Freitag, 01.Febura.2008

  Diese Funktion stammt von "umpani" und ist hier zu finden:
  [url]http://www.delphi-forum.de/viewtopic.php?t=12746&postdays=0&postorder=asc&start=20[/url]

  Ich habe sie "nur" Angepasst für mein zweck. Fragen also bitte an
  "umpani" richten im delphi-forum.de.
}

function kollision(r1,r2:TRect;B1,b2:TBitMap):boolean;
var
  ueberlapp_breite, ueberlapp_hoehe:integer;
  ueberlapp_nr1_x, ueberlapp_nr1_y, ueberlapp_nr2_x, ueberlapp_nr2_y:integer;
  x,y:integer;
  farbenr1,farbenr2:TColor;
  z:Boolean;
begin
  z:=False;
  if r1.left < r2.left then
    ueberlapp_breite := (r1.left + r1.Right) - (r2.left)
  else
    ueberlapp_breite := (r2.left + r2.Right) - r1.Left;

  if r1.Right > r2.Right then if ueberlapp_breite >= r2.Right then ueberlapp_breite := r2.Right;

  if r1.top < r2.top then
     ueberlapp_hoehe := (r1.Top + r1.Bottom) - (r2.Top)
   else
     ueberlapp_hoehe := (r2.Top + r2.Bottom) - (r1.Top);

  if r1.Bottom > r2.Bottom then if ueberlapp_hoehe > r2.Bottom then ueberlapp_hoehe := r2.Bottom;

  if (ueberlapp_breite > 0) and (ueberlapp_hoehe > 0) then begin
    if r1.Right >= r2.Right then begin
      if (r2.Left+r2.Right) >= (r1.Left+r1.Right) then begin
        ueberlapp_nr1_x := r1.Right - ueberlapp_breite;
        ueberlapp_nr2_x := 0;
      end;

      if ((r2.Left+r2.Right) < (r1.Left+r1.Right)) and (r2.left >= r1.left) then begin
        ueberlapp_nr1_x := (r2.Left-r1.Left);
        ueberlapp_nr2_x := 0;
      end;

      if (r2.Left) < (r1.Left) then begin
        ueberlapp_nr1_x := 0;
        ueberlapp_nr2_x := r2.Right - ueberlapp_breite;
      end;
    end;
  end;

  if r1.Right < r2.Right then begin
    if (r1.Left+r1.Right) >= (r2.Left+r2.Right) then begin
      ueberlapp_nr2_x := r2.Right - ueberlapp_breite;
      ueberlapp_nr1_x := 0;
    end;

    if ((r1.Left+r1.Right) < (r2.Left+r2.Right)) and (r1.Left >= r2.Left) then begin
      ueberlapp_nr2_x := (r1.Left-r2.Left);
      ueberlapp_nr1_x := 0;
    end;

    if (r1.Left < r2.Left) then begin
      ueberlapp_nr2_x := 0;
      ueberlapp_nr1_x := r1.Right - ueberlapp_breite;
    end;
  end;

  if r1.Bottom >= r2.Bottom then begin
    if (r2.Top+r2.Bottom) >= (r1.Top+r1.Bottom) then begin
      ueberlapp_nr1_y := r1.Bottom - ueberlapp_hoehe;
      ueberlapp_nr2_y := 0;
    end;

    if ((r2.Top+r2.Bottom) < (r1.top+r1.Bottom)) and (r2.Top >= r1.Top) then begin
      ueberlapp_nr1_y := (r2.top-r1.top);
      ueberlapp_nr2_y := 0;
    end;

    if (r2.top) < (r1.top) then begin
      ueberlapp_nr1_y := 0;
      ueberlapp_nr2_y := r2.Bottom - ueberlapp_hoehe;
    end;
  end;

  if r1.Bottom < r2.Bottom then begin
    if (r1.Top+r1.Bottom) >= (r2.Top+r2.Bottom) then begin
      ueberlapp_nr2_y := r2.Bottom - ueberlapp_hoehe;
      ueberlapp_nr1_y := 0;
    end;

    if ((r1.Top+r1.Bottom) < (r2.Top+r2.Bottom)) and (r1.Top >= r2.Top) then begin
      ueberlapp_nr2_y := (r1.top-r2.top);
      ueberlapp_nr1_y := 0;
    end;

    if (r1.top < r2.top) then begin
      ueberlapp_nr2_y := 0;
      ueberlapp_nr1_y := r1.Bottom - ueberlapp_hoehe;
    end;
  end;

  for x := 0 to (ueberlapp_breite-1) div 2 do begin
    for y := 0 to (ueberlapp_hoehe -1) div 2 do begin
      farbenr1 :=B1.Canvas.Pixels[ueberlapp_nr1_x+x*2,ueberlapp_nr1_y+y*2];
      farbenr2 :=B2.Canvas.Pixels[ueberlapp_nr2_x+x*2,ueberlapp_nr2_y+y*2];
      if ( farbenr1 <> b1.TransparentColor) and (farbenr2 <> b2.TransparentColor) then begin
        result:=True;
        exit;
      end;
    end; // for y
  end; // for x
  result:=False;
end; // kollision
Wie du siehst kann ich einmal nur eine Grobe Kollision Erkennung machen und eine genauere. Wobei eine Pixel Check Funktion natürlich länger dauert und auch mehr speicher Verbraucht. Darum mache ich es eine ungenauere.
Ich nutzte sowieso eigentlich nur Vierecke. Aber für den Fall der Fälle habe ich so eine Funktion eingebaut.

Per Default Paramenter wird immer eine Pixel Check Prüfung durch gefürht sowie ein Event ausgelöst. Was beides aber abgestellt werden kann.

Ich habe die "2D Engine" geschrieben für einfache 2D Spiele. Ich rechne nicht damit das ein Spiel 10000 Objekte hat.
Dafür sollte besser Andorra oder so genutzt werden.
Ich denke die Collisions Funktion dürfte für die meisten Spiele ausreichen oder ?

Medium 1. Jul 2008 13:22

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
Das ganze ist zwar soweit schon deutlich besser, wenn auch recht wenig auf Performance optimiert, jedoch bleibt der wichtigste Punkt offen:
Was passiert, wenn ein 10*10 Pixel großes Sprite kurz vor einem anderen 5*5 Pixel großem Sprite steht, sich aber mit sagen wir mal 10 Pixel pro Bild darauf zu bewegt? Das Sprite überspringt das andere, und die eigentlich stattfindende Kollision wird nicht erkannt. Darüber hinaus liefert deine Methode trotz ihrer Aufwendigkeit nur die Information "Kollision" (das aber wie gesagt nichtmal verlässlich), wogegen mein Ansatz quasi nebenbei auch gleich weiter nutzbare Größen ausspuckt, über die man den Stoß gleich mit berechnen kann, und zudem IMMER eine Kollision entdeckt, selbst wenn sich ein Sprite mit drei Bildschirmbreiten pro Bild schnell bewegen würde, und die "Wand" nur einen Pixel breit ist. DAS ist doch der Punkt um den es mir geht!

KleinAmann 5. Jul 2008 23:08

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
hey,

sry ich blick jetzt nicht mehr durch sry

kann mir bitte jetzt einer erklären wie ich dass machen soll?

wäre super nett =)

GN8 Domi

Medium 6. Jul 2008 02:22

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
Sag uns doch bitte nochmal ganz genau was du vor hast, und wo ganz genau das Problem liegt, und was du evtl. schon probiert hast.

KleinAmann 6. Jul 2008 11:55

Re: Break-Game, Kugel auf Rechtecklanden lassen ...
 
hey,

Das Problem liegt bei dem ab brallen,
die Idee von der Grafik hat mich sehr überzeugt leider nicht hinbekommen,
deshalb hab ich ja gefragt.

würde mich sehr freuen wenn mir ihr jemand
ein Beispiel oder ein gut Kommentierten Code Posten könnte.
So das der Ball ab brallt in in dem bestimmten errechneten Winkel
zurück brallen lässt.

Mfg Domi


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:21 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