2009-09-16 21 views
12

アンドロイド用のタイルベースのゲームを作りたいと思います。現時点では、各タイルを別々のビットマップとして描画しています。私は文字列から読み込み、レベルを描くためにどの文字が見つかったかによって異なるタイルを描画する大きなforループを持っています。Androidのゲームで画面にたくさんのビットマップを描画する方法

私は、ユーザーがスクロールジェスチャーを使って画面をスクロールすることができました。しかし、ゲームは遅すぎる。ユーザーがスクロールした後に画面を更新するのに時間がかかります。これは、各タイルのビットマップを個別に描画する必要があるためです。

レベルをより速く描く方法は何でしょうか?私はすべてのタイルを1つのビットマップにマージできると思っていました。しかし、私はこれを行う方法を知らない。何か案は?

package org.example.tutorial2d; 

import android.app.Activity; 
import android.os.Bundle; 
import android.view.GestureDetector; 
import android.view.MotionEvent; 
import android.view.GestureDetector.OnGestureListener; 

import org.example.tutorial2d.Panel; 

public class Tutorial2D extends Activity implements OnGestureListener { 

GestureDetector gestureScanner; 
Panel main; 

/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    gestureScanner = new GestureDetector(this); 

    //requestWindowFeature(Window.FEATURE_NO_TITLE);  
    main = new Panel(this); 
    setContentView(main);  

} 

@Override 
public boolean onTouchEvent(MotionEvent me) 
{ 
return gestureScanner.onTouchEvent(me); 
} 

@Override 
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) 
{ 
main.handleScroll(distanceX,distanceY); 
return true; 
} 

//////////////////// 
/////////////////// 
////////////////// 
@Override 
public boolean onDown(MotionEvent e) 
{ 
return true; 
} 

@Override 
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) 
{ 
return true; 
} 

@Override 
public void onLongPress(MotionEvent e){ } 

@Override 
public void onShowPress(MotionEvent e) { }  

@Override 
public boolean onSingleTapUp(MotionEvent e)  
{ 
return true; 
} 
//////////////////// 
/////////////////// 
////////////////// 
} 

そして、すべての作業を行うクラス:とにかくここ

は、あなたが問題を見ることができるように私のコードです

package org.example.tutorial2d; 

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.drawable.Drawable; 
import android.util.Log; 
import android.view.View; 
import org.example.tutorial2d.Point; 

