0

Androidで六角形ボードを使用してボードゲームを開発していますが、ボードを動かすと、「マップ」全体または数十のエンティティが遅れ始めます。forループを使っているのが原因だと思いますが、直し方がわかりません。スレッド描画の方法を使用していますが、影響があるかどうかはわかりません。ボードを移動しているときに、携帯電話でラグがはっきりとわかります。

私のゲームクラス:

public class Game extends SurfaceView implements SurfaceHolder.Callback {
// Game Vars

int mapWidth = 150, mapHeight = 150;
public static double hexagonSideLength = 80;
public static double cellWidth = 2 * hexagonSideLength, cellHeight = Math
        .sqrt(3) * hexagonSideLength;
public static double downwardShift = (0.5) * (cellHeight);
public static double rightShift = hexagonSideLength / 2;
public static int boundaryWidth = 0, boundaryHeight = 0;
public static int error = (int) ((hexagonSideLength) * (0.06));
public static int buffer = 2;
public static int draws = 0;

// Touch Handle

// Offset to the upper left corner of the map
private int xOffset = 0;
private int yOffset = 0;

// last touch point
private int _xTouch = 0;
private int _yTouch = 0;

// scrolling active?
private boolean _isMoving = false;

public Cell[][] map;
private GameThread thread;
static String TAG = Game.class.getSimpleName();
Bitmap image[] = new Bitmap[100];
Paint paint;

public Game(Context context) {
    super(context);
    Log.i(TAG, "Loaded Game");
    // adding the callback (this) to the surface holder to intercept events
    getHolder().addCallback(this);
    // make the GamePanel focusable so it can handle events
    thread = new GameThread(getHolder(), this);
    map = new Cell[mapWidth][mapHeight]; // Create new Map
    boolean isShiftedDownwards = false;
    for (int i = 0; i < mapWidth; i++) {
        for (int j = 0; j < mapHeight; j++) {
            map[i][j] = new Cell(j, i, isShiftedDownwards);
        }
        if (isShiftedDownwards == true)
            isShiftedDownwards = false;
        else
            isShiftedDownwards = true;
    }

    if (mapWidth % 2 != 0) {
        boundaryWidth = (int) ((((mapWidth - 1) / 2) * hexagonSideLength)
                + ((mapWidth / 2) * cellWidth) + (2) * hexagonSideLength);
    } else {
        boundaryWidth = (int) (((((mapWidth - 1) / 2) * hexagonSideLength) + ((mapWidth / 2) * cellWidth)) + (1.5) * hexagonSideLength);
    }
    boundaryHeight = (int) (mapHeight * cellHeight + 0.5 * cellHeight);
    setFocusable(true);
    image[0] = Bitmap.createBitmap(BitmapFactory.decodeResource(
            this.getResources(), R.drawable.hexagonrgb));
    image[1] = Bitmap.createScaledBitmap(image[0], (int) cellWidth + error,
            (int) cellHeight + error, false);
    Log.i(TAG, "Got Resources");
    paint = new Paint();
    Log.i(TAG, "Prepared paint");

}

// called every Frame
@Override
protected void onDraw(Canvas canvas) {
    Log.i(TAG, "onDraw Called");
    // BG
    canvas.drawColor(Color.BLACK);

    // Resize

    // Redraw Map
    draws = 0;
    for (int column = updateArea(0); column < updateArea(1); column++) {
        for (int row = updateArea(2); row < updateArea(3); row++) {
            canvas.drawBitmap(image[1], map[column][row].x - xOffset,
                    map[column][row].y - yOffset, paint);
            paint.setColor(Color.WHITE);
            canvas.drawText(row + "," + column, map[column][row].x
                    - xOffset + 80, map[column][row].y - yOffset + 80,
                    paint);
            draws++;
        }
    }

    /** Log */
    paint.setColor(Color.WHITE);
    paint.setTextSize(20);
    canvas.drawText("xOffset: " + xOffset, 0, 30, paint);
    canvas.drawText("yOffset: " + yOffset, 0, 50, paint);
    canvas.drawText("activeTitlesX: " + updateArea(0) + " - "
            + updateArea(1), 0, 70, paint);
    canvas.drawText("activeTitlesY: " + updateArea(2) + " - "
            + updateArea(3), 0, 90, paint);
    canvas.drawText("DimX: " + MainActivity.DimX, 0, 110, paint);
    canvas.drawText("DimY: " + MainActivity.DimY, 0, 130, paint);
    canvas.drawText("Draws: " + draws, 0, 150, paint);

    Log.i(TAG, "Cleared canvas");
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}

// called by thread
public static void update() {
    Log.i(TAG, "Updated Game");

}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    // TODO Auto-generated method stub

}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    thread.setRunning(true);
    thread.start();
    Log.i(TAG, "Thread Started");

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    boolean retry = true;
    while (retry) {
        try {
            thread.join();
            retry = false;
        } catch (InterruptedException e) {
            // try again shutting down the thread
        }
    }
    Log.i(TAG, "Thread Destroyed");
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    // touch down
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        // start of a new event, reset the flag
        _isMoving = false;
        // store the current touch coordinates for scroll calculation
        _xTouch = (int) event.getX();
        _yTouch = (int) event.getY();
    } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
        // touch starts moving, set the flag
        _isMoving = true;

        // get the new offset
        xOffset += _xTouch - (int) event.getX();
        yOffset += _yTouch - (int) event.getY();

        // secure, that the offset is never out of view bounds
        if (xOffset < 0) {
            xOffset = 0;
        } else if (xOffset > boundaryWidth - getWidth()) {
            xOffset = boundaryWidth - getWidth();
        }
        if (yOffset < 0) {
            yOffset = 0;
        } else if (yOffset > boundaryHeight - getHeight()) {
            yOffset = boundaryHeight - getHeight();
        }

        // store the last position
        _xTouch = (int) event.getX();
        _yTouch = (int) event.getY();
    } else if (event.getAction() == MotionEvent.ACTION_UP) {
        /*
         * // touch released if (!_isMoving) { // calculate the touched cell
         * int column = (int) Math.ceil((_xOffset + event.getX()) /
         * _cellSize) - 1; int row = (int) Math.ceil((_yOffset +
         * event.getY()) / _cellSize) - 1; Cell cell =
         * _mapCells.get(row).get(column); // show the id of the touched
         * cell Toast.makeText(getContext(), "Cell id #" + cell._id,
         * Toast.LENGTH_SHORT).show(); }
         */
    }
    return true;
}

