2

作成しようとしているアプリはボード ゲームです。ボードとして 1 つのビットマップと、ボード上のさまざまな場所に移動するピースがあります。ボードの一般的なデザインは正方形で、特定の数の列と行があり、外観の境界線があります。チェス盤やスクラブル ボードを思い浮かべてください。

ビットマップを使用する前に、最初にボードとボーダーを手動で描画して作成しました - drawLine & drawRect。「onSizeChanged」で渡された画面の幅と高さに基づいて、境界線の幅を何ピクセルにするかを決定しました。残りの画面を、必要な列または行の数で割りました。

例として、画面のサイズが 102 x 102 であるとします。

境界線を 1 に設定し、行と列の数を 10 に設定することを選択した可能性があります。これにより、100 x 100 が残ります (上下の境界線と左右の境界線を考慮して 2 だけ削減されます)。次に、列と行を 10 に設定すると、高さと幅の両方に 10 ピクセルが残ります。

どのような画面サイズが渡されても、ボーダーの幅のピクセル数と、ボード上の各正方形の高さと幅を正確に保存します。単純な式に基づいて画面上のどの位置にピースを移動するかを正確に把握しており、ユーザーがどのセルに触れて移動したかを正確に把握しています。

では、ビットマップではどのように機能するのでしょうか? つまり、密度ごとに1回、3つの異なる背景ビットマップを作成すると、各デバイスの画面解像度に合わせてサイズが変更されません.もっと。私または Android が現在のデバイスの画面サイズに合わせてビットマップを拡大または縮小する場合、ピースをどこに移動するか、またはプレーヤーの場所を計算するために、境界線の幅と各正方形の寸法をどのように知ることができますか触れた。これまで見てきた例は、ビットマップ全体をスケーリングし、ビットマップ全体の幅と高さを取得する方法を示しているだけです。しかし、スケーリング後にボードの各部分の幅または高さが何ピクセルになるかを知る方法がわかりません。

ビットマップでこれについて読むことができるサンプル コードまたは URL を誰かが持っている場合は、感謝します。

ところで、画面サイズに関係なく、ゲームボードの寸法 (境界線と正方形) を知る方法に関するサンプルコード (非常に単純化されたコード) を次に示します。ここで必要なのは、任意の画面サイズにスケーリングされるビットマップとしてボードを使用してこれを行う方法を知ることだけです。


 @Override
   protected void onSizeChanged(int w, int h, int oldw, int oldh) {
      intScreenWidth = w;
      intScreenHeight = h;

      // Set Border width - my real code changes this value based on the dimensions of w
      // and h that are passed in. In other words bigger screens get a slightly larger
      // border.
      intOuterBorder = 1;

      /** Reserve part of the board for the boardgame and part for player controls & score
          My real code forces this to be square, but this is good enough to get the point
          across.
      **/
      floatBoardHeight = intScreenHeight / 4 * 3;

      // My real code actually causes floatCellWidth and floatCellHeight to
      // be equal (Square).
      floatCellWidth = (intScreenWidth - intOuterBorder * 2 ) / intNumColumns;
      floatCellHeight = (floatBoardHeight - intOuterBorder * 2) / intNumRows;

      super.onSizeChanged(w, h, oldw, oldh);
   }


私は答えを見つけたと思います。1 つのスケーリングされたビットマップ内でプレイ可能な各正方形の正確な幅/高さと位置を見つけることができない場合がありますが、SDK の Snake の例を見ると、ボード全体とスケールに対して 1 つのビットマップが作成されていないことがわかります画面の寸法に基づいています - 代わりに、タイルごとにビットマップを作成し、画面の解像度と画面に必要なタイルの数に基づいてタイルをスケーリングします - ボードを手動で描画するときと同じように。この方法を使用すると、ボード上のすべてのプレイ可能な正方形の正確なピクセル境界を見つけることができるはずです。ボードを正方形ごとに複数のビットマップに分割するだけです。おそらく境界線についても同様のアプローチを行う必要があるため、スケーリング後に幅/高さも検出できます。

確認のためにテストしますが、Snake SDK の例で見たものに基づいて動作することを期待しています。

- マイク


私が求めていたことを実行する方法をテストしましたが、うまくいくようです。これが私がしたことです:

ボード用に 320 x 320 のビットマップを作成しました。境界線と正方形 (チェス盤のようなもの) で構成されていました。ボーダーは、ボード全体で 10 ピクセルの幅でした。正方形は 20 x 20 ピクセルでした。

onSizeChanged で画面の幅と高さを検出しました。480 x 800 ディスプレイでは、ボードの新しい幅を 480 x 480 に設定し、次のコードを使用して全体をスケーリングします。


protected void onSizeChanged(int w, int h, int oldw, int oldh) {        
    floatBoardWidth = w;
    floatBoardHeight = floatBoardWidth;

    bitmapScaledBoard = Bitmap.createScaledBitmap(bitmapBoard, (int)floatBoardWidth, (int)floatBoardHeight, true);      

        super.onSizeChanged(w, h, oldw, oldh);
}

境界線の幅が何ピクセルにスケーリングされ、正方形がスケーリングされた高さと幅のピクセル数を検出するために、最初に全体の画像がどれだけスケーリングされたかを計算しました。ビットマップを作成したときから、ビットマップが 320 x 320 であることはわかっていました。次の式を使用して、画像がどれだけスケーリングされたかを計算しました。

floatBoardScale = floatScreenWidth / 320;

幅 480 の画面の場合、floatBoardScale は 1.5 です。次に、完全なビットマップ内の境界線が何にスケーリングされたかを計算するために、次のことを行いました。

floatBorderWidth = 10 * floatBoardScale;

10 は、320 x 320 ビットマップの元の境界線の幅でした。最終的なコードでは、値をハードコーディングせず、変数を使用します。とにかく、この式の場合、新しく計算された境界線の幅は次のようになります: 15

ボードの四角形 (元のビットマップでは 20 x 20) に同じ倍率を掛けると、30 x 30 という新しい値が得られました。数式でこれらの値を使用して、人が触れた四角形を計算すると、うまくいきました。四角の隅々や中央に触れたところ、常に正しい位置が計算されました。これは重要なことです。画面の解像度に関係なく、ユーザーがピースを移動したい場所を把握しており、視覚的に適切な場所に表示されます。

同じ疑問を持った方の参考になれば幸いです。また、誰かが同じことを達成するためのより良い方法を持っている場合は、投稿してください。

4

1 に答える 1

2

いくつかのこと。まず、複数の画面をサポートする方法について読み始めます。 ディップとその仕組みについて学ぶことに細心の注意を払ってください。

次に、このビデオを見てください (少なくとも最初の 15 ~ 20 分)。

このテーマは簡単に理解できるものではありません。コード内で遊んでみることをお勧めします。surfaceview を作成し、いくつかのビットマップ、さまざまなエミュレーター (画面サイズと密度)、およびさまざまな種類の描画可能なフォルダーをいじり始めることをお勧めします。

残念ながら、このトピックには Google が認めたいと思っている以上のことがあり、実行可能であることは間違いありませんが、一部の種類のアプリケーションでは簡単に始めることはできません。

最後に、抽象的な回答 (このようなもの) を探していない場合は、質問をより単純化することを検討する必要があります。

幸運を!

于 2010-11-11T02:51:33.557 に答える