【问题标题】:Displaying text (like score) which changes on each frame显示在每一帧上变化的文本(如乐谱)
【发布时间】:2013-03-12 19:48:16
【问题描述】:

是否有任何简单的方法可以在 onDrawFrame 方法中显示在右上角没有任何纹理的简单白色文本,这些纹理在实现 Renderer 的类中的每一帧上都会发生变化?它是二维的,所以我相信不需要进行任何转换。我找到了很多教程,但是它们看起来都太复杂了,代码太多了。也许只需要几行代码就可以完成?如果这不可能,那么在不修改太多现有代码的情况下最简单的方法是什么?由于我是新手,请出示完整的代码。

【问题讨论】:

  • 有了一个好的位图字体库,它可能只需要几行。如果你找不到图书馆,那就需要更多。
  • @Geobits 关于我可以选择哪个库有什么建议吗?
  • 上次我查找时找不到完全符合我要求的。但是,它不仅仅是“显示一些数字”,所以可能会有一些适合你的东西,我只是不知道手头。
  • 你在问一些矛盾的东西。你说你看过教程,但是“代码太多”,但你想要一个完整的代码示例。你已经得到了答案,但不会接受你必须为此做一些工作。作为一个新手并不是不想弄清楚的借口。我们不是来为您编写代码的,而这似乎正是您想要的。

标签: java android opengl-es


【解决方案1】:

渲染器是一种 OpenGL 方法。 OpenGL ES 本身并不支持文本。这留下了以下选项:

  1. 使用纹理,使用 Android 的 Canvas 类对其进行绘制。
  2. 使用库。这很可能也会绘制到纹理上。
  3. 用多边形创建文本。

由于您的问题是寻求不绘制到纹理的解决方案,因此 1 和 2 都不适用。因为你想要一些简单的东西,所以 3 也出来了。没有留下好的解决方案。

要考虑的替代方法是在您正在使用的 GLSurfaceView 之上分层另一个视图。您可以使用 RelativeLayout 轻松堆叠两个视图,其中一个是可以锚定到屏幕右上角的文本视图。伪代码如下:

<RelativeLayout ... />
    <GLSurfaceView ... />
    <TextView ... />
</RelativeLayout>

这种方法的好处是让您摆脱 OpenGL 的要求来编写文本。我已经在我的几个应用上成功地做到了这一点。

【讨论】:

    【解决方案2】:

    您可能想查看 Android SDK 示例附带的 API Demos 项目。有一个 OpenGL Sprite Text 示例可以完全满足您的要求。

    您可以通过在模拟器(或设备)上安装 API Demos 并导航至: API 演示 > 图形 > OpenGL ES > 精灵文本

    这是截图:

    在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);
    

    【讨论】:

    • 您运行的是 API 演示还是我的示例应用程序?我的应用程序是 Sprite Text API 演示的精简版本,因为我删除了三角形精灵。这样就很容易理解只需要哪些代码行来渲染分数。您当然可以在特定于您的应用的屏幕上绘制更多内容。
    • +1 感谢您关于仅提取必要代码的说明。对我很有用:)
    【解决方案3】:

    尝试查看 CodeHead 的 Bitmap Font Generator 和 Android Loader,并尝试使用此代码。

    CBFG

    Android Loader

    【讨论】:

      【解决方案4】:

      我使用了位图画布 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);
      

      如果你去here 在第 9 章 src/com.badlogic.androidgames.framework.gl.Font.java 是我用于位图字体的,我使用 Codeheads 位图字体生成器生成位图字体

      【讨论】:

      • 我更新了一些代码,我不确定它是否会按照你想要的“每一帧”工作,但我想它值得一试
      • geobits 可能是正确的,虽然关于位图字体库,我有一个定制的,虽然它与一大堆类有关,我可以指出你的代码吗?我从一本书中学到的
      【解决方案5】:

      文本应该位于与 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的宽度和高度)

      【讨论】:

        【解决方案6】:

        在我看来,您可以使用RelativeLayout 来包装GLSurfaceView,也可以使用另一个TextView 来放置您想要的任何位置。然后在您的 Renderer 构造函数中,传递 TextView 引用 GLES20TriangleRenderer(上下文上下文,TextView tv) 在 onDrawFrame 方法中,调用

         ((Activity)mContext).runOnUiThread(new Runnable(){
        
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    tv.setText(Math.random() + " random");
        
                }
        
            });
        

        【讨论】:

          【解决方案7】:

          您需要将您的乐谱文本绘制到一个位图上,然后将此位图用作纹理。

          要在位图上绘制文本,您可以使用以下代码:

          // 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());
          

          【讨论】:

            【解决方案8】:

            您可以简单地将TextView 附加到您的ActivityWindowManager 并从那里显示。如下。

            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);
                }
            
            });
            

            【讨论】:

              猜你喜欢
              • 2016-02-09
              • 1970-01-01
              • 2019-03-24
              • 1970-01-01
              • 1970-01-01
              • 2012-11-09
              • 2016-11-21
              • 1970-01-01
              • 2014-01-02
              相关资源
              最近更新 更多