0

私はいくつかの星図を手で丸めたアプリに取り組んでいます。したがって、抽象的な話をする必要はありません。問題のアプリは次のとおりです: https://play.google.com/store/apps/details?id=com.tw.fireballs

ストアのリストを見ると、水平線のすぐ上にある画像を使用していることがわかります。これは主に、非常にきれいに見えるためです。低解像度のデバイスでは問題ではありません。関連するピクセル数が少ないため、レンダリングで大きな問題が発生することはないようです。私の HTC One や妻の Nexus 5 のような高解像度のデバイスでは、画面に表示されるとフレームレートが大幅に低下します。発売を差し控えるほどではありませんが、できれば改善していただきたいです。

私は現在、SurfaceView を使用しているだけで、mSurfaceHolder.lockCanvas(null) によって取得されたキャンバスに描画しているため、ハードウェア アクセラレーションではありません。通常のビューとして実装しようとしましたが、全体的に実際には遅くなったので、OpenGL の世界に飛び込む前に、これを高速化するためにできることがあるかどうかを調べたいと思います。

基本的に、水平線を通る薄い (不透明な) 画像の「スライス」から始め、画面の対角線のサイズまで拡大し、デバイスの向きに合わせて回転させます。

描画コードは次のとおりです。

private void loadResources() {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inPreferredConfig = Bitmap.Config.RGB_565;
    mHorizonImage = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.star_map_background, options);
}

@Override
public void updateDimensions(int width, int height) {
    super.updateDimensions(width, height);

    int horizonHeight = mCanvasHeight / 3;
    int horizonWidth = (int) Math.sqrt(Math.pow(mCanvasHeight, 2) + Math.pow(mCanvasWidth, 2));

    mHorizonImage = Bitmap.createScaledBitmap(mHorizonImage, horizonWidth, horizonHeight, false);
}

@Override
public void drawOn(Canvas canvas) {
    double upScreen = -mProjection.distanceFromScreen * Math.tan(Math.toRadians(mOrientation.elevation));
    double rightWithTiltCheat = upScreen * Math.sin(Math.toRadians(mOrientation.tilt));
    double upWithTiltCheat = upScreen * Math.cos(Math.toRadians(mOrientation.tilt));

    float x = (float) (mCanvasWidth / 2 * (1 + rightWithTiltCheat / mProjection.screenWidthInCm));
    float y = (float) (mCanvasHeight / 2 * (1 - upWithTiltCheat / mProjection.screenHeightInCm));

    canvas.save();
    canvas.translate(x, y);
    canvas.rotate((float) mOrientation.tilt);
    canvas.drawBitmap(mHorizonImage, -mHorizonImage.getWidth() / 2, -mHorizonImage.getHeight(), null);
    canvas.restore();
}

画面解像度の影響を受けない、より効率的な方法はありますか? いくつかアイデアを出し合いましたが、私よりもこのことをよく知っている誰かからの連絡をお待ちしています。質問がある場合は、お尋ねください。

乾杯、 ネイサン

4

1 に答える 1

2

@pskink は頭に釘を打ちました。Matrix パラメータを使用してビットマップを描画することは、私が経験していたスケーリングされたビットマップとキャンバスの回転よりもはるかに効率的です。私の HTC One のような 1080P デバイスでは、電話を斜めに持つと、フレームレートが 50+ から ~10 に低下するのを見ていました。これで5割落ちたらラッキーです。

変更されたコードは次のようになります。

@Override
public void updateDimensions(int width, int height) {
    super.updateDimensions(width, height);

    mHorizonHeight = mCanvasHeight / 3;
    mHeightScale = (float)mHorizonHeight / (float)mHorizonImage.getHeight();

    mHorizonWidth = (int) Math.sqrt(Math.pow(mCanvasHeight, 2) + Math.pow(mCanvasWidth, 2));
    mWidthScale = (float)mHorizonWidth / (float)mHorizonImage.getWidth();
}

@Override
public void drawOn(Canvas canvas) {
    double upScreen = -mProjection.distanceFromScreen * Math.tan(Math.toRadians(mOrientation.elevation));
    double rightWithTiltCheat = upScreen * Math.sin(Math.toRadians(mOrientation.tilt));
    double upWithTiltCheat = upScreen * Math.cos(Math.toRadians(mOrientation.tilt));

    float x = (float) (mCanvasWidth / 2 * (1 + rightWithTiltCheat / mProjection.screenWidthInCm));
    float y = (float) (mCanvasHeight / 2 * (1 - upWithTiltCheat / mProjection.screenHeightInCm));

    mDrawMatrix.reset();
    mDrawMatrix.postScale(mWidthScale, mHeightScale);
    mDrawMatrix.postTranslate(x - mHorizonWidth / 2, y - mHorizonHeight);
    mDrawMatrix.postRotate((float) mOrientation.tilt, x, y);
    canvas.drawBitmap(mHorizonImage, mDrawMatrix, null);
    canvas.save();
}
于 2013-11-20T00:17:48.867 に答える