2Dゲーム用にJavaでタイルマップを作成する方法
質問
この問題への対処方法がわからない。
基本的に、ピクセルが欲しい-> 400x400ウィンドウのタイル表現。画面上の各座標、たとえば 120x300
はタイルの一部である必要があります。私の最小のスプライトは4ピクセルなので、1タイル= 4ピクセルと言えます。プレイヤーと敵のスプライトはすべて20 x 20であるため、各プレイヤー/悪者は5タイルを占有します。
次に、このMapクラスを使用して、次のことを行います。
-
タイルのインデックス/ IDを追加して、プレーヤー/モンスタースプライトのx / y座標を取得します。
-
境界の位置を知るため、スプライトは
400x400
を超えて移動しないため、非表示になります。 -
タイルが空いているかどうかを知る衝突検出。
これはどのように行うことができますか?ここで、x、y->タイルまたはタイルインデックス-> gt; 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)..
タイルは内部的に2D配列または単一の配列として表現できます。この場合、何らかの内部表現スキームを使用して配列をボードの正方形にマップします。したがって、mod算術です。
他のヒント
簡単な答え:乗算とモジュロ演算。
しかし、これがあなたを困らせるなら、ゲームを書く前に深刻な数学の復習をすることをお勧めします。
またあなたの声明
私の最小のスプライトは4ピクセルなので、 1タイル= 4ピクセルと言えます。の プレイヤーと敵のスプライトはすべて20 x 20、各プレーヤー/悪者が占有します 5タイル。
適切なジオメトリでは動作しません。 「1タイル= 4ピクセル」単位の場合つまり、タイルが2x2である場合、プレーヤーは5ではなく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;
}
おそらく、2つの引数(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;
}
}
開始する希望。すべてのコードは近くにコンパイラーなしで記述されているため、タイプミスやもちろんバグが含まれます。バグはクリエイティブコモンズライセンスの下で配布される可能性があります。
ピースをセットに保持するアプローチは、ピースが多くない場合にうまく機能するはずです。ほとんどのボード領域にピースが含まれていない限り、2Dアレイよりもうまく機能するはずです。現在、全体は、重複する部分がないことを前提としています。これらが必要な場合、getPieceOnTileはピースのコレクションを返す必要があります。順序が重要でない場合はセット、重要な場合はリスト。