2016-08-03 66 views
0

Ich habe eine libgdx-Anwendung, die eine Klasse Button enthält. Der Konstruktor von Button hat drei Argumente: Dateiname von Grafiken, Position und Spiel (letzteres wird für Callbacks verschiedener Art verwendet).Offset zwischen Klickerkennung und Schaltflächengrafik in libgdx

Die Schaltfläche skaliert sich basierend auf den bereitgestellten Grafiken und legt ihre Breite und Höhe basierend auf den Eigenschaften der Grafiken fest.

Wenn ein Klick erkannt wird, vergleicht die Hauptklasse Game die Koordinaten des Klicks mit den Koordinaten der Schaltfläche kombiniert mit deren Breite und Höhe.

Nun besteht das Hauptproblem darin, dass zwischen der Schaltfläche und den Klickkoordinaten ein kleiner horizontaler Versatz besteht, so dass die Grafiken einige Pixel rechts vom anklickbaren Bereich angezeigt werden. Ich kann nicht für das Leben von mir herausfinden, woher diese Diskrepanz kommt, und deshalb würde ich sehr dankbar sein, dass ich ein paar frische Augen habe, um zu sehen, wo ich hier falsch liege.

Schaltfläche, Konstruktor und Abfragemethode für anklickbaren Bereich.

public Rectangle getClickArea() { 
    return new Rectangle(pos.x - (img.getWidth()/2), pos.y + (img.getHeight()/2), w, h); 
} 

public Button(String assetfile, int x, int y, Game game) { 
    this.game = game; 
    img = new Pixmap(new FileHandle(assetfile)); 
    pos = new Vector2(x, y); 
    this.w = img.getWidth(); 
    this.h = img.getHeight(); 
} 

Ein relevanter Ausschnitt aus InputHandler. Es wartet auf Eingaben und leitet das Ereignis weiter. Bitte beachten Sie, dass die vertikale Klickposition von der vertikalen Größe des Bildschirms subtrahiert wird, als vertikale 0 in InputHandler Gegenteil:

public boolean touchDown(int screenX, int screenY, int pointer, int button) { 
    tracker.click(screenX, Settings.windowSize_Y - screenY); 
    return false; 
} 

ClickTracker (wie tracker in dem obigen Schnipsel verwies), die Klasse, die tut ist-Vergleich zwischen Klicks und Clickables:

public void click(int x, int y) { 
    Vector2 clickPos = new Vector2(x, y); 
    for (Tickable c : world.getPaintables()) 
    { 
     if (!(c instanceof Unit)) 
      continue; 

     if (((Clickable)c).getClickArea().contains(clickPos)) { 
      System.out.println("Clicked on unit"); 
     } 


    } 
    for (Clickable c : clickables) 
    { 
     if (c.getClickArea().contains(clickPos)) { 
      c.clicked(x, y); 
     } 
    } 

kurz gesagt: die vertikale Ausrichtung funktioniert wie vorgesehen, aber die horizontal ist geringfügig ab. Die Schaltflächengrafiken erscheinen etwa 10 bis 20 Pixel rechts vom anklickbaren Bereich.

Ich werde gerne weitere Informationen oder Code bei Bedarf posten, aber ich glaube, ich habe die relevanten Teile abgedeckt.


Edit:

Als Maciej Dziuban angefordert, hier ist die snipped, die die UI-Elemente zieht. batch ist ein SpriteBatch wie Libgdx bereitgestellt:

for (Paintable p : ui) { 
     batch.draw(new Texture(p.getImg()), p.getImgPos().x, p.getImgPos().y); 
    } 

die getImgPos() ist eine Interface-Methode von allen ziehbar Elemente implementiert:

public Vector2 getImgPos() { 
    return new Vector2(pos.x - (getImg().getWidth()/2), pos.y); 
} 

Es ist erwähnenswert, dass die Hälfte der horizontalen Bildgröße der Feststellung, von der X subtrahiert pos, da sich X pos auf die untere Mitte bezieht.

+0

Wie zeichnen Sie Ihren Knopf? In 'getClickArea()' sieht es so aus, dass 'pos' das Zentrum der Entity darstellt, während es sich normalerweise um die linke untere Ecke handelt. –

+0

@MaciejDziuban hinzugefügt nach Ihrer Anfrage. – Jarmund

+0

'new Texture()' sollte nirgendwo in Ihrer Render-Schleife erscheinen. Sie leugnen mehrere Texturen in jedem Frame, abgesehen davon, unnötig viele Kopien der exakt gleichen Textur zu laden. – Tenfour04

Antwort

1

Sie haben Inkonsistenz in Ihrer Position Transformationen:

  • Ihre clickArea ‚s Ecke pos von [-width/2, height/2] Vektor übersetzt. Sie
  • Ihre drawArea ‚s Ecke pos von [-width/2, 0] Vektor

Sie übersetzt eindeutig gleich sein sollte, also, wenn Sie möchten, dass Ihre pos unten in der Mitte Ihres Unternehmens darstellen (wie Sie explizit angegeben haben) Ändern Sie Ihre getClickArea() Methode zu, so dass es getImgPos() entspricht.

public Rectangle getClickArea() { 
     return new Rectangle(pos.x - (img.getWidth()/2), pos.y, w, h); 
    } 

Randbemerkung: als Tenfour04 bemerkt haben, erstellen Sie neue Textur jeden Frame und das ist riesige Speicherleck. Sie sollten es zu einem Feld machen, das in Konstruktor oder sogar einer statischen Variable initialisiert wird, wenn einige Schaltflächen die Textur teilen. Vergessen Sie nicht, dispose() auf Ressourcen aufzurufen. Für ein leistungsfähigeres Asset-Management finden Sie unter this article (beachten Sie, dass es in kleinen Projekten ein Overkill sein kann).

+0

Das Hinzufügen von 'height/2' war ein Workaround für die Tatsache, dass der anklickbare Bereich ohne ihn vertikal falsch ausgerichtet wird. Ich habe den Grund nicht gefunden, aber es funktioniert wie vorgesehen mit der Problemumgehung. Das Problem ist die horizontale Ausrichtung. +1 für Optimierungszeiger in Bezug auf die Ressourcenbehandlung, wie das nächste auf meiner Todo-Liste. – Jarmund

+1

Haben Sie sich die Kamera/Viewport-Einrichtung angesehen? Ich habe diese Art von Problemen bekommen, als ich vergaß, 'resize()' Methode in 'ApplicationListener' zu überschreiben. –

+0

Sie haben meine Antwort akzeptiert. War es in der Tat ein Kamera-Problem? –