Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Jul 04, 2025 10:08

Foren-Übersicht » Programmierung » Einsteiger-Fragen
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Fr Aug 06, 2010 15:42 
Offline
DGL Member

Registriert: Do Jan 07, 2010 21:58
Beiträge: 240
Hallo,

ich habe mich mal dem colorpicking gewidmet um herauszufinden auf welches meiner vielen vierecke geclickt wurde

also ich habe ein 2 dimesionales array (Karte array of array of TField;) welches der reihe nach abgearbeitet wird, jedes TField steht für ein viereck welches über eine ID verfügt, über welche das feld identifizieren kann

die koordinaten werden über 2 schleifen festgelegt sodass egal wie groß das array wird, es immer gleich gezeichnet werden kann

das sieht im ganzen so aus

Code:
procedure TMap.Render;
const
  fac: single = 1/255;
var x,y : Integer;
    iv: array[0..3] of byte absolute x;
begin
 if Length(Karte) > 0 then
  for x := Low(Karte) to High(Karte) do
    for y := Low(Karte[x]) to High(Karte[x]) do begin
     TextureManager.BindTexture(Karte[x,y].Texture);
    {$ifdef ENDIAN_BIG}
    glUniform4f(ShaderManager.color, iv[1]*fac, iv[2]*fac, iv[3]*fac, 1.0);
    {$else}
    glUniform4f(ShaderManager.color, iv[0]*fac, iv[1]*fac, iv[2]*fac, 1.0);
    {$endif}
       glBegin(GL_QUADS);
        glTexCoord2f(0,0);
         glVertex3f(x, 0, y);
        glTexCoord2f(1,0);
         glVertex3f(x+1, 0, y);
        glTexCoord2f(1,1);
         glVertex3f(x+1, 0, y+1);
        glTexCoord2f(0,1);
         glVertex3f(x, 0, y+1);
       glEnd;
       glBegin(GL_LINE_LOOP);
        glColor3f(0,0,0);
         glVertex3f(x, 0.02, y);
         glVertex3f(x+1, 0.02, y);
         glVertex3f(x+1, 0.02, y+1);
         glVertex3f(x, 0.02, y+1);
        glColor3f(0.7,0.7,0.7);
       glEnd;
       if Karte[x,y].Besezt then begin
        ObjectManager.RenderObject(x+0.5,y+0.5,Karte[x,y].Objekt);
       end;
     end;
end;


dieser code gibt zu allererst einen wunderschönen farbverlauf und dann meine normale karte wieder.
jedoch kann ich nicht jedes feld einzeln anklicken sondern funktioniert nur das anklicken eines ganzen "stranges" also immer des "X",

ich denke das problem liegt in der variable iv.

die auswertung hab ich bis jetzt so gelößt
Code:
procedure TForm1.FormClick(Sender: TObject);
var i : LongWord;
    x,y : Integer;
begin
 i := Select(MousePos.X, Mousepos.Y);
  for x := Low(Map.Karte) to High(Map.Karte) do
    for y := Low(Map.Karte[x]) to High(Map.Karte[x]) do
      if Map.Karte[x,y].ID = i then  begin
          Map.Karte[x,y].Objekt := Form2.NewObjectCombo.Text;
          Map.Karte[x,y].Besezt := true;
      end;
end;


ich hoffe ihr wisst was ich meine und könnt mir helfen

lg


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Aug 06, 2010 17:35 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Also ich bin mir als C++-User nicht ganz sicher was "iv: array[0..3] of byte absolute x;" macht, aber ich nehme an iv ist ein Array der einzelnen Bytes des 32bit Integers x, richtig? In dem Fall wird dann doch y gar nicht berücksichtigt und die Objekte in jeder Zeile haben alle die gleiche ID?

Ich schlage vor du packst x in iv[0] bzw. iv[1] und y in iv[2] bzw. iv[3]. Das klappt natürlich nur wenn x und y zwischen 0 und 65535 liegen. Ggf. brauchst du eine kompliziertere Zerlegung, aber jedenfalls solltest du die ID so wählen das du sie, wenn sie vom Color-Picking zurückkommt direkt wieder in x/y zerlegen kannst ohne alle Objekte durch zu testen. Wenn das nicht möglich ist solltest du überlegen ob du nicht eine Map verwenden kannst. Auch Delphi hat bestimmt eine Datenstruktur in der Standard-Bib die eine ID effizient auf einen Objekt-Pointer mappen kann.

Des weiteren frage ich mich warum du überhaupt Color-Picking machst. Du hast doch da ein 2D-Feld von Quads? Ich meine x und y sollten sich doch quasi direkt aus den Cursor-Koordinaten ableiten lassen ohne das du erst tonnenweise Daten durch die Grafikkarte jagen musst. Gut, ich weiß natürlich nicht was du da genau machst ;)

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Aug 06, 2010 17:46 
Offline
DGL Member

Registriert: Do Jan 07, 2010 21:58
Beiträge: 240
ich danke dir erstmal für deine atnwort,

das einfach umrechnen geht eben nicht da es zwar 2d quads sind, sie aber 3d irgendwo im raum liegen, desweiteren sollten am ende auch objecte die auf der map stehen selektiert werden können

die ID die jedes feld bekommt wird vorher Festgelegt wenn die größe des "Spielfeldes" Festgelegt wird

Code:
procedure TMap.SetMapSize(pSize : Integer);
var x,y,ID : Integer;
begin
  ID := 0;
  SetLength(Karte, pSize);
  for x := Low(Karte) to High(Karte) do
    SetLength(Karte[x], pSize);
  for x := Low(Karte) to High(Karte) do
    for y := low(Karte[x]) to High(Karte[x]) do begin
      ID := ID+1;
      Karte[x,y].ID := ID;
      Karte[x,y].Besezt := false;
      Karte[x,y].Objekt := '';
    end;