public int updateArea(int i) {
    switch (i) {
    case 0: // Left
        return Math.max(
                (int) (xOffset / (cellWidth - rightShift)) - buffer, 0);
    case 1: // Right
        return Math
                .min((int) (xOffset / (cellWidth - rightShift) + (int) (MainActivity.DimX / (cellWidth - rightShift)))
                        + buffer, mapWidth);
    case 2: // Up
        return Math.max((int) (yOffset / cellHeight) - buffer, 0);
    case 3: // Down
        return Math.min(((int) (yOffset / cellHeight))
                + (int) (MainActivity.DimY / cellHeight) + buffer,
                mapHeight);
    }
    return 0;
}

/* CELL CLASS */
class Cell {
    int x, y;
    boolean isShiftedDown;

    public Cell(int row, int col, boolean isShifted) {
        if (col % 2 != 0) {
            isShiftedDown = true;
            y = (int) (row * Game.cellHeight + Game.downwardShift);
            x = (int) (col * Game.cellWidth - col * Game.rightShift);
            Log.i("Shift", "Shifted" + Game.downwardShift);
        } else {
            isShiftedDown = false;
            y = (int) (row * Game.cellHeight);
            x = (int) (col * Game.cellWidth - col * Game.rightShift);
            Log.i("Shift", "Not Shifted");
        }
    }
}

}

前もって感謝します :)

4

1 に答える 1

1

基本的なアルゴリズム分析は、この操作を行っていることを示しています。

map[i][j] = new Cell(j, i, isShiftedDownwards);

22500回。本当に毎回新しいオブジェクトを作成する必要がありますか?それとも、既存のオブジェクトの変数を変更するだけでよいのでしょうか?


アップデート:

for (int column = updateArea(0); column < updateArea(1); column++) {
    for (int row = updateArea(2); row < updateArea(3); row++) {
        canvas.drawBitmap(image[1], map[column][row].x - xOffset,
                map[column][row].y - yOffset, paint);
        paint.setColor(Color.WHITE);
        canvas.drawText(row + "," + column, map[column][row].x
                - xOffset + 80, map[column][row].y - yOffset + 80,
                paint);
        draws++;
    }
}

これが問題の二重 for ループです。これは実行する回数だけ実行する必要があるという前提で実行します。ループ ステートメント内の関数呼び出しは、ループの前に変数に減らすことができますか (ループごとに評価されます)。これpaint.setColor(Color.WHITE);は、反復ごとに呼び出されるべきではありません。最初の描画の後に白に変更する必要がある場合は、起動時に 2 番目のペイント オブジェクトを作成し、ループに入る前に変更します。

これで問題が解決しない場合は、より小さな領域で反復できるかどうかを判断する必要があります。


更新 2 for ループを次のように書き換えます

int minCol = updateArea(0);
int maxCol = updateArea(1);
int minRow = updateArea(2);
int maxRow = updateArea(3);
for(int column = minCol; column < maxCol; column++)
    for (int row = minRow; column < maxRow; row++)
 ....

これにより、各反復での操作が大幅に削減されます。

于 2012-12-12T18:15:26.483 に答える