Как построить плиточную карту на Java для 2D-игры? - PullRequest
3 голосов
/ 08 марта 2009

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

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

Тогда я хочу использовать этот класс Map для:

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

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

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

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

Ответы [ 3 ]

4 голосов
/ 08 марта 2009

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

Я нашел хороший способ распутать такие вещи, как начать набрасывать приблизительный 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)..

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

1 голос
/ 08 марта 2009
/** 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-> piece и наоборот доступны различные подходы. Какой из них выбрать, зависит от точных требований (скорость, размер игры ...). Поэтому убедитесь, что вы скрываете детали реализации, чтобы вы могли изменить их позже.

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

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.

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

1 голос
/ 08 марта 2009

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

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

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

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

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

...