как определить касание мышкой объекта(отрисованного в swing окне), находящегося в массиве
Я новичок в java, недавно начал писать свою игру(на подобие worldbox).
У меня есть двумерный массив типа int, это поле игры, которое я отрисовываю с помощью Graphics g. Если в массиве под нужной клеткой 1, то это земля (зеленная клетка), 2 - то вода(синяя клетка) и так далее.
Столкнулся с такой проблемой, по задумке игрок должен влиять на виртуальный мир с помощью мышки. Внизу есть кнопки, если нажата одна, то выбран инструмент земля, вторая - вода и так далее. То есть мне нужно определять, касается ли мышка объектов массива, и если да, то какого?
Если кто то знает как это осуществить, то пожалуйста опишите подробно как это сделать.
Ответы (1 шт):
У нас есть мир, разбитый на клеточки разного типа (Земля, Вода). Значит заведем класс World и наследуем его от чего-нибудь на чем можно рисовать и размещать кнопки.
Приведу пример класса отрисовки игрового поля. Также на нем расположены 2 кнопки (не показаны). Код максимально упрощен и для наглядности, и потому что стал подзабывать Java :)
public class World extends JFrame {
// Класс для хранения номера ячейки сетки
class MeshCell {
int row;
int col;
}
// Данный enum нужен для определения типа квадратиков/тайлов
public enum TileType {
LAND,
WATER;
};
// Эти два поля будут хранить разметы мира
private final int worldWidth;
private final int worldHeight;
// Это ассоциативный массив для хранения связи тип тайла - картинка
// В приложении не используется. Добавил для наглядности
private Map<TileType, BufferedImage> tiles = new HashMap<>();
// Сетка для хранения типа тайла в ячейке
private TileType[][] mesh = null;
// Размер клеточки тайла
private int tileSize = 10;
// Конструктор
// row - количество тайлов мира по-вертикали
// column - по-горизонтали
// tileSize - размер стороны тайла/клеточки мира
public World(int row, int column, int tileSize) {
super();
initComponents();
// Создаем сетку значений тайлов
this.mesh = new TileType[row][column];
this.tileSize = tileSize;
// Вычисляем физический размер игрового поля
this.worldHeight = tileSize*row;
this.worldWidth = tileSize*column;
// "Заливаем" все поле водой
for(int i = 0; i < row; i++) {
for(int j = 0; j < column; j++) {
mesh[i][j] = TileType.WATER;
}
}
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(), getHeight());
int posX = 0, posY = 0;
for(int row = 0; row < mesh.length; row++) {
posX = 0;
for(int col = 0; col < mesh[row].length; col++) {
// Здесь я просто закрашиваю нужный квадратик сплошным цветом,
// если нужно рисовать картинку, то надо вызвать getTileImage
// и отрисовывать изображение
g.setColor(mesh[row][col] == TileType.WATER? Color.BLUE: Color.GREEN);
g.fillRect(posX, posY, tileSize, tileSize);
g.setColor(Color.BLACK);
g.drawRect(posX, posY, tileSize, tileSize);
posX += tileSize;
}
posY += tileSize;
}
}
// Задаем изображение соответствующее типу тайла
public void setTileImage(TileType type, BufferedImage tile) {
tiles.put(type, tile);
}
// Метод определения номер ячейки в сетке mesh
// Возвращает cell, чей col - это номер столбца в сетке
// row - это номер строки в сетке
public MeshCell getCellBy(Point point) {
MeshCell cell = new MeshCell();
if( point.x > this.worldWidth )
cell.col = -1;
else
cell.col = point.x / tileSize;
if( point.y > this.worldHeight )
cell.row = -1;
else
cell.row = point.y / tileSize;
return cell;
}
public BufferedImage getTileImage(TileType type) {
return tiles.getOrDefault(type, null);
}
// Функция обработки клика по поверхности игрового мира
private void formMouseClicked(java.awt.event.MouseEvent evt) {
// Какую ячейку выбрали
Point p = getCellBy(evt.getPoint());
// Если клик находится за границей игрового мира, то ничего не делаем и выходим их функции
if( p.x == -1 || p.y == -1 )
return;
// Какой тип поверхности выбран. По-умолчанию вода
TileType type = TileType.WATER;
if( this.jToggleButtonLAND.isSelected() )
type = TileType.LAND;
// Устанавливаем новое значение в ячейку игровой сетки
mesh[p.y][p.x] = type;
// Перерисовываем поле
repaint();
}
Результат: ( Опять же кнопки книзу не отрисовались, потому что почему-то стираются. Почему, не знаю, а разбираться лень :) ):
