Delphi-PRAXiS
Seite 4 von 4   « Erste     234   

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 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 13:32 Uhr.
Seite 4 von 4   « Erste     234   

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