2016-08-03 2 views
0

У меня есть приложение libgdx, которое содержит класс Button. Конструктор Button принимает три аргумента: имя файла графики, положения и игры (последний используется для обратных вызовов разного рода).Смещение между обнаружением кликов и графикой кнопок в libgdx

Кнопка масштабируется на основе предоставленной графики, тем самым устанавливая ее ширину и высоту в зависимости от свойств графики.

Основной класс, Game, при обнаружении щелчка сравнивает координаты щелчка с координатами кнопки в сочетании с ее шириной и высотой.

Теперь основная проблема заключается в том, что между кнопкой и координатами клика имеется немного горизонтального смещения, поэтому эффект заключается в том, что графика отображает несколько пикселей справа от области, на которую можно щелкнуть. Я не могу, чтобы жизнь меня определяла источник этого несоответствия, поэтому я бы очень признателен за свежие глаза, чтобы увидеть, где я ошибаюсь.

Кнопка, конструктор и метод опроса для интерактивной области.

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(); 
} 

Соответствующий фрагмент из InputHandler. Он прослушивает ввод и передает событие. Обратите внимание, что вертикальное положение нажмите вычитаются из вертикального размера экрана, как по вертикали 0 противоположена по InputHandler:

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

ClickTracker (ссылаются как tracker в приведенном выше фрагмент коды), класс, который делает то фактическое сравнение между щелчками и 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); 
     } 
    } 

Вкратце: вертикальное выравнивание работает как задумано, но горизонтальная немного смещен. Графические кнопки могут отображаться примерно на 10-20 пикселей справа от области, на которую можно щелкнуть.

Я с удовольствием размещу дополнительную информацию или код, если необходимо, но я считаю, что у меня есть соответствующие части.


Edit:

По просьбе Maciej Дзюбан, вот пропущено, который рисует элементы пользовательского интерфейса. batch является SpriteBatch, как это предусмотрено libgdx:

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

getImgPos() представляет собой способ интерфейс, реализованный всеми рисуемых элементов:

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

Стоит отметить, что половина горизонтального размера изображения вычитается из X pos, поскольку X pos относится к нижнему центру.

+0

Как нарисовать свою кнопку? В 'getClickArea()' похоже, что 'pos' представляет центр объекта, в то время как это обычно левый нижний угол. –

+0

@MaciejDziuban добавлен согласно вашему запросу. – Jarmund

+0

'new Texture()' не должно появляться нигде в вашем цикле рендеринга. Вы пропускаете несколько текстур на каждом кадре, за исключением ненужной загрузки многих копий одной и той же текстуры. – Tenfour04

ответ

1

Вы непоследовательность в своих преобразованиях позиции:

  • Ваш clickArea «ы углу pos переводится [-width/2, height/2] вектора. угол
  • Ваш drawArea «ы это pos переводится [-width/2, 0] вектор

Они явно должны быть такими же, поэтому, если вы хотите, чтобы ваши pos представляют снизу центр вашей сущности (как вы явно указано иное) вы необходимо изменить свой метод getClickArea(), чтобы он соответствовал getImgPos().

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

Side Примечание: в качестве заметил Tenfour04, вы создаете новую текстуру каждый кадр, и это огромная утечка памяти. Вы должны сделать это поле, инициализированное в конструкторе или даже статической переменной, если некоторые кнопки обмениваются текстурой. Не забудьте позвонить по dispose() по ресурсам. Для более эффективного управления активами проверьте this article (обратите внимание, что это может быть излишним в небольших проектах).

+0

Добавление 'height/2' было обходным путем для того, чтобы кликабельная область смещалась вертикально без нее. Я не нашел причину, почему, но она работает по назначению с помощью обходного пути. Проблема заключается в горизонтальном присвоении. +1 для указателей оптимизации в отношении обработки ресурсов, поскольку это следующий в моем списке дел. – Jarmund

+1

Вы взглянули на свою настройку камеры/просмотра? Я использовал такие проблемы, когда забыл переопределить метод 'resize()' в 'ApplicationListener'. –

+0

Вы приняли мой ответ. Это действительно проблема с камерой? –

Смежные вопросы