绘制基于图块的地图

此脚本绘制控件,英雄,曲面和地图:

public void render(Canvas canvas) { canvas.drawColor(Color.TRANSPARENT); Drawable myImage; int tileWidth = 50; int tileHeight = 50; int rowBaseX = 0; int rowBaseY = 0; int[][] board = new int[][] { {0,0,0,0,0,0,2,0,0,0,}, {0,0,0,0,0,2,2,0,0,0,}, {0,0,0,0,0,2,0,0,0,0,}, {0,0,0,0,0,2,0,0,0,0,}, {0,0,0,2,2,2,0,0,0,0,}, {0,0,0,2,0,0,0,0,0,0,}, {0,0,0,2,0,0,0,0,0,0,}, {0,0,2,2,0,0,0,0,0,0,}, {0,0,2,0,0,0,0,0,0,0,}, {0,0,2,0,0,0,0,0,0,0,} }; int mapWidth = 10; int mapHeight = 10; for (int row = 0; row < mapHeight; row++) { for (int col = 0; col < mapWidth; col++) { Resources res = this.getContext().getResources(); switch(board[row][col]) { case 0: myImage = res.getDrawable(R.drawable.tile1); break; case 1: myImage = res.getDrawable(R.drawable.tile2); break; default: myImage = res.getDrawable(R.drawable.tile3); break; } int curL = rowBaseX + (col * tileWidth); int curU = rowBaseY + (row * tileHeight); int curR = curL + tileWidth; int curD = curU + tileHeight; myImage.setBounds(curL,curU,curR,curD); myImage.draw(canvas); } } droid.draw(canvas); butt.draw(canvas); butt1.draw(canvas); butt2.draw(canvas); butt3.draw(canvas); buttz.draw(canvas); buttz1.draw(canvas); buttz2.draw(canvas); buttz3.draw(canvas); buttx.draw(canvas); } 

有一个英雄,当玩家用控件移动他时必须重新绘制,所有其他drawable也必须重新绘制。 问题是绘制地图是一个漫长的过程,因此我创建的地图越大,英雄移动速度越慢,因为地图的每个地块都必须绘制。 有没有办法在其他方法中将所有切片放到一个位图,并在canvas方法中绘制一个位图?

最佳选择是仅绘制在屏幕上可见的地图部分。 这样,无论整个地图变得多大,该地图的绘制总是不变的。 由于你在网格系统上,你可以很容易地找出英雄所在的单元格:

 heroGridX = hero.x % mapWidth; heroGridY = hero.y % mapHeight; 

从那里,您可以使用canvas的宽度和高度以及网格单元宽度和高度的恒定大小来计算要绘制的玩家周围的单元格数:

 leftGrid = heroGridX - (canvas.getWidth() / tileWidth) / 2; topGrid = heroGridY - (canvas.getHeight() / tileHeight) / 2; rightGrid = heroGridX + (canvas.getWidth() / tileWidth) / 2; bottomGrid = heroGridY + (canvas.getHeight() / tileHeight) / 2; 

您可以使用数据结构来存储这些独立于英雄的值,并且只有在玩家靠近边缘时才移动它们以滚动地图。 通过这种方式,英雄在不滚动地图的情况下上下移动,直到它们获得到平铺边缘的X或Y像素。 而不是在渲染例程中计算这些。

这将使用比将整个地图绘制成一个大位图少得多的内存。 绘制成大型位图可以减少CPU时间,从而节省更多内存。 随着地图变大,绘制该地图所需的内存也随之增大。 此算法仅保持绘制地图不变,因为屏幕大小在运行时不会更改。 并且,与其他选项相比,随着地图变大,内存使用量不会增大(与在canvas中绘制更多切片相比,它的增长非常小)。 关于这一点的一个重要事实是,如果你确实获得了更大的屏幕(比如平板电脑和手机)。 此算法也会正确放大,以便玩家可以看到更多地图的周围地形。

如果无法在应用程序外创建静态地图,则可以将静态内容的绘制与动态内容分开。

创建一个Bitmap ,用它创建一个Canvas并在该Canvas上绘制地图。 你只需要这样做一次。 在另一个Canvas上每帧渲染一次动态内容。 然后在SurfaceView的“真实” Canvas上绘制两个Bitmap 。 它可能看起来像这样:

每个地图一次的部分:

 Bitmap mapBitmap = Bitmap.createBitmap(width, height, myConfig); Canvas c = new Canvas(mapBitmap); //draw map on c 

……和每帧一次的部分:

 //draw dynamic stuff Canvas canvas = getHolder().lockCanvas(); canvas.drawBitmap(mapBitmap, null, targetRect, null); canvas.drawBitmap(heroBitmap, null, targetRect, null); getHolder().unlockCanvasAndPost(); 

编辑:

您可以像myImage.draw(canvas)一样使用myImage.draw(canvas)绘制tile,但是将mapBitmap- Canvas作为参数而不是“real”canvas传递。 myConfig必须是Bitmap.Config 。 取RGB_565因为它是内部格式。