AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Kollisionsabfrage für gedrehte Sprites mittels Vektoren

Kollisionsabfrage für gedrehte Sprites mittels Vektoren

Ein Thema von Sangoku · begonnen am 28. Feb 2006 · letzter Beitrag vom 3. Mär 2006
Antwort Antwort
Sangoku

Registriert seit: 13. Jan 2006
10 Beiträge
 
#1

Kollisionsabfrage für gedrehte Sprites mittels Vektoren

  Alt 28. Feb 2006, 19:44
Hallo alle zusammen.

Ich hab da mal ein Problemchen. Und zwar programmieren wir in der Schule grad ein paar Spielchen, und dabei kam das Problem auf, dass ein Sprite, das über die Angle-Eigenschaft gedreht wird, dafür seinen Pixelcheck einbüßen muss. Da dachte ich mir kein Problem - schreibst de einfach selber.

Zuerst hab ich mittels Bogenmaßrechnungen die X,Y-Koordinate des Sprites imaginär mit dem Winkel im Kreis wandern lassen, da die Orginal X,Y-Koordinate sich bei der Drehung des Sprites nicht verändert.

Delphi-Quellcode:
procedure TFigur.WinkelinVektoren;
var rad : Double;
begin
  //deg in rad umrechnen
  rad := ((Angle / 255 * 360) - 135) * (pi/180);

  //Die Drehung der X, Y Koordinate des Sprites simulieren
  XO := XU + cos(rad) * Radius;
  YO := YU + sin(rad) * Radius;
XU, YU stehen für den Mittelpunkt des Sprites - den Ursprung - und XO, YO sind die Koordinaten der wandernden Ecke oben links, die sich ja theoretisch mit der Drehung des Sprites mitdreht.

Als nächstes hab ich über das Bild im Sprite eine Ebene durch zwei Vektoren beschrieben, in der eine Pixelabfrage stattfindet. Vorerst soll die Kollisionsabfrage nämlich nur den Hintergrund auf Farben überprüfen.

Delphi-Quellcode:
rad := (Angle / 255 * 360) * (pi/180);

  //Richtungsvektor berechnen
  MoveVek.x := -(sin(rad)*yDiff);
  MoveVek.y := cos(rad)*yDiff;

  //Vektor der Höhe der Figur
  HochVek.x := -(sin(rad));
  HochVek.y := cos(rad);

  //Vektor der Breite der Figur
  rad := ((Angle / 255 * 360) - 90) * (pi/180);

  BreitVek.x := -(sin(rad));
  BreitVek.y := cos(rad);
end;
Der MoveVek ist der RichtungsVektor, der für die Bewegung des Sprites nach vorne und hinten zuständig ist. Der HochVek steht für die Höhe des Sprites und der BreitVek für dessen Breite.
Alle drei Vektoren drehen sich mit dem Bild im Sprite.

Soweit so gut, nun kommt die Pixelabfrage

Delphi-Quellcode:
function TFigur.PixelKollision(Farbe : TColor): TKollision;
var
  xi, yi : Integer;
  xw, yw : Double;
  Flag : Boolean;
  Status : TKollision;
begin
  Flag := false;
  Status := None;

  for yi := 0 to Width do begin
    for xi := 0 to Height do begin
      xw := XO + (BreitVek.x * xi) + (HochVek.x * yi);
      yw := YO + (BreitVek.y * xi) + (HochVek.y * yi);
      if Image.Picture.Bitmap.Canvas.Pixels[Round(xw - XO), Round(yw - YO)] <> Image.TransparentColor then
        if Form1.Spielfeld.Image.Picture.Bitmap.Canvas.Pixels[Round(xw), Round(yw)] = Farbe then begin
          Flag := true;
          if yw - YO < 0 then yw := -(yw - YO); //Hiermit will ich ermitteln
          if yw - YO <= Height div 2 then //ob die Kollsion beim vorwärts oder
            Status := Vorne //rückwärts laufen stattfindet
          else
            Status := Hinten;
          Break;
        end;
    end;
    if Flag then Break;
  end;

  Result := Status;
end;
Sie überprüft den Hintergrund auf eine variable Farbe, die mit Funktionsaufruf übergeben wird, aber nur in dem Bereich des Sprites, der auch tatsächlich von der Spielfigur überdeckt wird. Der Bereich, der als transparent deklariert ist, soll nicht überprüft werden.

Ich habe das gleich Verfahren in einem Testprogramm angewendet, hab dort allerdings statt nicht Pixel abgefragt, sonderm gezeichnet. Die Drehung und die Vektorebene funktionieren eigentlich einwandrei.

Delphi-Quellcode:
type
  TVektor = class
  private

  public
    x, y : Double;
    constructor Create;
    destructor Free;
  end;

type
  TForm1 = class(TForm)
    Image1: TImage;
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure FormCreate(Sender: TObject);
    procedure WinkelinVektoren;
    procedure PixelKollision;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  MoveVek, HochVek, BreitVek : TVektor;
  Angle, X, Y : Integer;
  XO, YO, XU, YU, Radius : Double;

implementation

{$R *.dfm}

constructor TVektor.Create; begin end;

destructor TVektor.Free; begin end;

procedure TForm1.WinkelinVektoren;
var rad : Double;
begin
  //deg in rad umrechnen
  rad := ((Angle / 255 * 360) - 135) * (pi/180);

  //neue Koordinaten setzten
  XO := 100 + cos(rad) * Radius;
  YO := 100 + sin(rad) * Radius;

  Image1.Canvas.Pixels[50, 50] := clBlack;
  Image1.Canvas.Pixels[Round(XO), Round(YO)] := clBlack;

  rad := (Angle / 255 * 360) * (pi/180);

  //Richtungsvektor berechnen
  MoveVek.x := -(sin(rad)*30);
  MoveVek.y := cos(rad)*20;

  //Vektor der Höhe der Figur
  HochVek.x := -(sin(rad));
  HochVek.y := cos(rad);

  //Vektor der Breite der Figur
  rad := ((Angle / 255 * 360) - 90) * (pi/180);

  BreitVek.x := -(sin(rad));
  BreitVek.y := cos(rad);
end;

procedure TForm1.PixelKollision;
var
  xi, yi : Integer;
  xw, yw : Double;
begin
  for yi := 0 to 45 do begin
    for xi := 0 to 45 do begin
      xw := XO + (BreitVek.x * xi) + (HochVek.x * yi);
      yw := YO + (BreitVek.y * xi) + (HochVek.y * yi);
      Image1.Canvas.Pixels[Round(xw), Round(yw)] := clBlack;
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  MoveVek := TVektor.Create;
  BreitVek := TVektor.Create;
  HochVek := TVektor.Create;

  Radius := sqrt((45*45)*2);
  Radius := Radius / 2;

  X := Image1.Width div 2;
  Y := Image1.Height div 2;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key = VK_Left then Angle := Angle - 2;
  if Key = VK_Right then Angle := Angle + 2;
  WinkelinVektoren;
  //Image1.Canvas.Rectangle(0, 0, Image1.Width, Image1.Height);
  PixelKollision;
end;

end.
Aber dennoch funktioniert die Kollisionsabfrage nicht richtig. Sobald ich das Objekt drehe und rumlaufe, passieren absolut verrückte Sachen. Mal wird die Farbe ignoriert oder gar dort erkannt, wo sie gar nicht ist. Wäre dür Hilfe echt dankbar, denn ich bin mit meinem Latein doch schon bald so ziemlich am Ende. Ich häng das komplette Programm mal als Anhang hinten dran.

Danke schon mal im voraus
Angehängte Dateien
Dateityp: rar atschool_868.rar (2,19 MB, 10x aufgerufen)
  Mit Zitat antworten Zitat
pacman1986

Registriert seit: 11. Feb 2005
Ort: Kirchhain
498 Beiträge
 
Delphi 2005 Personal
 
#2

Re: Kollisionsabfrage für gedrehte Sprites mittels Vektoren

  Alt 1. Mär 2006, 16:51
In deinem Quellcode (function TFigur.PixelKollision(Farbe : TColor): TKollision; ) hab ich das gefunden
Zitat:
for yi := 0 to Width do begin
for xi := 0 to Height do begin
y ist normalerweise die höhe
x die breite hier hast du es umgekehrt.

Liegt es daran ?

//Edit doch net in deinem testprogramm hast du ja feste werte
Christian N.
Designed to make a difference

najjaronline.de
  Mit Zitat antworten Zitat
Sangoku

Registriert seit: 13. Jan 2006
10 Beiträge
 
#3

Re: Kollisionsabfrage für gedrehte Sprites mittels Vektoren

  Alt 1. Mär 2006, 19:56
Da könnte durchaus was dran sein. Ich werde es direkt mal testen.
  Mit Zitat antworten Zitat
Sangoku

Registriert seit: 13. Jan 2006
10 Beiträge
 
#4

Re: Kollisionsabfrage für gedrehte Sprites mittels Vektoren

  Alt 3. Mär 2006, 18:25
Hallo alle zusammen.

Hab das Problem selbst gelöst. Hab die Drehung der Vektoren falsch berechnet und teilweise cos und sin vertauscht. Aber jetzt funzt es!
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 11:17 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