[英]Drawing a tile based map
该脚本绘制控件,英雄,表面和地图:
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);
}
有一个英雄,当玩家使用控件移动他时必须重新绘制,所有其他可绘制对象也必须重新绘制。 问题在于绘制地图是一个漫长的过程,因此我创建的地图越大,英雄移动的速度就越慢,因为必须绘制地图的每个图块。 有没有一种方法可以将所有图块以其他方法放置到一个位图,然后在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)
,但经过mapBitmap- Canvas
作为参数,而不是你的“真实”的画布。 myConfig
必须是Bitmap.Config 。 以RGB_565
为内部格式。
最好的选择是只绘制地图在屏幕上可见的部分。 这样,无论整个地图变成多大,该地图的绘制始终是恒定的。 由于您使用的是网格系统,因此可以轻松找出英雄所在的单元格:
heroGridX = hero.x % mapWidth;
heroGridY = hero.y % mapHeight;
在这里,您可以使用画布的宽度和高度以及网格单元的宽度和高度的恒定大小来计算要在播放器周围绘制多少个单元:
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时间而消耗更多的内存。 随着地图的变大,绘制该地图所需的内存也随之增加。 该算法只是使地图绘制保持恒定,因为屏幕大小在运行时不会改变。 并且,与其他选项相比,您的内存使用量不会随着地图的增大而增大(与在画布中绘制更多的图块相比,其占用的空间很小)。 一个重要的事实是,如果您的屏幕更大(例如平板电脑还是手机)。 该算法也将适当放大,因此玩家将看到更多地图周围的地形。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.