public class Panel extends View { 

private int scrollX = 0; 
private int scrollY = 0; 

public Panel(Context context) 
{ 
    super(context); 
} 

@Override 
public void onDraw(Canvas canvas) 
{ 
    /*Bitmap scratch; 
    //Drawable scratch; 
    //scratch = getContext().getResources().getDrawable(
    //  R.drawable.icon); 
    canvas.drawColor(Color.BLACK); 
    //scratch.draw(canvas); 
    int origin = 0; 
    scratch = BitmapFactory.decodeResource(getResources(), R.drawable.horizontal5); 
    canvas.drawBitmap(scratch, origin, origin, null); 
    int width = scratch.getWidth(); 
    int height = scratch.getHeight(); 
    scratch = BitmapFactory.decodeResource(getResources(), R.drawable.room4entrynesw3x3); 
    canvas.drawBitmap(scratch, origin + width, origin - 32, null); 
    */ 

    String sucide_mission = 
"     wwwww\n" + 
"     wfffw\n" + 
"     wfffw\n" + 
"     wfffw\n" + 
"     wwfww\n" + 
"     wfw\n" + 
"     wfw\n" + 
"     wfw\n" + 
"    wwwwwwwfwwwwwfw\n" + 
"    wfffffffffffffw\n" + 
"    wfwwwwwfwwwwwfw\n" + 
"  wwwww wfw wfw wfw\n" + 
"wwwwwwfffwwwwwfwwwwwfwwwwwfw\n" + 
"fffffffffffffffffffffffffffw\n" + 
"wwwwwwfffwwwwwwwwwwwfwwwwwfw\n" + 
"  wwfww   wfw\n" + 
"  wfw   wfw\n" + 
"  wfw   wfw\n" + 
"  wfw   wfw\n" + 
"  wfw   wfw\n" + 
"  wwfww   wfw\n" + 
"  wfffwwfw  fff\n" + 
"  wffffffw  www\n" + 
"  wfffwwfw\n" + 
"  wwwww"; 

    canvas.drawColor(Color.BLACK); 
    int x = 0, y = 0; 

    for (int i = 0; i < sucide_mission.length(); i++) 
    { 
     Bitmap tileImage; 
     char tile = sucide_mission.charAt(i); 

     Log.d("Draw tiles", Character.toString(tile) + " " + x + "," + y); 

     switch (tile) 
     { 
      case 'w': 
       if (x < tileImage = BitmapFactory.decodeResource(getResources(), R.drawable.walla); 
       canvas.drawBitmap(tileImage, x - scrollX, y - scrollY, null); 
       x += 32; 
       break; 
      case 'f': 
       tileImage = BitmapFactory.decodeResource(getResources(), R.drawable.floore); 
       canvas.drawBitmap(tileImage, x - scrollX, y - scrollY, null); 
       x += 32; 
       break; 
      case ' ': 
       x += 32; 
       break; 
      case '\n': 
       y += 32; 
       x = 0; 
       break; 
     } 

    } 

    //canvas.drawBitmap(adapt, 0, 0, paint); 
    //canvas.drawBitmap(corner, origin -scrollX , origin -scrollY, paint); 

} 

public void handleScroll(float distX, float distY) 
{ 
     // X-Axis //////////////////////////////// 

     if(distX > 6.0) 
     { 
      if(scrollX < 460) 
      { 
       scrollX += 30; 
      } 
     } 
     else if(distX < -6.0) 
     { 
      if(scrollX >= 30) 
      { 
       scrollX -= 30; 
      } 
     } 
     //////////////////////////////////////////// 

     // Y-AXIS ////////////////////////////////// 
     if(distY > 6.0) 
     { 
      if(scrollY < 100) 
      { 
       scrollY += 30; 
      } 
     } 
     else if(distY < -6.0) 
     { 
      if(scrollY >= 30) 
      { 
       scrollY -= 30; 
      } 
     }    
     //////////////////////////////////////////// 

     if((scrollX <= 480) && (scrollY <= 120)) 
     { 
      //adapt = Bitmap.createBitmap(bmp, scrollX, scrollY, 320, 480); 
      invalidate(); 
     } 
} 
} 
+3

。 –

答えて

28

あなたがレンダリングされたすべてのタイルの各ビットマップイメージの新しいインスタンスを作成しているように見えます。たぶんそれを行う代わりに、各タイルタイプごとに1つのインスタンスを作成できますか?例:

private Bitmap wallTile = BitmapFactory.decodeResource(getResources(), R.drawable.walla); 
private Bitmap floorTile = BitmapFactory.decodeResource(getResources(), R.drawable.floore); 

次に、タイルが描画されるたびに同じタイルインスタンスを再利用します。これがうまくいかない場合は、コードのどの部分が最も長い時間を費やしているかを確認し、コードが実行される時間を最小限に抑えたり、スリム化を試みたりするために、何らかのパフォーマンス測定を行う必要があります。

免責事項:私はAndroidのプログラマーではありません

+0

私のプログラムを修正してくれてありがとう。 –

3

私が前にAndroidのためにプログラムされたことがありませんので、私「はカバーの下に何が起こっているの約100%よく分からないが、それを想定して:

BitmapFactory.decodeResource(getResources(), R.drawable.walla); 

このビットコードを読み込んでビットマップをメモリに読み込むと、描画するたびに各ビットマップをリロードしているように見えます。あなたは、それらを再利用し、一旦メモリにそれらをロードし、その後必要がありますすべてのリソースをうまく、レベルをロードするために行くとき、過去の小さなゲームを開発する場合、私がやった何

は、あります。

15

問題はかなり明らかです。あなたは地獄の多くのメモリを漏れているだけです。 LogCatを見て、私が何を意味するのか見てみましょう。 1.各フレームに文字列を割り当てないでください。それらは不変であるため、文字列を使用するたびにメモリリークが発生します。代わりに、変更する単純なchar []オブジェクトを使用します。 2.ビットマップオブジェクトの作成を何度もやめてください。私はDecodeBitmapメソッドは、内部的に各呼び出しのビットマップオブジェクトを割り当てると仮定します。それを毎フレーム行うのは悪いことです。経験則として

- >メモリリーク、それはGCをバディのは、描画するときに回避することは非常に高価な操作です。

0

別の考えは、非プログラマから、多分スクロールする、など。と可動アイテム(プレイヤー、NPC、アイテムが)背景の上に描画された第2の上層大きなタイルの背景を作成しています。したがって、スクロールは速く、全体的なレンダリングは少なくなります。 これは既にレンダリングされたタイルを参照するよりもリソース集約的かもしれないと思っています(上記の別の提案に記載されています)。しかしそうではないかもしれません。:-)

