Displaying text (like score) which changes on each frame

点点圈 提交于 2019-12-08 17:47:12

问题


Is there any easy way to display simple white text without any textures on the right top corner which changes on each frame in the class which implements Renderer, in onDrawFrame method? It's 2D, so there is no need to make any transformations, I believe. I've found many tutorials, but they all seem just too complex with too much code. Maybe it could be done just with a few lines of code? If that's not possible, what's the easiest way to do it without modifying too much of existing code? Please show complete code as I am a newbie.


回答1:


Renderer is an OpenGL method. OpenGL ES doesn't inherently support text. This leaves the following options:

  1. Use a texture, draw to it using Android's Canvas class.
  2. Use a library. This will most likely also draw to a texture as well.
  3. Create the text with polygons.

Since your question is asking for a solution that doesn't draw to a texture, then 1 and 2 are both out. And since you want something simple, 3 is also out. Leaving no good solutions.

An alternative to consider is to layer another view on top of the GLSurfaceView you are using. You can use a RelativeLayout to easily stack two views, one being a textview that you can anchor to the top right corner of the screen. Pseudocode below:

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

This approach has the benefit of pulling you out of the OpenGL requirements to do your text. I've done this successfully on a couple of my apps.




回答2:


You may want to take a look at the API Demos project which comes with the Android SDK samples. There is a OpenGL Sprite Text sample which does exactly what you want.

You can see the demo by installing API Demos on emulator (or device) and navigating to: API Demos > Graphics > OpenGL ES > Sprite Text

Here is a screenshot:

The text at the bottom right corner of the screen is changed on each frame in onDrawFrame method of the Renderer.

You can find the source code in your Android SDK samples directory: ApiDemos\src\com\example\android\apis\graphics\spritetext

You'll need to copy few files into your project and with very few lines of code can achieve the same functionality.

Sample Application: I have created a sample application to demonstrate the same by reusing code from the API Demos project. You can get it from here - OpenGLText_eclipse_project.zip

In brief, you can reuse Grid.java, LabelMaker.java, NumericSprite.java completely. Then add few lines of code in your Renderer for using the above classes as shown in my TextRenderer.java

Here is how it looks with the score updating continuously.

Basically, rendering the score is as simple as this:

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



回答3:


Try to look at CodeHead's Bitmap Font Generator and Android Loader, and try to use this code .

CBFG

Android Loader




回答4:


i used a bitmap canvas drawText, but i still had to use it as a texture, probably with a smaller bitmap and font size

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

if you go here in chapter 9 src/com.badlogic.androidgames.framework.gl.Font.java is what i use for bitmap fonts and i generate the bitmapfonts with Codeheads Bitmap Font Generator




回答5:


The text should be in a different layer than the OpenGL one.

<FrameLayout>
    <GLSurfaceView/>
    <LinearLayout android:layout_gravity="top|right" >
        <TextView android:id="@+id/score" ... />
    </LinearLayout>
</FrameLayout>

FrameLayout allows views to be stacked one on the top of the other. Then set the text with:

( (TextView) findViewById(R.id.score) ).setText( "Your Score" );

You may need to force the redrawing of the score layout after each rendering of the GLSurfaceView to avoid that openGL draws on top of the text. (not sure about this)

For the performance sake, make the text area as small as possible (wrap_content for width and height of the LinearLayout)




回答6:


In my opinion, you can use a RelativeLayout to wrap the GLSurfaceView, and also another TextView to put wherever you want. Then in your Renderer constructor, pass the TextView reference GLES20TriangleRenderer(Context context, TextView tv) In the onDrawFrame method, call

 ((Activity)mContext).runOnUiThread(new Runnable(){

        @Override
        public void run() {
            // TODO Auto-generated method stub
            tv.setText(Math.random() + " random");

        }

    });



回答7:


You need to draw your score text to a Bitmap, and after use this bitmap as a texture.

To draw a text on the bitmap you can use this code:

// 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:


You could simply attach a TextView to your Activity's WindowManager and show it from there. As followed.

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

Then update this via

activity.runOnUiThread(new Runnable(){

    @Override
    public void run() {
        tv.setText("FPS: " + fps);
    }

});



来源:https://stackoverflow.com/questions/15370748/displaying-text-like-score-which-changes-on-each-frame

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!