Android - 跟随角色移动的缩放相机的Canvas onDraw。

6

一些背景信息:

我正在创建一个Android游戏,它在背景图像上绘制迷宫到画布上,这使用了一个正方形块,因此迷宫总是自动缩放为5 x 5的正方形,而实际迷宫可能是20 x 20。迷宫是通过简单地运行一组for循环然后在相关位置绘制线条来绘制的。这一切都工作得很完美,但是我在让我的onDraw平滑工作方面遇到了问题。这是由于每次无效化时,我必须重新运行for循环并运行各种if语句来检查位置(不幸的是,这个过程无法改进)。

问题:

我想重新编写迷宫绘制到画布上的方式,以下是我需要实现的3个主要功能:

1-将整个迷宫绘制到画布上(这很容易) 2-放大迷宫,只显示5 x 5 3-移动角色(始终位于屏幕中心)并绘制迷宫的下一个部分

如上所述,绘制整个迷宫非常容易,并且会使onDraw显着加快,因为无需在invaldate时运行for循环,可以在加载级别时只运行一次。

就第2和3点而言,我认为这样可以工作:将角色绘制在画布中央,然后将一个2D鸟瞰视图相机连接/链接到角色的移动上。此相机还需要缩放到仅显示整个迷宫网格的5 x 5。然后随着角色的移动,相机会随之移动并显示已经绘制的迷宫的下一个部分。我尝试了一些事情并进行了一些研究,但我以前从未使用过画布,真的不知道从哪里开始,也不知道这是否可行。

因此,总结主要问题是是否有一种方法将鸟瞰视图相机与缩放并随角色图像移动的角色相连接。

以下是当前绘制迷宫的代码片段,使用两组for循环检查两组布尔数组[][],这些数组仅存储要绘制的垂直和水平线条。

@Override
protected void onDraw(Canvas canvas) 
{
    canvas.drawRect(0, 0, width, 100, background);
    RectBackground.set(0,0, FullScreenWidth, FullScreenWidth);
    canvas.drawBitmap(gameBackground, null, RectBackground, null);

    for(int i = 0; i < 5; i++) 
    {
        for(int j = 0; j < 5; j++)
        {
            float x = j * totalCellWidth;
            float y = i * totalCellHeight;

            indexY = i + currentY;
            indexX = j + currentX;

            // Draw Verticle line (y axis)
            if (indexY < vLength && indexX < vLines[indexY].length && vLines[indexY][indexX])
            {
                RectOuterBackground.set((int)x + (int)cellWidth, (int)y, (int)x + (int)cellWidth + 15,  (int)y + (int)cellHeight + 15);
                canvas.drawBitmap(walls, null, RectOuterBackground, null);
            }
            // Draws Horizontal lines (x axis)
            if (indexY < hLength && indexX < hLines[indexY].length && hLines[indexY][indexX])
            {
                RectOuterBackground.set((int)x, (int)y + (int)cellHeight,(int)x + (int)cellWidth + 15,(int)y + (int)cellHeight + 15);
                canvas.drawBitmap(walls, null, RectOuterBackground, null);
            }
        }
    }
}
2个回答

1
要进行缩放,您需要将坐标乘以一个数字(缩放因子)。
int x1 = (int)x + (int)cellWidth; 
int y1 = (int)y; 
int x2 = (int)x + (int)cellWidth + 15;  
int y2 = (int)y + (int)cellHeight + 15;

RectOuterBackground.set(x1*zoom, y1*zoom, x2*zoom, y2*zoom);

请注意,缩放必须是浮点数,使用zoom=2将使所有内容放大两倍。
如果您想将相机放置在单元格(xc,yc)上方,则需要执行以下操作:
RectOuterBackground.set( (x1-xc)*zoom, (y1-yc)*zoom, (x2-xc)*zoom, (y2-yc)*zoom);

首先尝试绘制整个迷宫,很快你就会发现如何只绘制屏幕内的部分迷宫。

希望这能帮到你,如果有任何问题,请告诉我 :)


今晚我会看一下这个,然后告诉你我的进展情况。 - SingleWave Games
你能否提供一个更完整的代码片段给我,因为我不太确定如何实现它。例如,int后面是否应该有分号。到目前为止,我已经画出了完整的10 x 10迷宫,现在我需要使用相机实现缩放,以便平滑地移动(逐渐显示迷宫的下一部分)。谢谢。 - SingleWave Games
你能把你目前的进展发给我吗?我会为你实现这一部分。 - aguaviva
嗨,这是我的完整onDraw函数,它绘制了迷宫的背景图像和线条,以及角色和他的移动(角色是一个精灵图像)。http://pastebin.com/YL9utzpe 谢谢。 - SingleWave Games

1
为了加快绘图速度,您可以通过直接绘制到位图并将位图闪烁到画布中来双缓冲画布。这非常快速。
private void init()
{
        //variables below are class-wide variables
        b = Bitmap.createBitmap(cwidth, cheight, Bitmap.Config.ARGB_8888);
        bitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        bitmapPaint.setStyle(Paint.Style.STROKE);

        bitmapPaint.setStrokeWidth(3);
        myPaint.setColor(0xff000000);
        myCanvas = new Canvas(b);
}

protected void onDraw(Canvas c)
{
    super.onDraw(c);
    c.drawBitmap(b, 0, 0, myPaint);

    for(int i = 0; i < number lines; i++)
    {
        //draw here using myPath
    }

    if(b != null)
        c.drawBitmap(b, 0, 0, myPaint);

    myCanvas.drawPath(myPath, bitmapPaint);

}

为了“移动”,我建议使用裁剪框。这意味着,在1:1的比例下,图像比屏幕上显示的视口要大。实际上,“移动”时发生的是位图在裁剪框下移动。

您可以使用BitmapRegionDecoder仅显示角色所在的区域(这可能会比较慢),或者使用

public void drawBitmap (Bitmap bitmap, Rect src, RectF dst, Paint paint)

这里的src参数允许您指定要显示的位图的小区域。它实际上是一个剪裁框。

我还应该补充一下,onDraw方法非常不完整。如果你需要看到整个工作流程,我可以给你发送一些代码。我编写了一个类似于你使用迷宫的应用程序,它绘制笔记本线条并捕获手写笔的输入。 - mttdbrd
明天我会看一下这个,你能否发邮件给我你的完整代码,这样我就可以查看一个工作版本。谢谢。 - SingleWave Games
我不知道如何通过Stack Overflow向人们发送电子邮件。怎么办? - mttdbrd
只需点击我的用户名并从那里获取详细信息,然后可以从任何外部帐户发送电子邮件。 - SingleWave Games
请问您能否将相关示例代码发送至llpartners2012@gmail.com邮箱?谢谢。 - SingleWave Games

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接