0

ユーザーがスクロールしたときに全体のビューを移動する方法について説明します。ウィンドウをスクロールすると、実際にウィンドウが反対方向に移動します。下にスクロールすると、ウィンドウが上に移動します。

ビュー(グリッド)内のすべての要素を収集し、全体のビューを移動することができます。 イメージを画面から(速く)レンダリングし、

利用可能な例があります。ホーム画面のすべてのコードを取得でき、左から右にスクロールすることがわかります。調べるべきものかもしれない。私は彼らがそのアプリを正しく作ったと確信しています。あなたは、ビューを使用している、SurfaceViewはあなたが望むものをほぼ確実である間:それはまだ誰かに重要念の

+0

ああ、側に。すべての画像を1つのビューにまとめると、1つの大きなビットマップと考えることができます。それは本質的にGUIが何であるかです。少なくとも画面レンダリングの観点から。 – baash05

2
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.util.AttributeSet; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

public class MapLoader extends SurfaceView implements SurfaceHolder.Callback, 
    Runnable { 

SurfaceHolder holder; 
Thread thread; 

Bitmap grass = BitmapFactory.decodeResource(getResources(), 
     R.drawable.tilemapdemo); 
boolean running = false; 

int[][] grassCoords = new int[][] { { 0, 16, 32, 48, 64 }, 
     { 0, 16, 32, 48, 64 }, { 0, 16, 32, 48, 64 }, 
     { 0, 16, 32, 48, 64 }, { 0, 16, 32, 48, 64 } }; 

public MapLoader(Context context, int width, int height) { 
    super(context); 

    holder = getHolder(); 
    holder.addCallback(this); 
} 

public MapLoader(Context context, AttributeSet attrs) { 
    super(context, attrs); 

    holder = getHolder(); 
    holder.addCallback(this); 
} 

public MapLoader(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 

    holder = getHolder(); 
    holder.addCallback(this); 
} 

public void pause() { 
    running = false; 

    while (running) { 
     try { 
      thread.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     break; 
    } 
    thread = null; 
} 

public void resume() { 
    running = true; 
    thread = new Thread(this); 
    thread.start(); 

} 

@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int width, 
     int height) { 

    running = true; 
    thread = new Thread(this); 
    thread.start(); 

} 

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    Canvas c = holder.lockCanvas(); 
    draw(c); 
    holder.unlockCanvasAndPost(c); 

} 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 

} 

@Override 
public void run() { 

    while (running == true) { 

     // performs drawing to the canvas 
     if (!holder.getSurface().isValid()) { 

      continue; 
     } 

     Canvas c = holder.lockCanvas(); 

     int x = 0; 
     int y = 0; 

     for (x = 0; x < grassCoords.length; x += grass.getWidth()) { 

      for (y = 0; y < grassCoords.length; y += grass.getHeight()) { 

       c.drawBitmap(grass, x, y, null); 
      } 

     } 

     holder.unlockCanvasAndPost(c); 

    } 

} 

}

関連する問題