Как создать плиточную карту на Java для 2D-игры?

StackOverflow https://stackoverflow.com/questions/622832

  •  05-07-2019
  •  | 
  •  

Вопрос

Не знаю, как подойти к этой проблеме.

По сути, мне нужно представление Pixel -> Tile для окна размером 400x400.Каждая координата на экране, например 120x300 должен быть частью плитки.Мой самый маленький спрайт — 4 пикселя, поэтому можно сказать, что 1 тайл = 4 пикселя.Спрайты игрока и врага имеют размер 20 x 20, поэтому каждый игрок/плохой парень будет занимать 5 плиток.

Затем я хочу использовать этот класс Map, чтобы:

  • Получите координаты x/y спрайта игрока/монстра, указав индекс/идентификатор плитки.

  • Знать, где находятся границы, чтобы спрайт не выходил за их пределы. 400x400, тем самым скрывая это.

  • Обнаружение столкновений, зная, свободна ли плитка или нет.

Как это может быть сделано?Здесь речь конкретно идет о преобразовании x,y->tile или tile index->x,y (для правильного рисования спрайтов).

Это было полезно?

Решение

Во-первых, разделите концепцию пикселя, который занимается только представлением, на тайл, который является реальным игровым объектом с ограничениями, которые он накладывает на игру.

Я считаю, что хороший способ разобраться в подобных вещах — начать с наброска примерного API того, что вы хотите.Что-то вроде:

public class Board {
  public Board (int width, int height){.. }
  public boolean isOccupied(int x, int y){.. }
  public void moveTo(Point from, Point to) { .. 
    (maybe throws an exception for outofbounds )

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

  public Point getPixelPosition(int xTilePos, int yTilePos, int pixelsPerTile)..

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

Другие советы

Короткий ответ:Операции умножения и модуля.

Но если вас это ставит в тупик, я бы посоветовал вам серьезно освежить знания по математике, прежде чем пытаться написать игру.

Также ваше заявление

Мой самый маленький спрайт - 4 пикселя, поэтому мы можем сказать, что 1 плитка = 4 пикселя.Игрок и вражеские спрайты - это 20 х 20, поэтому каждый игрок/плохой парень будет занимать 5 плиток.

не работает ни для какой разумной геометрии.Если под «1 плитка = 4 пикселя» вы подразумеваете, что плитки имеют размер 2х2, то игрок берет 100, а не пять.Если вы имеете в виду, что это 4x4, то игроки берут 25, что все равно не 5.

/** size of a tile in pixel (for one dimension)*/
int TILE_SIZE_IN_PIXEL = 4;
/** size of a piece in tiles (for one dimension)*/
int PIECE_SIZE_IN_TILE = 5;


public int tileToPixel(int positionInTiles){
    return TILE_SIZE_IN_PIXEL * positionInTiles;
}

/** returns the tile coordinate to which the given tile coordinate belongs 

Note: tileToPixel(pixelToTile(x)) only returns x if x is the upper or left edge of a tile
*/
public int pixelToTile(int positionInPixel){
    return positionInPixel / TILE_SIZE_IN_PIXEL;
}

Вероятно, вам также понадобятся методы, работающие с двумя аргументами (x и y at).

Для преобразования ID->кусок и наоборот у вас есть различные подходы.Какой из них выбрать, зависит от конкретных требований (скорость, размер игры...).Поэтому убедитесь, что вы скрываете детали реализации, чтобы вы могли изменить их позже.

Я бы начал с очень простого решения:

public class Piece{
    /** x position measured in tiles */
    private int x;
    /** y position measured in tiles */
    private int y;

    /** I don't think you need this, but you asked for it. I'd pass around Piece instances instead */
    private final  Long id;

    public void getX(){
        return x;
    }
    public void getY(){
        return y;
    }

    public void getID(){
        return id;
    }

}

public class Board(){
    private Set<Long,Piece> pieces = new HashMap<Piece>(pieces);

    public Piece getPieceOnTile(int tileX, int tileY){ 
        for(Piece piece:pieces){
             if (isPieceOnTile(piece, tileX, tileY)) return piece;
        }
    }

    private boolean isPieceOnTile(piece, tileX, tileY){
        if (piece.getX() < tileX) return false;
        if (piece.getX() > tileX + PIECE_SIZE_IN_TILE) return false;

        if (piece.getY() < tileY) return false;
        if (piece.getY() > tileY + PIECE_SIZE_IN_TILE) return false;

        return true;
    }
}

Надеюсь, это поможет вам начать.Весь код пишется без компилятора, поэтому он будет содержать опечатки и, конечно же, ошибки, которые могут распространяться по лицензии Creative Commons.

Подход к хранению частей в наборе должен работать хорошо, если их не так много.Он должен работать лучше, чем 2D-массив, если большая часть доски не содержит фигур.В настоящее время все это предполагает отсутствие перекрывающихся частей.Если они вам нужны, getPieceOnTile должен вернуть коллекцию частей.Набор, если порядок не имеет значения, и список, если имеет значение.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top