9

簡単にするために、Android用の単純なPongクローンゲームを作成していると仮定します。ランドスケープモードでのみ再生可能であると仮定しましょう。(今のところ四角い電話は無視してください)。

QVGA電話でゲームのスクリーンショットを撮り、スクリーンショットのサイズをWVGAサイズに変更した場合、ゲームとほぼ同じように見える程度に、ゲームを各電話で同じスケールで表示したいと思います。 WVGA電話を見てください。つまり、パドルの幅は常に画面幅の1/32である必要があり、ボールの直径は常に画面幅の1/16である必要があります。

アプリケーションをペイントする適切な方法は何でしょうか?に描画される標準のSurfaceViewで実行されますCanvas

パドル、ボール、およびゲームフォント(スコアボード、メインメニュー)用の高解像度PNGがあるとします。

物理的な解像度を確認し、Canvasビアscale(float sx, float sy)を拡大縮小してすべてのキャンバス(QVGAおよびWVGA上)の仮想解像度を同じにし、各画面サイズの各位置にまったく同じプリミティブを描画しますか?

または、Canvasで密度に依存しないピクセル(ディップ)を使用できますか?

4

3 に答える 3

4

キャンバスの描画機能を1回だけプレイしてから、すべてをopenglに切り替えましたが、ロジックは同じままです(私は思います)。

最初の問題では、ある電話から別の電話への比率を一定に保ちたいと思うでしょう。私のアプリでは、両側に「ブラックバンド」効果を追加します。onSurfaceChangedでは、比率を計算する必要があります。この比率を使用すると、図面のアスペクトを一定に保つために、各側で削除する必要のあるスペースの量を決定できます。これにより、すべての描画に適用するデルタXまたはYが得られます。次のコードは、oglバージョンから適応したものであるため、少し調整する必要がある場合があります。

@Override
   public void onSurfaceChanged(int w, int h){
   float ratioPhysicScreen = nativeScreenResoltionW/nativeScreenResoltionH;
   float ratioWanted = GameView.getWidth()/GameView.getHeight();
   if(ratioWanted>ratioPhysicScreen){
      newHeight = (int) (w*GameView.getHeight()/GameView.getWidth());
      newWidth = w;
      deltaY = (int) ((h-newHeight)/2);
     deltaX = 0;
   }else{
      newWidth = (int) (h/GameView.getHeight()*GameView.getWidth());
      newHeight = h;
      deltaX = (int) ((w-newWidth)/2);
      deltaY = 0;       
}

次に、実際のサイズよりもキャンバス上のサイズと、image.getWidth()(画像の実際のサイズ)との違いを知ることで、キャンバス上に画像を描画できるようにする必要があります。 image.getScaledWidth(canvas)は、要素のサイズをdpで示します。これは、要素が画面に表示される大きさを意味します)が重要です。下の例を見てください。

public class MainMenuView extends PixelRainView{
private Bitmap bmpPlay = null;
private float playLeft = 0;
private float playRight = 0;
private float playBottom = 0;
private float playTop = 0;

public MainMenuView(Context context, AttributeSet attrs) {
    super(context,attrs);
}



@Override
public void unLoadBitmaps() {
    super.unLoadBitmaps();
    if(bmpPlay != null){
        bmpPlay.recycle();
        bmpPlay = null;
    }
}



@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if(bmpPlay == null){
        bmpPlay = getBitmapFromRessourceID(R.drawable.play_bt);
        playLeft = (this.getWidth()-bmpPlay.getScaledWidth(canvas))/2; 
        playRight = playLeft + bmpPlay.getScaledWidth(canvas);
        playTop = (this.getHeight()-bmpPlay.getScaledHeight(canvas))/2;
        playBottom = playTop+bmpPlay.getScaledHeight(canvas);
    }
    canvas.drawBitmap(bmpPlay,playLeft, playTop, null);

    }       
}


@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
}



@Override
public boolean onTouchEvent(MotionEvent event) {
    if(event.getAction() == MotionEvent.ACTION_DOWN){
        float x = event.getX();
        float y = event.getY();
        //test central button
        if(x>playLeft && x<playRight && y<playBottom && y>playTop){
            Log.e("jason", "touched play");
            PixelRainView.changeView(R.layout.composedlayoutgroup);
        }
    return super.onTouchEvent(event);
}
}

これにより、すべての比率の問題のクロスプレートフォームが解決されるはずです。これにより、一定のアスペクトを維持する必要性が単純化されるため、openglをお勧めしますが、オプションではないと思います^^

これがあなたに十分役立つことを願っています

于 2010-11-19T03:09:39.600 に答える
2

PNGを使用する代わりに、ディップを使用してパドルをペイントします

于 2010-11-15T10:22:29.733 に答える
-1

利用できる標準解像度は3つ(ldip、mdip、hdip)しかないので、それぞれにリソースフォルダーが必要だと思います。

http://developer.android.com/guide/practices/screens_support.html

PNGを手動でスケーリングして、使用可能な3つの解像度のそれぞれに合わせる場合、電話は特定のリソースフォルダを透過的にロードする必要があります

于 2010-11-15T10:40:35.033 に答える