#1 07.09.2005 06:58:51

firlefanz
GodlikeMember
Ort: Olpe in NRW
Registriert: 31.01.2005
Beiträge: 1035
Web-Seite

Freie Schussbahn

Hallo,

also mit dieser Funktion rufe ich ab, ob mein Sprite mit einem anderen Sprite kollidiert. Jedes Sprite hat dafür ein benutzerdefiniertes Rect (RectCol). Falls jemand hierzu einen Verbesserungsvorschlag für die Geschwindigkeit hat, jderzeit gerne.  big_smile

Code: delphi

function tcommandoform.rect_collide(spriteself:tsprite): boolean;
var i: integer;
    l,r,t,b: single;
begin
  result:=false;
  for i:=0 to xensprite.count-1 do begin
    if (spriteself <> xensprite.items[i]) and (xensprite.items[i].name<>'Bullet') and
    ((max(spriteself.rectcol.left+spriteself.x,xensprite.items[i].rectcol.left+xensprite.items[i].x) < min(spriteself.rectcol.right+spriteself.x, xensprite.items[i].rectcol.right+xensprite.items[i].x)) and
    (max(spriteself.rectcol.top+spriteself.y, xensprite.items[i].rectcol.top+xensprite.items[i].y) < min(spriteself.rectcol.bottom+spriteself.y, xensprite.items[i].rectcol.bottom+xensprite.items[i].y))) then begin
     result:=true;
     exit;
   end;
  end;
  result:=false;
end;



[Edit by Coolcat] Code-Tag ergänzt [/Edit]

So. Jetzt brauche ich eine Funktion, die mir entweder für 2 Punkte, oder für 1 Punkt mit Richtung (8 Richtungen Senkrecht Waagerecht und Diagonalen) True liefert, wenn kein Sprite zwischen den beiden Punkten bzw. nix in die Richtung liegt, anhand dieser Rects.

Wie mache ich das am besten?

Firle

Offline

 

#2 07.09.2005 07:16:08

Coolcat
ProGuru
Ort: Aachen, NRW
Registriert: 24.01.2005
Beiträge: 2780
Web-Seite

Re: Freie Schussbahn

Ich nehme mal an, dass du rect_collide für jedes Sprite aufrufst. Daran kann mal sicherlich noch wesentlich optimieren (sofern du mehr als ca. 100 Sprites hast), indem da beispielsweise mit einer Divide&Conquer-Strategie (Aufwand O(n*log n) ) rangehst, statt deinem BrutForce (Aufwand O(n^2) )...

Ansatz findest du hier (direkt das erste, "Maximale Punktdichte")
http://www-i8.informatik.rwth-aachen.de/teaching/ss05/datalg/downloads/PDF/2.7.3-nachbarschaften.pdf


Zu deiner zweiten Frage hab ich gerade keine Idee, aber such mal ne SweepTest oder sowas... (das ist der "Fachbegriff", glaub ich)

Coolcat


My software never has bugs. It just develops random features.

Offline

 

#3 03.11.2005 07:24:06

firlefanz
GodlikeMember
Ort: Olpe in NRW
Registriert: 31.01.2005
Beiträge: 1035
Web-Seite

Re: Freie Schussbahn

Hi!

Nochmals zur Kollision.

Ich nutze jetzt meine eigene Routine auch als eigene Kollsionserkennung, damit der Typ nicht durch Bäume rennt. Der Gedanke ist, dass nur ein Teil des Sprites kollidieren soll, aufgrund der Schrägansicht soll der Mann ja hinter einer Baumkrone gehen können, nur nicht mitten durch den Baum.

Also dient am Sprite ein Rechteck dazu: public RectCol: TRect;
Das soll meine Collision-Area sein.

In jeder Sprite Create Methode:

Zitat:

 
Rectcol.Top:=35;
Rectcol.left:=55;
Rectcol.bottom:=90;
Rectcol.right:=105;

Die ist z.B. für den Typen.

Dann in der Move Methode

Zitat:


begin
  lastxco:=xco;
  lastyco:=yco;
...
Sprite bewegen hier
...
  if commandoform.rect_collide(tsprite(self)) then begin
    xco:=lastxco;
    yco:=lastyco;
  end;
  //if a collision detection returns true set the sprite
  //back to location it had before
