![]() |
Kollisionsabfrage für gedrehte Sprites mittels Vektoren
Liste der Anhänge anzeigen (Anzahl: 1)
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. :thumb: 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:
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. :corky:
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; 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. :coder2:
Delphi-Quellcode:
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.
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; Alle drei Vektoren drehen sich mit dem Bild im Sprite. Soweit so gut, nun kommt die Pixelabfrage :-D
Delphi-Quellcode:
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.
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; 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. :angel2:
Delphi-Quellcode:
Aber dennoch funktioniert die Kollisionsabfrage nicht richtig. Sobald ich das Objekt drehe und rumlaufe, passieren absolut verrückte Sachen. :wall: 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.
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. Danke schon mal im voraus :dp: |
Re: Kollisionsabfrage für gedrehte Sprites mittels Vektoren
In deinem Quellcode (function TFigur.PixelKollision(Farbe : TColor): TKollision; ) hab ich das gefunden
Zitat:
x die breite hier hast du es umgekehrt. Liegt es daran ? //Edit doch net in deinem testprogramm hast du ja feste werte :P |
Re: Kollisionsabfrage für gedrehte Sprites mittels Vektoren
:shock: Da könnte durchaus was dran sein. :oops: Ich werde es direkt mal testen.
|
Re: Kollisionsabfrage für gedrehte Sprites mittels Vektoren
Hallo alle zusammen.
Hab das Problem selbst gelöst. :dancer: Hab die Drehung der Vektoren falsch berechnet und teilweise cos und sin vertauscht. :wall: Aber jetzt funzt es! :bouncing4: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:40 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz