Изменение цвета плитки при наведении курсора мыши - предотвращение выбора нескольких плиток одновременно

1

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

Теперь в следующем gif, вы можете увидеть, буду ли я нависнуть на самом краю плитки, он выберет сразу две плитки или даже 4 сразу, если вы держите мышью в середине 4-х плиток:

gif http://gyazo.com/4d9f4a07b19d01642f92d3818f36b5fa.gif

Это не должно происходить в игре, как я могу это предотвратить?

Это код обновления:

/**
 * 
 * @param x mouse X
 * @param y mouse Y 
 */
public void checkHover(int x, int y) {
    for (int i = 0; i < tiles[0].length; i++) {
        for (int j = 0; j < tiles[1].length; j++) {

            // get coordinates from tile
            int x1 = i * (sprite.getWidth() - 1);
            int y1 = j * (sprite.getHeight() - 1);  

            // If we have screen translate, we can cancel it for 
            // this situation
            int realX = x - this.translate.getX();
            int realY = y - this.translate.getY();

            // checking if mouse inside tile
            if (realX >= x1 && realX <= x1 + sprite.getWidth() &&
                    realY >= y1 && realY <= y1 + sprite.getHeight()) {
                // set tile to hovered sprite
                this.tiles[i][j].setHover(true);
            }
            else {
                // cancel hovered sprite
                this.tiles[i][j].setHover(false);
            }
        }
    }
}

Как я могу это предотвратить?

  • 0
    Разрыв цикла - это одно из решений (поэтому, когда вы получаете положительный удар, вы можете выйти из цикла), но при этом можно сохранить активные ранее выделенные ячейки. Вместо этого вы можете уменьшить количество проверок, используя «<x1 + sprite.getWidth ()». Другое решение состоит в том, чтобы просто вычислить плитку непосредственно в позиции мыши, сохраняя ссылку на плитку как выбранную плитку, но это изменит способ ее рисования. Вы также можете воспользоваться API-интерфейсом 2D-графики для расчета положительных результатов.
Теги:
graphics

3 ответа

1
Лучший ответ

Вместо двух циклов я бы вычислил индекс массива 2d, основанный на позиции x и y мыши, разделив положение x и y на сколько места от одной плитки до следующей (которая выглядит как ширина плитки плюс 1, пустая рамка). Это приведет к тому, что границы будут поддерживать определенную сторону, но похоже, что вы не хотите выбирать две плитки в любом случае.

Когда у вас есть индекс плитки, lastHighlightedTile подсветку и сохраните ссылку на нее с переменной экземпляра, как lastHighlightedTile, но прежде чем вы это сделаете, также вызовите lastHighlightedTile.setHover(false); ,

Если индекс плитки недействителен, как если бы мышь вышла из области плитки, не обращайтесь к массиву и все еще вызывайте lastHighlightedTile.setHover(false); ,

Это должно исправить выделение нескольких фрагментов, а также позволит отключить предыдущую подсветку (решение выхода из текущего цикла может не отключить предыдущую подсветку).

0

EDIT: другое решение: просто объявите логическое начало в начале метода и установите только в том случае, если этот логический объект все еще является ложным. После того, как вы установили плитку, также установите для boolean значение true, что предотвратит установку других.

public void checkHover(int x, int y) {
   boolean hasTurnedOneOn = false;
   for (int i = 0; i < tiles[0].length; i++) {
    for (int j = 0; j < tiles[1].length; j++) {

        // get coordinates from tile
        int x1 = i * (sprite.getWidth() - 1);
        int y1 = j * (sprite.getHeight() - 1);  

        // If we have screen translate, we can cancel it for 
        // this situation
        int realX = x - this.translate.getX();
        int realY = y - this.translate.getY();

        // checking if mouse inside tile
        if (realX >= x1 && realX <= x1 + sprite.getWidth() &&
                realY >= y1 && realY <= y1 + sprite.getHeight() && !hasTurnedOneOn) {
            // set tile to hovered sprite
            this.tiles[i][j].setHover(true);
            hasTurnedOneOn = true;
        }
        else {
            // cancel hovered sprite
            this.tiles[i][j].setHover(false);
        }
    }
}
}
  • 0
    Серьезно, не используйте ярлыки. Там должно быть 101 лучший способ достичь того же результата: P
  • 0
    Ранний выход из цикла может не отключить предыдущий основной момент, если у Бена Бери не будет больше логики для этого.
Показать ещё 4 комментария
0

Предполагая, что ширина спрайта равна 50, я вижу, что первый заголовок имеет координату x1-x2 (0-50), второе название имеет (49-100), третье имеет (99-150)... То же самое для y-измерения.

Поэтому, когда указатель находится в точке (x) = (50), он отображает (x1 - x2) (0-50) и (49 -1 00) заголовки.

Почему вы вычитаете 1 из ширины/высоты sprite? попробуйте с этим:

        // get coordinates from tile
        int x1 = i * (sprite.getWidth());
        int y1 = j * (sprite.getHeight());  

Редактировать: я написал пример приложения, которое запустило мое решение:

public class App {

Tile[][] tiles;
Sprite sprite;

public static void main(String[] args) {
    App app = new App();
    app.init();
    app.checkHover(50, 50);
    app.printHovers();
}

private void init() {
    sprite = new Sprite();
    tiles = new Tile[10][10];
    for (int i = 0; i < tiles[0].length; i++) {
        for (int j = 0; j < tiles[1].length; j++) {
            tiles[i][j] = new Tile();
        }
    }
}

public void checkHover(int x, int y) {
    for (int i = 0; i < tiles[0].length; i++) {
        for (int j = 0; j < tiles[i].length; j++) {

            // get coordinates from tile
            int x1 = i * (sprite.getWidth());
            int y1 = j * (sprite.getHeight());

            // If we have screen translate, we can cancel it for
            // this situation
            // int realX = x - this.translate.getX();
            // int realY = y - this.translate.getY();
            int realX = x;
            int realY = y;

            // checking if mouse inside tile
            if (realX >= x1 && realX < x1 + sprite.getWidth()
                    && realY >= y1 && realY < y1 + sprite.getHeight()) {
                // set tile to hovered sprite
                this.tiles[i][j].setHover(true);
            } else {
                // cancel hovered sprite
                this.tiles[i][j].setHover(false);
            }
        }
    }
}

public void printHovers() {
    for (int i = 0; i < tiles[0].length; i++) {
        for (int j = 0; j < tiles[i].length; j++) {
            System.out.print((tiles[i][j].isHover() ? "Y" : "O") + " ");
        }
        System.out.println();
    }
}

public class Sprite {

    public int getWidth() {
        return 50;
    }

    public int getHeight() {
        return 50;
    }
}

public class Tile {

    private boolean hover;

    public boolean isHover() {
        return hover;
    }

    public void setHover(boolean hover) {
        this.hover = hover;
    }
}
}

Он отлично работает для (49, 49), (49, 50), (50, 49) и (50, 50) коордов. Итак, сначала вы должны удалить вычеты -1 и изменить <= test на <.

  • 0
    Моей единственной заботой было бы убедиться, что никакие другие названия еще не выбраны, но у нас точно нет большого кода, чтобы продолжить ...
  • 0
    @MGordon Потому что мне нужно сдвинуть их на 1 пиксель, чтобы сделать красивые четкие границы.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню