有没有什么简单的方法可以在右上角显示没有任何纹理的简单白色文本,这些纹理在 onDrawFrame 方法中实现 Renderer 的类中的每一帧都会发生变化?它是二维的,所以我相信不需要进行任何转换。我找到了很多教程,但是它们看起来都太复杂了,代码太多了。也许只需要几行代码就可以完成?如果这不可能,那么在不修改太多现有代码的情况下最简单的方法是什么?请显示完整的代码,因为我是新手。
8 回答
渲染器是一种 OpenGL 方法。OpenGL ES 本身并不支持文本。这留下了以下选项:
- 使用纹理,使用 Android 的 Canvas 类对其进行绘制。
- 使用图书馆。这很可能也会绘制到纹理上。
- 用多边形创建文本。
由于您的问题是要求一个不绘制纹理的解决方案,因此 1 和 2 都出局了。因为你想要一些简单的东西,所以 3 也出来了。留下没有好的解决方案。
要考虑的替代方法是在您正在使用的 GLSurfaceView 之上分层另一个视图。您可以使用 RelativeLayout 轻松堆叠两个视图,其中一个是可以锚定到屏幕右上角的文本视图。伪代码如下:
<RelativeLayout ... />
<GLSurfaceView ... />
<TextView ... />
</RelativeLayout>
这种方法的好处是让您摆脱 OpenGL 的要求来编写文本。我已经在我的几个应用程序上成功地做到了这一点。
您可能想查看 Android SDK 示例附带的 API Demos 项目。有一个 OpenGL Sprite Text 示例可以完全满足您的要求。
您可以通过在模拟器(或设备)上安装 API Demos 并导航至:API Demos > Graphics > OpenGL ES > Sprite Text 来查看演示
这是一个屏幕截图:
在 Renderer 的 onDrawFrame 方法中,屏幕右下角的文本每帧都会发生变化。
您可以在 Android SDK 示例目录中找到源代码: ApiDemos\src\com\example\android\apis\graphics\spritetext
您需要将少量文件复制到您的项目中,并且只需很少的代码行就可以实现相同的功能。
示例应用程序:我创建了一个示例应用程序,通过重用 API Demos 项目中的代码来演示相同的内容。你可以从这里得到它 - OpenGLText_eclipse_project.zip
简而言之,您可以完全重用 Grid.java、LabelMaker.java、NumericSprite.java。然后在您的渲染器中添加几行代码以使用上述类,如我的 TextRenderer.java 中所示
这是分数不断更新时的样子。
基本上,渲染分数就像这样简单:
LabelMaker mLabels = new LabelMaker();
mLabels.initialize(gl);
mLabels.beginAdding(gl);
int mLabelMsPF = mLabels.add(gl, "Score:", mLabelPaint);
mLabels.endAdding(gl);
mLabels.beginDrawing(gl, mWidth, mHeight);
mLabels.draw(gl, 0, 0, mLabelMsPF);
mLabels.endDrawing(gl);
NumericSprite mNumericSprite = new NumericSprite();
mNumericSprite.setValue(16);
mNumericSprite.draw(gl, 0, 0, mWidth, mHeight);
文本应该在与 OpenGL 不同的层中。
<FrameLayout>
<GLSurfaceView/>
<LinearLayout android:layout_gravity="top|right" >
<TextView android:id="@+id/score" ... />
</LinearLayout>
</FrameLayout>
FrameLayout 允许视图堆叠在另一个之上。然后设置文本:
( (TextView) findViewById(R.id.score) ).setText( "Your Score" );
您可能需要在每次渲染 GLSurfaceView 后强制重新绘制乐谱布局,以避免 openGL 在文本顶部绘制。(不确定这个)
为了性能起见,使文本区域尽可能小(wrap_content为LinearLayout的宽度和高度)
我使用了位图画布 drawText,但我仍然必须将其用作纹理,可能使用较小的位图和字体大小
bitmap = Bitmap.createBitmap(256, 256, Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
h = (int)((((System.currentTimeMillis()/1000)/60)/60)%60);
m = (int)(((System.currentTimeMillis()/1000)/60)%60);
s = (int)((System.currentTimeMillis()/1000)%60);
paint = new Paint();
paint.setColor(Color.MAGENTA);
paint.setTextAlign(Align.CENTER);
paint.setTypeface(Typeface.DEFAULT_BOLD);
paint.setTextSize(55);
time = String.valueOf(h) + "h" + String.valueOf(m) + "m" + String.valueOf(s) + "s";
canvas.drawText(time, bitmap.getWidth()/2, 100, paint);
int[] textureIds = new int[1];
gl.glGenTextures(1, textureIds, 0);
textureId = textureIds[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
如果你在第 9 章 src/com.badlogic.androidgames.framework.gl.Font.java 是我用于位图字体的地方,我使用 Codeheads 位图字体生成器生成位图字体
您需要将乐谱文本绘制到位图上,然后将此位图用作纹理。
要在位图上绘制文本,您可以使用以下代码:
// Create and draw a texto to your bitmap.
Bitmap bm = Bitmap.createBitmap(300, 100, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bm);
Paint p = new Paint();
p.setColor(Color.RED);
c.drawText("YOUR SCORE", 0, 0, new Paint());
在我看来,您可以使用 RelativeLayout 来包装 GLSurfaceView,也可以使用另一个 TextView 来放置您想要的任何位置。然后在你的 Renderer 构造函数中,传递 TextView 引用 GLES20TriangleRenderer(Context context, TextView tv) 在 onDrawFrame 方法中,调用
((Activity)mContext).runOnUiThread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
tv.setText(Math.random() + " random");
}
});
您可以简单地将 a 附加TextView
到您Activity
的 'sWindowManager
并从那里显示它。如下。
TextView tv = new TextView(this);
tv.setText("FPS: 0");
//get WindowManager from Activity
WindowManager w = this.getWindowManager();
//setup view LayoutParams
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSPARENT);
//position
lp.gravity = Gravity.RIGHT | Gravity.TOP;
//attach view
w.addView(tv,lp);
然后通过更新
activity.runOnUiThread(new Runnable(){
@Override
public void run() {
tv.setText("FPS: " + fps);
}
});