end;

Also wenn kollidiert, das Sprite auf die ursprüngliche Pos zurücksetzen.

Hier die Routine für den Kollisions-Check (ähnlich oben):

Zitat:


function TCommandoForm.rect_collide(SpriteSelf:TSprite): boolean;
var i: integer;
    l,r,t,b: single;
begin
  result:=false;
  for i:=0 to xensprite.count-1 do begin
    if (spriteself <> xensprite.Items[i]) and (xensprite.Items[i].name<>'Bullet') and
    ((max(spriteSelf.rectcol.left+spriteSelf.x,xensprite.Items[i].Rectcol.left+xensprite.Items[i].x) < min(spriteSelf.Rectcol.right+spriteSelf.x, xensprite.Items[i].Rectcol.right+xensprite.Items[i].x)) and
    (max(spriteSelf.Rectcol.top+spriteSelf.y, xensprite.Items[i].Rectcol.top+xensprite.Items[i].y) < min(spriteSelf.Rectcol.bottom+spriteSelf.y, xensprite.Items[i].Rectcol.bottom+xensprite.Items[i].y))) then begin
     result:=true;
     exit;
   end;
  end;
  result:=false;
end

Meistens klappt das, aber manchmal kann ich doch mitten durch den Baum rennen. An der Schrittgröße liegt es nicht, das habe ich schon getestet.

Irgendwelche Ideen, wie man das besser machen kann oder warum das so nur bedingt funktioniert?
:thx:
Firle

Offline

 

#4 03.11.2005 14:17:30

firlefanz
GodlikeMember
Ort: Olpe in NRW
Registriert: 31.01.2005
Beiträge: 1035
Web-Seite

Re: Freie Schussbahn

Hallo,

also ich habe jetzt selber gesehen, dass die String-Abfrage schlecht fürs Zeitverhalten ist und die durch ne Bool-Abfrage ersetzt. Problem ist aber immer noch das gleiche...

Firle

Offline

 

#5 05.11.2005 18:58:21

Chris
ExtremeMember
Ort: Erlangen, Bay
Registriert: 24.01.2005
Beiträge: 694
Web-Seite

Re: Freie Schussbahn

Ich würde 2 Sprites verwenden.

Eines das Kollidiert (Baumstamm)
und
eines das Darüberliegt (Blätter)

Dann hast du das Problem nicht.

mfg  chris


Nimm meinen Rat an - ich brauch ihn sowieso nicht

Offline

 

#6 05.11.2005 19:09:16

Coolcat
ProGuru
Ort: Aachen, NRW
Registriert: 24.01.2005
Beiträge: 2780
Web-Seite

Re: Freie Schussbahn

@Firle: Wie sieht den dein Koordiantensystem aus? Also wo ist bei dir "top", "bottom", "left" bzw. "right" ?

Wenn dein Ursprung bei dir unten links oder rechts in der Bildschirmecke  ist, würde das erklären, warum das bei dir nicht funzt...

Wenn es das nicht ist, liegt es an der Schrittweite. Versuch es mit einem Sweeptest, also teste ob ein Punkt deines Baums in dem bereich liegt, welcher von deinem Spieler in diesem Frame überschritten wird. Kann dir auch gerne nen bildchen dazu malen....hab allerdings wenig zeit im Moment...

Coolcat


My software never has bugs. It just develops random features.

Offline

 

#7 06.11.2005 10:29:23

firlefanz
GodlikeMember
Ort: Olpe in NRW
Registriert: 31.01.2005
Beiträge: 1035
Web-Seite

Re: Freie Schussbahn

Hallo,

danke für die Tips. Mittlerweile habe ich das hinbekommen, klappt jetzt viel besser :mrgreen:

Ich lasse jetzt alles hinlaufen wo will, und am Ende der Move-Methode wird bei Überlappung das entsprechende Sprite einfach zurückgesetzt, klappt jetzt sehr gut.  lol

Mein Koordinatensystem ist einfach 2D, also oben links ist 0,0 und unten rechts ist 1024,768...

Danke,

Firle

Offline

 

Brett Fußzeile

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson