我一直在 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");
}
}
}
}
提前致谢:)
基本算法分析显示您正在执行此操作:
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像这样重写你的 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++)
....
这将显著减少每次迭代中的操作。