end;


so hat wirklich jedes feld seine eigene ID

und das mit dem "iv : array[0..3] of Byte abslolute x; kann ich dir leider gar nicht sagen, ich hab nämlich auch keine ahnung was das darstellen soll das wurde im Tutorial dazu nicht erklärt.
wobei ich das sowieso sehr knapp finde

und das mit de ID finden, da denke ich das ich eventuell einen Pointer auf Tfield setzen könnte und diesen dann aufrufe aber das muss ich mir nochmal ansehen


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Aug 06, 2010 18:09 
Offline
DGL Member

Registriert: Do Jan 07, 2010 21:58
Beiträge: 240
ich hab mal versuchtdas ganze grafisch darzustellen um es besser erklären zu können

Bild


das ist die struktur meiner map

wenn ich nun aber auf [2,4] klicke wird nur erkannt das ich auf x2 geklickt habe und es wird [2,0] selektiert da ja y nicht mit einbezogen wird


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Aug 07, 2010 10:53 
Offline
DGL Member

Registriert: Mo Aug 31, 2009 13:19
Beiträge: 151
Also....
var iv: Array[0..3] of Byte absolute x;
Heißt tatsächlich, dass iv[0], iv[1]... Zugriff auf das erste, zweite... Byte des Integers x bieten.

Zu deinem Problem: Wenn jedes Feld eine eindeutige, eindimensionale ID hat, warum nutzt du die nicht fürs Colorpicking und lässt die Koordinaten auf der Map völlig außer Acht?

Ne eindeutige Zuordnung sollte (wenn die Arraygrößen konstant sind, wenn sie nicht konstant sind müssen bei jeder Änderung neue ID's berechnet werden) wie folgt möglich sein:

Zuweisung der ID:
Code:
ID := (High(x) + 1) * y + x;


Aus den so vergebenen IDs lassen sich die Koordinaten im 2D-Array dann einfach wieder berechnen:

Code:
x := ID mod (High(x) + 1);
y := ID div (High(x) + 1);


Es gibt auch ne Möglichkeit, von für nicht-konstante Arraydimensionen von vornherein eindeutige IDs zu vergeben:

Code:
ID := Power(2, x) * Power(3, y);


Mit Power(2, x) = 2^x - ich verdreh da immer die Argumente, deswegen stell ich das nochmal klar. Bei der Möglichkeit wird das Zurückrechnen von der ID auf die Koordinaten aber schwierig.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Aug 07, 2010 13:39 
Offline
DGL Member

Registriert: Do Jan 07, 2010 21:58
Beiträge: 240
durch bisschen probieren was mir die funktion überhaupt zurückgibt habe ich erkannt das es mir ja direkt die positionsdaten des objects in meinem array zurückgibt.

und da is mir ein licht aufgegangen

passt auf die lösung ist folgende

als allererstes musste ich die renderprocedure abändern sodass ich eine art selektionsmodus habe.
desweiteren habe ich noch ein iy array[0..3] of byte absolute y; abgelegt um die y werte abzudecken

Code:
procedure TMap.Render(const SelektionsMode : Integer);
const
  fac: single = 1/255;
var x,y : Integer;
    iv: array[0..3] of byte absolute x;
    iy: array[0..3] of byte absolute y;
begin
 if Length(Karte) > 0 then
  for x := Low(Karte) to High(Karte) do
    for y := Low(Karte[x]) to High(Karte[x]) do begin
     TextureManager.BindTexture(Karte[x,y].Texture);
     case SelektionsMode of
     1 : begin
      {$ifdef ENDIAN_BIG}
        glUniform4f(ShaderManager.color, (iv[1])*fac, (iv[2])*fac, (iv[3])*fac, 1.0);
      {$else}
        glUniform4f(ShaderManager.color, (iv[0])*fac, (iv[1])*fac, (iv[2])*fac, 1.0);
      {$endif}
      end;
     2 : begin
      {$ifdef ENDIAN_BIG}
        glUniform4f(ShaderManager.color, (iy[1])*fac, (iy[2])*fac, (iy[3])*fac, 1.0);
      {$else}
        glUniform4f(ShaderManager.color, (iy[0])*fac, (iy[1])*fac, (iy[2])*fac, 1.0);
      {$endif}
      end;
     end;


das hatte auch zur folge das die eigentliche selektionsmethode abgeändert werden musste

Code:
function Select(x, y, Mode: integer): longword;
[...]
Form1.Render(Mode);
[...]


die onclick sieht nun so aus
Code:
procedure TForm1.FormClick(Sender: TObject);
var i,b : LongWord;
begin
 i := Select(MousePos.X, Mousepos.Y, 1);
 b := Select(MousePos.X, MousePos.Y, 2);
  Map.Karte[i,b].Objekt := Form2.NewObjectCombo.Text;
  Map.Karte[i,b].Besezt := true;
  //ShowMessage(inttostr(i)+','+inttostr(b));
end;


so bekomme ich genau das feld was ich haben möchte

ich danke euch für eure anregungen und vorschläge, das hat mir wirlich geholfen :)

da das ganze noch recht langsam ist werde ich es noch bisschen verfeinern müssen aber es funktioniert wrstmal einwandfrei

lg


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Aug 07, 2010 19:53 
Offline
DGL Member

Registriert: Mo Aug 31, 2009 13:19
Beiträge: 151
Die einzige Vereinfachung, die eigentlich fehlt ist - das ganze auf den eindimensionalen Fall zu reduzieren, damit du nur einmal rendern musst...aber nagut...es sei dir überlassen, darauf zu kommen ;)


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Foren-Übersicht » Programmierung » Einsteiger-Fragen


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.009s | 15 Queries | GZIP : On ]