Отображение текста (например, счет), который меняется на каждом кадре

Есть ли простой способ отобразить простой белый текст без текстур в правом верхнем углу, который изменяется на каждом кадре в классе, который реализует Renderer, в методе onDrawFrame? Это 2D, так что нет необходимости делать какие-либо преобразования, я считаю. Я нашел много учебников, но все они кажутся слишком сложными из-за слишком большого количества кода. Может быть, это можно сделать всего несколькими строками кода? Если это невозможно, каков самый простой способ сделать это без изменения слишком большого количества существующего кода? Пожалуйста, покажите полный код, так как я новичок.

8 ответов

Renderer - это метод OpenGL. OpenGL ES по своей природе не поддерживает текст. Это оставляет следующие варианты:

  1. Используйте текстуру, нарисуйте ее, используя класс Android Canvas.
  2. Используйте библиотеку. Скорее всего, это также привлечет текстуру.
  3. Создайте текст с полигонами.

Поскольку ваш вопрос требует решения, которое не обращается к текстуре, то 1 и 2 оба отсутствуют. И так как вы хотите что-то простое, 3 также отсутствует. Не оставляя хороших решений.

Альтернативой для рассмотрения является наложение другого представления поверх используемого вами GLSurfaceView. Вы можете использовать RelativeLayout для простого объединения двух представлений, одно из которых представляет собой текстовое представление, которое можно привязать к верхнему правому углу экрана. Псевдокод ниже:

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

Преимущество этого подхода состоит в том, что вы вытаскиваете вас из требований OpenGL для написания текста. Я сделал это успешно на нескольких моих приложениях.

Возможно, вы захотите взглянуть на проект API Demos, который поставляется с примерами Android SDK. Существует образец OpenGL Sprite Text, который делает именно то, что вы хотите.

Демонстрацию можно увидеть, установив демоверсии API на эмуляторе (или устройстве) и перейдя по ссылке: Демоверсии API> Графика> OpenGL ES > Sprite Text

Вот скриншот:

введите описание изображения здесь

Текст в правом нижнем углу экрана изменяется в каждом кадре в методе onDrawFrame средства визуализации.

Вы можете найти исходный код в каталоге примеров Android SDK:ApiDemos \ src \ com \ example \ android \ apis \ graphics \ spritetext

Вам нужно будет скопировать несколько файлов в ваш проект, и с помощью очень небольшого количества строк кода можно достичь той же функциональности.

Пример приложения: я создал пример приложения, чтобы продемонстрировать то же самое путем повторного использования кода из проекта API Demos. Вы можете получить это здесь - http://www.appsrox.com/shared/OpenGLText_eclipse_project.zip

Вкратце, вы можете полностью использовать Grid.java, LabelMaker.java, NumericSprite.java. Затем добавьте несколько строк кода в ваш Renderer для использования вышеупомянутых классов, как показано в моем 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);

Попробуйте взглянуть на генератор растровых шрифтов CodeHead и загрузчик Android и попробуйте использовать этот код.

CBFG

Android Loader

Я использовал 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 Bitmap Font Generator

Текст должен быть в другом слое, чем в 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)

Вам нужно нарисовать текст партитуры в растровое изображение, а затем использовать это растровое изображение в качестве текстуры.

Чтобы нарисовать текст на растровом изображении, вы можете использовать этот код:

// 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(Контекст контекста, TextView TV). В методе onDrawFrame вызовите

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

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

        }

    });

Вы можете просто прикрепить TextView на ваш Activity"s WindowManager и покажи это оттуда. Как и следовало

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

});

введите описание изображения здесь

Другие вопросы по тегам