Einzelnen Beitrag anzeigen

mimi

Registriert seit: 1. Dez 2002
Ort: Oldenburg(Oldenburg)
2.008 Beiträge
 
FreePascal / Lazarus
 
#34

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

  Alt 1. Jul 2008, 12:21
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 ?
Michael Springwald
MFG
Michael Springwald,
Bitte nur Deutsche Links angeben Danke (benutzte überwiegend Lazarus)
  Mit Zitat antworten Zitat