none
Bitmap Positionierung anhand von Koordinaten RRS feed

  • Frage

  • Hallo Leute,

    ich habe derzeitig ein Problem damit in meinem Radar die Karte von einem Spiel dem Spieler richtig anzuordnen, so dass die Karte in richtiger Position zu dem Spieler ist.

    Ich habe mal ein paar Bilder davon gemacht um es besser zu Veranschaulichen:

    Dies hier ist die "Minimap" von dem Spiel wo alles richtig ist, in der Mitte der Pfeil ist der Spieler und dieser blickt gerade in die Richtung Nord-Östlich.

    Hier ist das Bild von meinem Radar, leider sieht man hier auf dem ersten blick, dass die Positionierung von dem Spieler (Blau) nicht mit der von der Minimap vom Spiel übereinstimmt.

    Hier erstmal meine derzeitigen Code versuche um das gerade zu biegen:

    private static Bitmap DrawMinimapOverlay(Bitmap img, Bitmap RadBit) { Graphics G = Graphics.FromImage(RadBit); int cellBindpointX = (int)((((Math.Abs(ObjectMgr.LocalPlayer.X) % TILE_SCALE_FACTOR) / TILE_SCALE_FACTOR) * ZoomFactor) * 1); int cellBindpointY = (int)((((Math.Abs(ObjectMgr.LocalPlayer.Y) % TILE_SCALE_FACTOR) / TILE_SCALE_FACTOR) * ZoomFactor) * 1); if (ObjectMgr.LocalPlayer.X <= 0 && ObjectMgr.LocalPlayer.Y <= 0) {//2 G.DrawImage(img, ((int)((RadarWidth) / 2) - cellBindpointX) - 1 * ZoomFactor, ((int)((RadarHeight) / 2) - cellBindpointY) - 1 * ZoomFactor); } else if (ObjectMgr.LocalPlayer.X >= 0 && ObjectMgr.LocalPlayer.Y <= 0) { G.DrawImage(img, ((int)((RadarWidth) / 2) + (cellBindpointX - ZoomFactor)) - 1 * ZoomFactor, ((int)((RadarHeight) / 2) - cellBindpointY) - 1 * ZoomFactor); } else if (ObjectMgr.LocalPlayer.X <= 0 && ObjectMgr.LocalPlayer.Y >= 0) { G.DrawImage(img, ((int)((RadarWidth) / 2) - cellBindpointX) - 1 * ZoomFactor, ((int)((RadarHeight) / 2) + (cellBindpointY - ZoomFactor)) - 1 * ZoomFactor); } else if (ObjectMgr.LocalPlayer.X >= 0 && ObjectMgr.LocalPlayer.Y >= 0)//2 { G.DrawImage(img, ((int)((RadarWidth) / 2) + (cellBindpointX - ZoomFactor)) - 1 * ZoomFactor, ((int)((RadarHeight) / 2) + (cellBindpointY - ZoomFactor)) - 1 * ZoomFactor); } return img; }

    Also: wenn die Funktion aufgerufen wird, benutzt er zu 90% immer die else if Schleife die mit //2 Makiert ist, in dieser Schleife habe ich den Code von //1 Benutzt um die obrigen Bilder zu machen, da dies von den 4 if Schleifen die ist, die am nächsten an das gewünschte Ergebniss kommt.

    Falls noch irgendwas unklar sein sollte, bitte hier Schreiben, werde die benötigten Daten dann nachliefern.


    Donnerstag, 15. November 2012 12:30

Antworten

  • Hallo Palin,

    ich habe nun gewiss 2-3 Stunden da dranne gesessen und habe die Fehler nun alle behoben bekommen, das erste Problem mit der Minimap wurde gelöst in dem ich bei der Y Position -20 gemacht habe, somit habe ich mir das Positionieren des Spielers usw. erspart und alles passt.

    Dann ist mir ein Problem mit der Positionierung der Spieler aufgefallen, dieses habe ich behoben mit der Zoom Größe, die auf 2 stand und halt mit den Coordinaten Multipiziert wurde und dann falsche Positionen zeichnete.

    Samstag, 17. November 2012 20:48

Alle Antworten

  • Hallo Günther,

    wissen sollte man noch, wie Dein Koordinaten-System aufgebaut ist.
    Befindet sich der 0-Punkt oben / links (oder eine der anderen Ecken) oder aber in der Mitte?

    Gruß Elmar

    Donnerstag, 15. November 2012 13:22
    Beantworter
  • Hallo Günter,

    ich gehe jetzt mal davon aus das die Bildmitte der Ursprung des Koordinaten-Systems ist.

    Wenn der Spiele die x,y-Koordinaten = 0, hat sollte er in der Bildmitte erscheinen.

    Du verschiebst ihn dann aber nochmal um deinen Zoomfaktor.

    Mir ist auch nicht klar wie so der Wert sich in den einzelnen Achsen-Abschnitte ändert.

    Ich denke folgender Code sollte es tun, wenn die Bildmitte der Koordinaten Ursprung ist.

      private static Bitmap DrawMinimapOverlay(Bitmap img, Bitmap RadBit)
            {
    
                Graphics G = Graphics.FromImage(RadBit);
    
               
                int cellBindpointX = (int)((((Math.Abs(ObjectMgr.LocalPlayer.X) % TILE_SCALE_FACTOR) / TILE_SCALE_FACTOR) * ZoomFactor) * 1);
                int cellBindpointY = (int)((((Math.Abs(ObjectMgr.LocalPlayer.Y) % TILE_SCALE_FACTOR) / TILE_SCALE_FACTOR) * ZoomFactor) * 1);
    
                Point BildMitte = new Point ((int)((RadarWidth) / 2, (int)((RadarHeight) / 2)
    
                G.DrawImage(img, (BildMitte .X + cellBindpointX , (BildMitte .Y + cellBindpointY );
              
                return img;
            }

    Ich hab es jetzt aber nicht getestet.

    MFG

    Björn

    Donnerstag, 15. November 2012 14:21
  • Hi Günter,

    ein Punkt noch bei der Berechnung des cellBindPoint, ich weiß jetzt nicht genau was der TILE_SCALE_FACTOR ist.

    Aber ich denke, der cellBindPoint sollte eher so Berechnet werden.

     int cellBindpointX = (int)((((ObjectMgr.LocalPlayer.X) * TILE_SCALE_FACTOR) * ZoomFactor) );

    Ist jetzt auch nicht getestet.

    MFG

    Björn

    Donnerstag, 15. November 2012 15:03
  • Hallo Björn,
    danke für deine Antwort, aber leider bringt auch sie nicht das gewünschte Ergebnis.

    Hier mal die Bilder davon:

    Spiel Minimap:


    Radar:

    Hier mal noch ein paar Daten:

            static int RadarHeight = 300;
            static int RadarWidth = 300;
            const int TILE_HEIGHT = 256;
            const float TILE_SCALE_FACTOR = 533.5F;

    Also, das cellbindx+y ist definitiv richtig, weil dieses wird auch Benutzt um die Richtigen Karten zu finden, und allein daran weiß ich, dass es auf jedenfall Funktionstüchtig ist.

    Was ich vergessen habe zu Erwähnen heute Mittag ist, dass ich hier 4 kleine Bilder Lade die dann die Karte im Hintergrund Bilden, daher kommt es nun dazu das jetzt mit dem Code von dir nur ein Bild Angezeigt wird, nur was mich etwas verwirrt ist, dass der Code der normal die 4 Bilder lädt normal in einer anderen Funktion ist und mit dieser Positionierungsfunktion wenig am Hut hat.

    Aber das dieses Puzzle mal Vollständig wird, Poste ich diesen hier auch noch zur Sicherheit.

            public static Bitmap GetNearbyMinimap()
            {
                Bitmap Minimap = new Bitmap(TILE_HEIGHT * 3, TILE_HEIGHT * 3);
                Graphics G = Graphics.FromImage(Minimap);
                float mapSize = 34133.333f; // 34133.333
                float tileSize = 150.0f / 36.0f * 8 * 16; // 533.333
    
                float absCoordX = (mapSize / 2) - ObjectMgr.LocalPlayer.X + tileSize;
                float absCoordY = (mapSize / 2) - ObjectMgr.LocalPlayer.Y + tileSize;
    
                int b = (int)(absCoordX / tileSize) - 1;
                int a = (int)(absCoordY / tileSize) - 1;
    
                if (OldMinimap.Equals(new MinimapData(a, b, ZoomFactorx)))
                {
                    return (Bitmap)OldMinimap.img.Clone();
                }
    
                OldMinimap.a = a;
                OldMinimap.b = b;
                OldMinimap.zoom = ZoomFactor;
    
               // Minimap = AddTile(Minimap, a, b, (int)0, (int)0, TILE_HEIGHT);
    
                var count = 0;
                for (int aa = a - 1; aa <= a + 1; aa++)
                {
                    for (int bb = b - 1; bb <= b + 1; bb++)
                    {
                        Minimap = AddTile(Minimap, aa, bb, TILE_HEIGHT + (TILE_HEIGHT * (aa - a)), TILE_HEIGHT + (TILE_HEIGHT * (bb - b)), TILE_HEIGHT);
                        count++;
                    }
                }
    
                Bitmap FinalMM = new Bitmap((int)(ZoomFactor * 3), (int)(ZoomFactor * 3));
                Graphics G2 = Graphics.FromImage(FinalMM);
    
                G2.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
                G2.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
                G2.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
                G2.DrawImage(Minimap, 0, 0, ZoomFactor * 3, ZoomFactor * 3);
                OldMinimap.img = (Bitmap)FinalMM.Clone();
    
                return FinalMM;
            }

    Die Code womit ich letzt endlich die Minimap auf das Radar zeichne:

    DrawMinimapOverlay(GetNearbyMinimap(), Minimap);
    Hoffe wir kommen nun ein Stückchen weiter ;)

    Donnerstag, 15. November 2012 20:56
  • Hi Günter,

    ich war jetzt davon ausgegangen, dass du den Spieler (Variable img) in die Karte Zeichnen willst (RadBit). Wie es jetzt aus sieht hast du eine größere Karte in img die du passend unter das Radar schieben willst.

    Das sieht ganz oben eigentlich recht gut aus.

    Da ist dann eher das Problem, dass der Blaue Punkt nicht in der Mitte ist.

    Das setzen wird wohl in einer Anderen Methode geschehen.

    Wenn es das nicht sein sollte, beantworte bitte die gestellten Fragen und bedenke das man nicht  weiß was du Programmierst und was hinter deinen Variablen steckt.

    MFG

    Björn

     

    Freitag, 16. November 2012 00:03
  • Hallo Björn,

    Die Variablen die hierzu notwendig sind habe ich im 2. Post von mir mit rein gepackt, sollte dort irgendwas fehlen, dann bitte bescheid geben.

    In der Tat wird die Karte nicht Richtig dem Blauen Punkt positioniert, das ist auch der Grund warum ich diesen Thread eröffnet habe, weil ich dort im Moment nicht weiter komme.

    Soweit ich weiß wird diese Positionierung in der Funktion

    DrawMinimapOverlay

    vorgenommen, somit habe ich diese auch im ersten Post mit bei gepackt, da dies der knackpunkt sein wird um das Problem zu beheben.

    Gruß Günther


    Edit: oben/links ist der 0 Punkt von der 300x300 Picturebox.
    Freitag, 16. November 2012 00:46
  • Hi Günter,

    du hast immer noch nicht beantwortet welches Koordinaten-System du verwendest.

    Und wenn du mir angibst, dass TILE_SCALE_FACTOR = 533.5F ist, kenne ich zwar den Wert, aber weiß immer noch nicht welche Bedeutung  hinter der Variabel Steckt.

    Was den Blauen Punkt angeht, für mich sieht es so aus das in der Funktion die Karte und nicht der Punkt gesetzt wird. Ich weiß aber wirklich nicht was in der Variabel img übergeben wird.

    Das solltest du Wissen, wenn nicht, Speicher das Bild einfach mal auf die Festplatte und schau was dir dort übergeben wird.

    MFG

    Björn

    Freitag, 16. November 2012 09:08
  • Hallo Björn,

    Die Variable TILE_SCALE_FACTOR = 533.5F ist im grunde das selbe wie

    float tileSize = 150.0f / 36.0f * 8 * 16; // 533.333

    Wie man hier entnehmen kann bestimmt dieser Wert, die größe von einer Kachel der Minimap, wo von ich 4 Stück lade um sie auf dem Radar zu Zeichnen.

    Du hast genau richtig gedacht damit das diese Funktion die Karten Position bestimmt und nicht den Blauen Punkt, ist auch alles so gewollt. (Hier in diesem Thema geht es auch darum, dass die Karte nicht richtig unter den Blauen Punkt gesetzt wird)

    Zu der Variable img:

    private static Bitmap DrawMinimapOverlay(Bitmap img, Bitmap RadBit)

    img ist in diesem Falle die Minimap, welche ein Bitmap ist, worauf die 4 Kacheln gezeichnet werden, und da img gezeichnet werden soll ist am Ende der Funktion return img;.

    Gruß Günther

    Freitag, 16. November 2012 14:15
  • Hi Günter,

    danke für die Infos jetzt sehe ich ein Wenig klarer.

    Wenn du dir den Blauen Punkt anschaust siehst du das er nicht mittig im Bild ist sondern nach oben verschoben ist.

    Diese Verschiebung musst du auch auf das Bild anwenden.

    (Oder den Punkt mittig Zeichnen ;) )

    MFG

    Björn

    Freitag, 16. November 2012 14:51
  • Also denkst du, sobald ich den Punkt richtig gezeichnet habe in der Mitte, dass dann der Code im ersten Post Funktioniert und die Minimap richtig positioniert?
    Freitag, 16. November 2012 15:36
  • Könnte Klappen.

    Ich hab mal das Bild mit Gimp geöffnet und mir Hilfslinien die Mitte markiert.

    Sah ganz gut  aus.

    Freitag, 16. November 2012 16:10
  • Naja wird bestimmt nicht so einfach sein, die Positionierung zu ändern da ja viel von dem Blauen Punkt aus geht wie z.B. andere Spieler oder Gegenstände.

    Werde da mal so ab 20Uhr bei schauen, wenn ich Schwierigkeiten bekomme, werde ich mich nochmal melden, auch wenns geklappt hat, um das Endergebnis zu präsentieren ;)

    Freitag, 16. November 2012 17:03
  • Die Position des Spielers sollst du auch nicht ändern.

    Nur das Zeichnern der Position auf der Radar Karte.

    Das Bild was du hier Erzeugst, wird Wahrscheinlich in einem der nächsten Schritte, an einer andere Methode übergeben die dann den Spieler(Blauer Punkt) einzeichnet. 

    Freitag, 16. November 2012 17:51
  • So nach einer Stunde ist der Übeltäter gefunden welches die Karte falsch eingezeichnet hat, es war TILE_SCALE_FACTOR was ich nun zu diesem geändert habe: const float TILE_SCALE_FACTOR = 150.0f / 36.0f * 8 * 16;

    nun sieht die Positionierung so aus:

    Wie dort zu sehen ist, stimmt die Positionierung nun überein, jedoch gibts halt immer noch ein Problem und zwar wenn ich mich von dor aus nach Norden drehe und ein paar Meter mich hoch bewege verschiebt sich die Minimap (Die Bildgrafik unter den Spielern) nicht korrekt, ich denke das sie sich genau um 90° in die falsche Richtung bewegt.

    Hier ein Bild davon:

    Ich bin mir derzeitg nicht sicher wie ich dies beheben kann, aber ich denke diese Minimap bewegung nur aus der Funktionist DrawMinimapOverlay() ist.

    Wäre für ein paar Ideen dankbar :)

    Freitag, 16. November 2012 20:23
  • X und Y Vertauscht?
    Freitag, 16. November 2012 20:35
  • Danke Björn, das war die Lösung ;)

    Hier mal ein Bild von der Lösung:

    Also da ich ja ein Perfektionist bin, hast du noch eine Idee wie ich es noch ein wenig genauer machen kann?

    Oder liegt dieses Problem nun an dem Zoomfactor, der evtl. zu hoch eingestellt ist?

    Gruß Günther

    Freitag, 16. November 2012 22:15
  • Hi Günter,

    wenn ich das richtig sehe ist es immer noch das gleiche Problem wie oben.

    Entweder Karte nach oben schieben oder den Punkt mittig setzen.

    MFG

    Björn

    Samstag, 17. November 2012 10:58
  • Hallo Palin,

    ich habe nun gewiss 2-3 Stunden da dranne gesessen und habe die Fehler nun alle behoben bekommen, das erste Problem mit der Minimap wurde gelöst in dem ich bei der Y Position -20 gemacht habe, somit habe ich mir das Positionieren des Spielers usw. erspart und alles passt.

    Dann ist mir ein Problem mit der Positionierung der Spieler aufgefallen, dieses habe ich behoben mit der Zoom Größe, die auf 2 stand und halt mit den Coordinaten Multipiziert wurde und dann falsche Positionen zeichnete.

    Samstag, 17. November 2012 20:48