6

我一直在寻找答案,但似乎找不到答案(这是一种非常规的 android 游戏编程方法,所以至少我认为这是可以预料的)。

我正在尝试在 Android 中创建 GBA 风格的 RPG 游戏(用于怀旧)。OpenGL 对我来说不够好,因为它在游戏循环中的可定制性不够(我只想在需要绘制某些东西时调用 draw,因为我希望这个游戏在使用方式上非常高效电池,这意味着让它更像一个投票应用程序而不是游戏)。我创建了一个自定义表面视图,它有自己的线程,每当需要完成绘图时就会调用它(我在 SDK 中的示例 LunarLander android 游戏之后对其进行建模)。

问题是,我希望游戏本身是固定大小(208x160),然后放大到屏幕大小。我遇到的问题是,在 XML 中扩展 SurfaceView 的正常参数中似乎没有这样做。当前状态下的游戏如下图所示。我试图让它伸展到屏幕的高度并保持宽度的比例,同时也不添加到可视游戏中(保持它固定,不管屏幕大小)。

https://i.stack.imgur.com/EWIdE.png(我打算在线发布实际图像。垃圾邮件预防会咬我>.<)

目前,我正在获取 SurfaceView 的画布并直接对其进行绘图,并将我的尺寸作为硬编码的像素尺寸(208 像素、160 像素)提供。

这就是线程当前在获取画布和绘制它时的样子。在不改变我希望游戏虚拟占用的大小的情况下绘制画布的更好方法是什么?

@Override
    public void run()
    {
        Canvas c = null;
        try
        {
            c = surfaceHolder.lockCanvas(null);
            synchronized (surfaceHolder)
            {
                draw(c);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (c != null)
                surfaceHolder.unlockCanvasAndPost(c);
        }
    }

绘制方法是这样的(StringBuilder是我自己在引擎中编码的Object):

public void draw(Canvas canvas)
{       
    canvas.drawColor(Color.GRAY);
    StringBuilder stringBuilder = new StringBuilder(canvas, Color.BLACK, letters);
    stringBuilder.drawString("Oh, hello there!");
    stringBuilder.setLocation(10, 20);
    stringBuilder.drawString("Why am I so small?");
}

有任何想法吗?

4

2 回答 2

5

假设您的draw函数被重命名为drawBase。这是您的操作方法:

public void draw(Canvas canvas)
{
    final float scaleFactor = Math.min( getWidth() / 208.f, getHeight() / 160.f );
    final float finalWidth = 208.f * scaleFactor;
    final float finalHeight = 160.f * scaleFactor;
    final float leftPadding = ( getWidth() - finalWidth ) / 2;
    final float topPadding =  ( getHeight() - finalHeight ) / 2;

    final int savedState = canvas.save();
    try {
        canvas.clipRect(leftPadding, topPadding, leftPadding + finalWidth, topPadding + finalHeight);

        canvas.translate(leftPadding, topPadding);
        canvas.scale(scaleFactor, scaleFactor);

        drawBase(canvas);
    } finally {
        canvas.restoreToCount(savedState);
    }
}
于 2012-05-22T18:45:50.903 回答
2

(K-ballo 接受的答案很好,但在它编写后的 2.5 年里,显示器变得更加密集,这意味着软件渲染越来越昂贵。让硬件来帮助完成这项工作很重要。)

要以特定分辨率渲染,您可以使用SurfaceHolder#setFixedSize()。这会将 Surface 的大小设置为您指定的确切尺寸。硬件缩放器将缩放表面以匹配视图的大小,这将比软件缩放更有效。此博客文章中描述了该功能,您可以在Grafika 的“硬件缩放器练习器”活动(演示视频)中看到它的实际效果。

您可以通过调整 Surface 的大小(这是 Grafika 为该演示所做的)或通过将 View 调整为信箱或邮筒布局来为不同大小的显示器保持适当的纵横比。您可以在 Grafika 的 AspectFrameLayout 类中找到后者的示例,该类用于各种相机和视频演示。

关于这一点:

OpenGL 对我来说不够好,因为它在游戏循环中不够可定制(我只想在需要绘制某些东西时调用 draw ...

你有两个选择。首先,您可以使用GLSurfaceView#setRenderMode()禁用连续渲染。其次,你不需要使用 GLSurfaceView 来使用 OpenGL。Grafika 中的大部分 GLES 代码都在 SurfaceView 或 TextureView 上运行。

于 2015-01-05T17:21:01.073 回答