dir.by  
  Поиск  
Программирование, разработка, тестирование
Android, Google Play телефон, планшет (пишем приложение, игру)
C++ игра (для Android телефона) в Android Studio | Android NDK, OpenGL ES
Загрузка bmp файла из Assets и рисование текстур в "Android Native C++ Game" для телефона | Android Studio, Android NDK, OpenGL ES v2 (shader), C++
  Посмотрели 3516 раз(а)    
 Загрузка bmp файла из Assets и рисование текстур в "Android Native C++ Game" для телефона | Android Studio, Android NDK, OpenGL ES v2 (shader), C++ 
последнее обновление: 14 ноября 2024
Загрузка bmp файла из Assets и рисование текстур в "Android Native C++ Texture Game" для телефона | Android Studio  Android NDK  OpenGL ES v2  shader   C++
Загрузка bmp файла из Assets и рисование текстур в "Android Native C++ Texture Game" для телефона | Android Studio, Android NDK, OpenGL ES v2 (shader), C++
Скачать проект с github.com:
В Google Chrome открываем github.com/EvgenProjects/AndroidNative_BasicGame_Texture
Шаг 1. Создаем проект
Шаг 2. Поменяем код в файле my_game.h
  C++  
#include <android/input.h>
#include <android/asset_manager.h>
#include <EGL/egl.h>
#include "texture_buffer_shader.h"

class MyGame
{
     // constructor
     public: MyGame(AAssetManager* pAssetManager);

     // my objects
protected:
     TextureImageOpenGL m_TextureImage_Hero;
     TextureImageOpenGL m_TextureImage_Ghost;

     BufferPointsOpenGL m_BufferPoints_Hero;
     BufferPointsOpenGL m_BufferPoints_Ghost1;
     BufferPointsOpenGL m_BufferPoints_Ghost2;

     ShaderOpenGL m_ShaderOpenGL;


     // fields
     protected: AAssetManager* m_pAssetManager;
     protected: EGLDisplay m_Display = EGL_NO_DISPLAY;
     protected: EGLSurface m_Surface = EGL_NO_SURFACE;
     protected: EGLContext m_Context = EGL_NO_CONTEXT;
     protected: EGLConfig m_configOpenGL = nullptr;
     protected: int32_t m_Width;
     protected: int32_t m_Height;

     // events
     public: void OnActiveFocus();
     public: void OnLostFocus();
     public: bool OnHandleTouch(AInputEvent* pEvent);
     public: void OnNextTick();

     // OpenGL
     public: void CreateSurfaceFromWindow_OpenGL(ANativeWindow* pWindow); // calling when window set focus (need recreate Surface OpenGL)
     public: void KillSurface_OpenGL(); // calling when window kill focus (need destroy Surface OpenGL)
     public: bool MakeCurrent_Display_Surface_Context_OpenGL();
     public: bool InitGraphic_OpenGL(ANativeWindow* pWindow);
     public: void CloseGraphic_OpenGL();
     public: void DrawGraphic_OpenGL();
};
Шаг 3. Поменяем код в файле my_game.cpp
Файл my_game.cpp
...
 
void MyGame::DrawGraphic_OpenGL()
{
     if (m_Display == EGL_NO_DISPLAY || m_Surface == EGL_NO_SURFACE)
          return;

     if (m_Context == EGL_NO_CONTEXT)
          return;

     // green color
     glClearColor(0.72f, 0.87f, 0.55f, 1);
     glClear(GL_COLOR_BUFFER_BIT);

     m_ShaderOpenGL.MakeActive();
     m_ShaderOpenGL.Draw(m_TextureImage_Hero, m_BufferPoints_Hero);
     m_ShaderOpenGL.Draw(m_TextureImage_Ghost, m_BufferPoints_Ghost1);
     m_ShaderOpenGL.Draw(m_TextureImage_Ghost, m_BufferPoints_Ghost2);
     m_ShaderOpenGL.Disable();

     eglSwapBuffers(m_Display, m_Surface);
}
 
...
 
bool MyGame::InitGraphic_OpenGL(ANativeWindow* pWindow)
{
     // init Display
     m_Display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     eglInitialize(m_Display, nullptr, nullptr);

     // init Surface
     CreateSurfaceFromWindow_OpenGL(pWindow);

     // init Context
     EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2,EGL_NONE };
     m_Context = eglCreateContext(m_Display, m_configOpenGL, NULL, contextAttribs);

     if (!MakeCurrent_Display_Surface_Context_OpenGL())
          return false;

     EGLint w, h;
     eglQuerySurface(m_Display, m_Surface, EGL_WIDTH, &w);
     eglQuerySurface(m_Display, m_Surface, EGL_HEIGHT, &h);

     m_Width = w;
     m_Height = h;

     // Open GL states
     glDisable(GL_CULL_FACE);
     glDisable(GL_DEPTH_TEST);
     glEnable(GL_TEXTURE_2D);

     // for alpha color (transparency)
     glEnable( GL_BLEND );
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

     // create shader (for drawing vertex very fast)
     m_ShaderOpenGL.Create();

     // load textures
     m_TextureImage_Hero.Create(m_pAssetManager, "hero.bmp", GL_RGB);
     m_TextureImage_Ghost.Create(m_pAssetManager, "ghost.bmp", GL_RGB);

     // create display points and texture points
     float z = 0;
     PosXYZ_TextureXY* pBuffer = nullptr;

     pBuffer = new PosXYZ_TextureXY[]{
               {.x=0.0, .y=0.5, .z=z, .texture_x=0, .texture_y=0}, // left top
               {.x=0.4, .y=0.5, .z=z, .texture_x=1, .texture_y=0}, // right top
               {.x=0.0, .y=0.9, .z=z, .texture_x=0, .texture_y=1}, // left bottom
               {.x=0.4, .y=0.9, .z=z, .texture_x=1, .texture_y=1} // right bottom
     };
     m_BufferPoints_Hero.Create(pBuffer, 4,GL_TRIANGLE_STRIP);
     delete[] pBuffer;

     pBuffer = new PosXYZ_TextureXY[]{
               {.x=0.5, .y=0.2, .z=z, .texture_x=0, .texture_y=0}, // left top
               {.x=0.7, .y=0.2, .z=z, .texture_x=1, .texture_y=0}, // right top
               {.x=0.5, .y=0.4, .z=z, .texture_x=0, .texture_y=1}, // left bottom
               {.x=0.7, .y=0.4, .z=z, .texture_x=1, .texture_y=1} // right bottom
     };
     m_BufferPoints_Ghost1.Create(pBuffer, 4,GL_TRIANGLE_STRIP);
     delete[] pBuffer;

     pBuffer = new PosXYZ_TextureXY[]{
               {.x=0.8, .y=0.6, .z=z, .texture_x=0, .texture_y=0}, // left top
               {.x=1, .y=0.6, .z=z, .texture_x=1, .texture_y=0}, // right top
               {.x=0.8, .y=0.8, .z=z, .texture_x=0, .texture_y=1}, // left bottom
               {.x=1, .y=0.8, .z=z, .texture_x=1, .texture_y=1} // right bottom
     };
     m_BufferPoints_Ghost2.Create(pBuffer, 4,GL_TRIANGLE_STRIP);
     delete[] pBuffer;


     return true;
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 рисуем текстуры в OpenGL используя Shader
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
// load textures
m_TextureImage_Hero.Create(m_pAssetManager, "hero.bmp", GL_RGB);
 // Это означает, что файл hero.bmp будет загружен из папки assets и будет создан texture OpenGL id

m_TextureImage_Ghost.Create(m_pAssetManager, "ghost.bmp", GL_RGB);
 // Это означает, что файл ghost.bmp будет загружен из папки assets и будет создан texture OpenGL id

На заметку по поводу assets folder:
 Я создал папку  assets и положил туда 2 файла hero.bmp и ghost.bmp.
Вот так:
  D:\MyGit\AndroidNative_BasicGame\app\src\main\assets\
      hero.bmp
      ghost.bmp
Чтобы создать папку  assets я открыл File Explorer и создал новую папку.
Этот путь в проект никуда не надо подключать.
Читать подробнее: Как получить файл bmp, расположенный в Assets внутри файла apk ... | Android Studio, NDK, C++
 
Важно о размере bmp файла для текстуры!
При рисовании текстуры на экране обязательно ширина bmp картинки должна делится на 4 и высота картинки должна делится на 4. Если не делится на 4 то текстура на экране не нарисуется
Примеры bmp файла:
Хороший bmp для текстуры: ширина = 100 точек, высота = 60 точек.
Плохой bmp для текстуры: ширина = 90 точек, высота = 60 точек (плохой потому что 90 не делится на 4). 
 
 
 
 
Шаг 4. Создадим новый файл texture_buffer_shader.h
В этом файле я написал 3 класса:
class TextureImageOpenGL
загрузка bmp файла из папки assets и создание OpenGL texture id
class BufferPointsOpenGL
хранение 3D точек в video card buffer и создание OpenGL buffer id
class ShaderOpenGL
Очень быстрое рисование 3D точек используя OpenGL shader
  C++     Файл texture_buffer_shader.h
#pragma once

#include <GLES2/gl2.h>

struct PosXYZ_TextureXY
{
     float x;
     float y;
     float z;
     float texture_x;
     float texture_y;
};

class TextureImageOpenGL
{
     public:
     TextureImageOpenGL();
     virtual ~TextureImageOpenGL();

     public:
     bool Create(AAssetManager* pAssetManager, const char* filename, GLuint imgFormat);
     int32_t GetTextureId();

     private:
     GLuint m_TextureId;
     void* LoadImageFromAssets(AAssetManager* pAssetManager, const char* filename, int* pFileSize);
     void Swap24BitColors(void* pBuffer, int count);
     void Bmp24BitUpDownLines(void* pColorData, int width, int height);
     void GetBmpWidthHeight(void* pFileData, int count, int* pWidth, int* pHeight, int* pDataOffset);
};

class BufferPointsOpenGL
{
     public:
     BufferPointsOpenGL();
     virtual ~BufferPointsOpenGL();

     public:
     bool Create(PosXYZ_TextureXY* pBuffer, int pointsCount, GLuint pointsModeHowToDraw);
     int32_t GetBufferId();
     GLuint GetPointsModeHowToDraw();
     GLuint GetPointsCount();

     private:
     GLuint m_BufferId;
     GLuint m_PointsModeHowToDraw;
     GLuint m_PointsCount;
};

class ShaderOpenGL
{
     public:
     ShaderOpenGL();
     virtual ~ShaderOpenGL();

     public:
     bool Create();
     void MakeActive();
     void Draw(TextureImageOpenGL& rTextureImageOpenGL, BufferPointsOpenGL& rBufferPointsOpenGL);
     void Disable();
     void Close();

     private:
     GLuint LoadShader(const char *shaderSrc, GLenum type);
     int32_t m_ShaderId;
     int m_SHADER_TEXTURE_parameter_position_index;
     int m_SHADER_TEXTURE_parameter_texture_index;
};
Шаг 5. Создадим новый файл texture_buffer_shader.cpp
  C++     Файл texture_buffer_shader.cpp
#include <android/native_window.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <android/asset_manager.h>
#include "texture_buffer_shader.h"

#include <string>

bool WaitOpenGlStatus(int goodOpenGlStatus, int waitSeonds)
{
     timespec timeNow1;
     clock_gettime(CLOCK_MONOTONIC, &timeNow1);

     while (true)
     {
          if (glGetError()==goodOpenGlStatus)
               return true;

          sleep(1); // sleep 1 second

          timespec timeNow2;
          clock_gettime(CLOCK_MONOTONIC, &timeNow2);
          if ((timeNow2.tv_sec- timeNow1.tv_sec)>waitSeonds)
               return false;
     };
}

/////////// class TextureImageOpenGL //////////////
TextureImageOpenGL::TextureImageOpenGL()
{
     m_TextureId = 0;
}

TextureImageOpenGL::~TextureImageOpenGL()
{
}

bool TextureImageOpenGL::Create(AAssetManager* pAssetManager, const char* filename, GLuint imgFormat)
{
     m_TextureId = 0;
     int fileSize = 0;
     void* pFileData = LoadImageFromAssets(pAssetManager, filename, &fileSize);

     int width = 0;
     int height = 0;
     int dataOffset = 0;
     GetBmpWidthHeight(pFileData, fileSize, &width, &height, &dataOffset);

     void* pColorData = (char*)pFileData + dataOffset;
     Swap24BitColors(pColorData, fileSize-dataOffset);
     Bmp24BitUpDownLines(pColorData, width, height);

     GLuint textureID = 0;
     glGenTextures(1, &textureID);
     glBindTexture(GL_TEXTURE_2D, textureID);

     glTexImage2D(GL_TEXTURE_2D, 0, imgFormat, width, height, 0, imgFormat, GL_UNSIGNED_BYTE, pColorData);

     if (WaitOpenGlStatus(GL_NO_ERROR, 5 /*seconds to finish wait*/))
     {
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
          glGenerateMipmap(GL_TEXTURE_2D);
     }
     else // error
     {
          textureID = 0;
          return false;
     }

     if (pFileData!= nullptr)
          delete[] ((char*)pFileData);

     glBindTexture(GL_TEXTURE_2D, 0);

     m_TextureId = textureID;
     return true;
}

int32_t TextureImageOpenGL::GetTextureId()
{
     return m_TextureId;
}

void* TextureImageOpenGL::LoadImageFromAssets(AAssetManager* pAssetManager, const char* filename, int* pFileSize)
{
     *pFileSize = 0;
     int readBytesCount = 0;
     char* buffer = nullptr;

     // open file
     AAsset* pAsset = AAssetManager_open(pAssetManager, filename, AASSET_MODE_UNKNOWN);
     if (pAsset== nullptr)
          return nullptr;

     int fileSize = AAsset_getLength64(pAsset);
     if (fileSize==0)
          return nullptr;

     *pFileSize = fileSize;

     buffer = new char [fileSize];
     if (buffer== nullptr)
          return nullptr;

     // read file
     readBytesCount = AAsset_read(pAsset, buffer, fileSize);
     AAsset_close(pAsset);

     if (readBytesCount==fileSize) // good
          return buffer;

     delete[] buffer;
     return nullptr;
}

void TextureImageOpenGL::Swap24BitColors(void* pColorData, int count)
{
     unsigned char* pBuffer = (unsigned char*)pColorData;
     for (int i=0; i<(count-2); i+=3)
          std::swap(pBuffer[i], pBuffer[i+2]);
}

void TextureImageOpenGL::Bmp24BitUpDownLines(void* pColorData, int width, int height)
{
     int bytesCountPerColor = 3;
     const int bytesCountFor1Line = width * bytesCountPerColor;
     char* pData =(char*) pColorData;
     char* pLine = new char[bytesCountFor1Line];
     int iBottom = 0;
     for (int iTop=0; iTop< height / 2; iTop++)
     {
          iBottom = height-1 - iTop;
          memcpy(pLine, pData+(iTop*bytesCountFor1Line), bytesCountFor1Line);
          memcpy(pData+(iTop*bytesCountFor1Line), pData+(iBottom*bytesCountFor1Line), bytesCountFor1Line);
          memcpy(pData+(iBottom*bytesCountFor1Line), pLine, bytesCountFor1Line);
     }
     delete[] pLine;
}

void TextureImageOpenGL::GetBmpWidthHeight(void* pFileData, int count, int* pWidth, int* pHeight, int* pDataOffset)
{
     const int DATA_OFFSET_OFFSET = 0x000A;
     const int WIDTH_OFFSET = 0x0012;
     const int HEIGHT_OFFSET = 0x0016;

     *pWidth = *(int*)((char*)pFileData + WIDTH_OFFSET);
     *pHeight = *(int*)((char*)pFileData + HEIGHT_OFFSET);
     *pDataOffset = *(int*)((char*)pFileData + DATA_OFFSET_OFFSET);
}

//////////// class BufferPointsOpenGL to create 3d points in video card buffer ///////////////
BufferPointsOpenGL::BufferPointsOpenGL()
{
     m_BufferId = 0;
     m_PointsCount = 0;
     m_PointsModeHowToDraw = 0;
}

BufferPointsOpenGL::~BufferPointsOpenGL()
{
}

bool BufferPointsOpenGL::Create(PosXYZ_TextureXY* pBuffer, int itemsCount, GLuint pointsModeHowToDraw)
{
     m_BufferId = 0;
     m_PointsCount = itemsCount;
     m_PointsModeHowToDraw = pointsModeHowToDraw;

     glGenBuffers(1, &m_BufferId);
     glBindBuffer(GL_ARRAY_BUFFER, m_BufferId);
     glBufferData(GL_ARRAY_BUFFER, sizeof(PosXYZ_TextureXY)*itemsCount, pBuffer, GL_STATIC_DRAW);
     return true;
}

int32_t BufferPointsOpenGL::GetBufferId()
{
     return m_BufferId;
}

GLuint BufferPointsOpenGL::GetPointsModeHowToDraw()
{
     return m_PointsModeHowToDraw;
}

GLuint BufferPointsOpenGL::GetPointsCount()
{
     return m_PointsCount;
}

//////////////////// class ShaderOpenGL ///////////////
ShaderOpenGL::ShaderOpenGL()
{
     m_ShaderId = 0;
     m_SHADER_TEXTURE_parameter_position_index = 0;
     m_SHADER_TEXTURE_parameter_texture_index = 0;
}

ShaderOpenGL::~ShaderOpenGL()
{
     Close();
}

bool ShaderOpenGL::Create()
{
     m_ShaderId = 0;

     const char* vertexShaderStr = R"(
               attribute vec3 aPos;
               attribute vec2 aTexCoord;

               varying vec2 TexCoord;

               void main()
               {
                    gl_Position = vec4(aPos, 1.0);
                    gl_Position.x = gl_Position.x * 2.0 - 1.0; // I use x from [0, 1] in my files. This line converts x from [0, 1] -> openGL standard [-1, 1]
                    gl_Position.y = -(gl_Position.y * 2.0 - 1.0); // I use y from [0, 1] in my files. This line converts y from [0, 1] -> openGL standard [1, -1]
                    TexCoord = vec2(aTexCoord.x, aTexCoord.y);
               }
     )"
;

     const char* fragmentShaderStr = R"(
               precision mediump float;
               varying vec2 TexCoord;

               uniform sampler2D textureGood;
               void main()
               {
                    gl_FragColor = texture2D(textureGood, TexCoord);
               }
     )"
;

     GLuint vertexShader;
     GLuint fragmentShader;
     GLint linked;

     // Load the vertex/fragment shaders
     vertexShader = LoadShader(vertexShaderStr, GL_VERTEX_SHADER);
     fragmentShader = LoadShader(fragmentShaderStr, GL_FRAGMENT_SHADER);

     // Create the program object
     int32_t myGraphicObject = glCreateProgram();
     if(myGraphicObject == 0)
     {
          return false;
     }

     // Attach shaders to program
     glAttachShader(myGraphicObject, vertexShader);
     glAttachShader(myGraphicObject, fragmentShader);

     // Link the program
     glLinkProgram(myGraphicObject);

     m_SHADER_TEXTURE_parameter_position_index = glGetAttribLocation(myGraphicObject, "aPos");
     m_SHADER_TEXTURE_parameter_texture_index = glGetAttribLocation(myGraphicObject, "aTexCoord");

     // Check the link status
     glGetProgramiv(myGraphicObject, GL_LINK_STATUS, &linked);
     if(!linked)
     {
          GLint infoLen = 0;
          glGetProgramiv(myGraphicObject, GL_INFO_LOG_LENGTH, &infoLen);

          if(infoLen > 1)
          {
               char* infoLog = new char[infoLen];
               glGetProgramInfoLog(myGraphicObject, infoLen, NULL, infoLog);
               //LOG_WARN("Error linking program:\n%s\n", infoLog);

               delete[] infoLog;
          }

          glDeleteShader(vertexShader);
          glDeleteShader(fragmentShader);

          glDeleteProgram(myGraphicObject);
          return false;
     }

     glDeleteShader(vertexShader);
     glDeleteShader(fragmentShader);

     m_ShaderId = myGraphicObject;
     return true;
}

void ShaderOpenGL::Close()
{
     if (m_ShaderId!=0)
     {
          glDeleteProgram(m_ShaderId);
          m_ShaderId = 0;
     }
}

GLuint ShaderOpenGL::LoadShader(const char *shaderSrc, GLenum type)
{
     GLuint shader;
     GLint compiled;

     // Create the shader object
     shader = glCreateShader(type);
     if(shader != 0)
     {
          // Load the shader source
          glShaderSource(shader, 1, &shaderSrc, NULL);

          // Compile the shader
          glCompileShader(shader);
          // Check the compile status
          glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);

          if(!compiled)
          {
               GLint infoLen = 0;
               glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);

               if(infoLen > 1)
               {
                    char* infoLog = new char[infoLen];
                    glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
                    //LOG_WARN("Error compiling shader:\n%s\n", infoLog);
                    delete[] infoLog;
               }
               glDeleteShader(shader);
               shader = 0;
          }
     }
     return shader;
}

void ShaderOpenGL::MakeActive()
{
     // Use the program object
     glUseProgram(m_ShaderId);

     glEnableVertexAttribArray(m_SHADER_TEXTURE_parameter_position_index);
     glEnableVertexAttribArray(m_SHADER_TEXTURE_parameter_texture_index);
}

void ShaderOpenGL::Disable()
{
     glDisableVertexAttribArray(m_SHADER_TEXTURE_parameter_position_index);
     glDisableVertexAttribArray(m_SHADER_TEXTURE_parameter_texture_index);
     glUseProgram(0);
}

void ShaderOpenGL::Draw(TextureImageOpenGL& rTextureImageOpenGL, BufferPointsOpenGL& rBufferPointsOpenGL)
{
     glBindTexture(GL_TEXTURE_2D, rTextureImageOpenGL.GetTextureId());

     // data
     glBindBuffer(GL_ARRAY_BUFFER, rBufferPointsOpenGL.GetBufferId());

     // vertex pos and texture coord
     glVertexAttribPointer(m_SHADER_TEXTURE_parameter_position_index,
                              3 /*fields with type float*/, // x,y,z
                              GL_FLOAT,
                              GL_FALSE,
                              sizeof(PosXYZ_TextureXY),
                              (GLvoid*)0
     );

     // texture
     glVertexAttribPointer(m_SHADER_TEXTURE_parameter_texture_index,
                              2 /*fields with type float*/, // texture_x, texture_y
                              GL_FLOAT,
                              GL_FALSE,
                              sizeof(PosXYZ_TextureXY),
                              (GLvoid*)( sizeof(PosXYZ_TextureXY::x) + sizeof(PosXYZ_TextureXY::y) + sizeof(PosXYZ_TextureXY::z) )
     );

     // draw
     glDrawArrays(rBufferPointsOpenGL.GetPointsModeHowToDraw(), 0, rBufferPointsOpenGL.GetPointsCount());
}
На заметку!
Vertex Shader отвечает за преобразование координат.
Fragment Shader принимает координаты текстуры и вычисляет цвет для каждого пикселя.
Шаг 6. Поменяем код в файле CMakeLists.txt
Я подключаю в проект файл texture_buffer_shader.cpp т.е. этот файл будет участвовать в компиляции
  Файл CMakeLists.txt
...

add_library(MyCPlusPlusActivity
          SHARED
          main.cpp
          texture_buffer_shader.cpp
          my_game.cpp)

...
 
← Предыдущая тема
Рисование треугольника с закрашиванием внутри в "Android Native C++ Game" для телефона | Android Studio, Android NDK, OpenGL ES v1, C++
 
Следующая тема →
Как получить файл bmp, расположенный в Assets внутри файла apk? | Android Studio, NDK, C++
 
Ваши Отзывы ... комментарии ...
   
Вашe имя
Ваш комментарий (www ссылки может добавлять только залогиненный пользователь)

  Объявления  
  Объявления  
 
Что такое операционная система Android? Какие номера версий были в Android
Что такое ARM процессоры? | Android
Что такое AndroidX?
Java приложение (для Android телефона) в Android Studio
Почему Android приложения пишутся на Java?
Скачать и установить Android Studio для написания программ для Android телефонов на языке Java, Kotlin
Открываем Android Studio на компьютере (Windows 10)
Создаем новый проект на Java с одной простой Activity в Android Studio (пишем программу для Android телефонов, планшетов) в Windows 10
Компиляция и запуск приложения в Android Studio на компьютере (Windows) в режиме эмулятора Android Device
Запуск приложения Android Studio в отладке на компьютере (Windows) в режиме эмулятора Android Device
Ошибка "error while waiting for device: the emulator process for ..... has terminated" при запуске приложения в Android Studio на компьютере (Windows) в режиме эмулятора Android Device
Ошибка "Error while waiting for device: Illegal char <*> at index 0: *.lock ..." при запуске приложения в Android Studio
Ошибка "AVD is already running ..." при запуске приложения в Android Studio
Ошибка "CMake "3.18.1" was not found in SDK, PATH, or by cmake.dir property" при компиляции проекта в Android Studio
Ошибка "Execution failed for task ":app:compressDebugAssets" при компиляции проекта в Android Studio
Все ошибки при запуске Android приложения
Что такое Android SDK (копия операционной системы Android)? Инсталлирование Android SDK 8.1 в Android Studio ...
Создаем Android виртуальное устройство в Android Studio
Установить HAXM
Activity в Android
Kotlin приложение (для Android телефона) в Android Studio
Скачать и установить Android Studio для написания программ для Android телефонов на языке Java, Kotlin
Создаем новый проект "Empty Views Activity" на Kotlin в Android Studio (пишем программу для Android телефонов, планшетов) в Windows 10
Компиляция и запуск Kotlin приложения в Android Studio на компьютере (Windows) в режиме эмулятора Android Device
Запуск Kotlin приложения в Android Studio в отладке на компьютере (Windows) в режиме эмулятора Android Device
Запуск и отладка Kotlin Android Studio приложения на моем телефоне через USB
Долгое ожидание при запуске Kotlin Android приложения. Вижу сообщение: "I/zygote:Waiting for a blocking GC ProfileSaver"
Создаем Android проект добавляем TextView и показываем значение на телефоне | Android телефон, Android Studio, Kotlin, Windows 10
Копирование данных в классе и объекта. Используем аттрибут @Parcelize и интрефейс Parcelable. | Kotlin | Android Studio
Ошибка "Class is not abstract and does not implement abstract member public abstract fun describeContents(): Int defined in android.os.Parcelable" | Kotlin | Android Studio | @Parcelize | Parcelable
Показываем окно с 2-мя кнопками: yes, no и не надо добавлять никаких resource, layout | Я вызываю функцию AlertDialog в Kotlin | Android Studio
Android Kotlin приложение делает фото на камеру и рисует в приложении | Android Studio | Kotlin
Android Kotlin выбираем фото из галереи и рисуем в приложении | Android Studio | Kotlin ...
getExternalFilesDir - функция, которая возвращает полный путь к внешнему каталогу, в который наше приложение может помещать постоянные файлы | Android Studio, Kotlin
getFilesDir - функция, которая возвращает полный путь к каталогу, в который наше приложение может поместить файлы | Android Studio, Kotlin
Как работать с файлами, media в Android? Что такое content Uri и file path. Отличие getExternalFilesDir и getFilesDir ... | Android Studio, Kotlin
Как сделать переменную в build.gradle файле и передать ее в манифест файл AndroidManifest.xml | Android Studio | Kotlin
Как сделать переменную в build.gradle файле и передать ее в Kotlin файл | Android Studio | Kotlin
Moshi (Преобразование текста json в объект класса) | десериализация на языке Kotlin | Android Studio
Moshi (Преобразование массива json в список объектов) | десериализация на языке Kotlin | Android Studio
Ошибка "Failed to find the generated JsonAdapter class for class com.example.androidkotlinapp1.MyBook" | Exception | Kotlin | Moshi | Android Studio
Ошибка "A problem occurred evaluating project ':app'. Caused by: CustomMessageMissingMethodException: Could not find method kapt() for arguments [com.squareup.moshi:moshi-kotlin-codegen:1.14.0]" | При компиляции Kotlin, Moshi проекта в Android Studio
Jetpack приложение (для Android телефона) в Android Studio | Kotlin
Что такое Jetpack для Android?
Создаем новый проект "Jetpack Compose" на Kotlin в Android Studio (пишем программу для Android телефонов, планшетов) в Windows 10
C++ игра (для Android телефона) в Android Studio | Android NDK, OpenGL ES
Что такое Android NDK для Android телефона? Это C++ библиотека для Android телефона.
Что такое Android OpenGL ES для Android телефона? Это C++ графическая библиотека для Android телефона.
Создаем проект "Android Native C++ Game" для телефона | Android Studio, Android NDK, OpenGL ES, C++
Рисование озера по точкам для 2D игры
Рисую вражеский самолетик как векторная графика в Adobe Illustrator. Беру координаты точек из Adobe Illustrator и добавляю в мою 2D игру на C++ OpenGL
Компиляция и запуск "Android Native C++ Game" в Android Studio на компьютере(Windows) в режиме эмулятора Android Device
Ошибка "[CXX1405] error when building with cmake using CMakeLists.txt: C build system [configure] failed while executing cmake.exe" при компиляции Android Native C++ приложения в Android Studio на компьютере (Windows)
Ошибка "ninja: error: rebuilding 'build.ninja': subcommand failed" при компиляции Android Native C++ приложения в Android Studio на компьютере (Windows)
Рисование треугольника с закрашиванием внутри в "Android Native C++ Game" для телефона | Android Studio, Android NDK, OpenGL ES v1, C++
Загрузка bmp файла из Assets и рисование текстур в "Android Native C++ Game" для телефона | Android Studio, Android NDK, OpenGL ES v2 (shader), C++
Как получить файл bmp, расположенный в Assets внутри файла apk? | Android Studio, NDK, C++
Как использовать альфа-прозрачность при отображении текстуры с помощью OpenGL? | Android Studio, OpenGL ES, NDK, C++
Почему glTexImage2D возвращает ошибку с кодом 1280 ? | Android Studio, OpenGL ES, NDK, C++
Что такое cpp и h файлы в C++? | Android Studio, NDK, C++
Как создать новый файл h и добавить в проект android NDK C++? | Android Studio, NDK, C++
Как создать новый файл cpp и добавить в проект android NDK C++? | Android Studio, NDK, C++, CMakeLists.txt
dynamic_cast в C++ (преобразование указателя в другой тип и проверка валидности во время выполнения) | Android Studio, NDK, C++
std::map<Key, Value> это набор ключей и значений в C++. | Android Studio, NDK, C++
Передаем функцию как параметр в функцию (callback) | C++ | Android Studio, NDK, C++
Как найти событие при повороте дисплея (изменении ориентации) в телефоне Android | Android Studio, NDK, C++
Как обрабатывать события в телефоне Android (создание/завершение события окна, установка фокуса, потеря фокуса, касание в телефоне) | Android Studio, NDK, C++
Создаем подписанный apk файл в Android Studio | Android NDK, OpenGL ES
Google Play Console (для разработчика)
Создаем Google Play account разработчика | Google Play Console
Разработчику в Google Play Console требуется подтвердить личность | Google Play Console
Разработчик в Google Play Console должен подтвердить аккаунт разработчика | Google Play Console
Учетная запись разработчика не используется | Учетная запись разработчика находится под угрозой закрытия | Google Play Console
Скомпилируйте приложение и отправьте его в продакшн в Google Play Console | Мое приложение в Google Play Console
Policy status "App must target Android 15 (API level 35) or higher" | Status "You won't be able to release app updates" | Мое приложение в Google Play Console
Policy status "App must target Android 14 (API level 34) or higher" | Status "You won't be able to release app updates" | Мое приложение в Google Play Console
Создаем приложение в Google Play Console (в опции выбираю что это будет игра) | Моя игра в Google Play Console
Важные параметры: package, applicationId, versionCode, versionName, android:label (в AndroidManifest.xml, build.gradle) чтобы создать тестовую версию для Google Play Console | Моя игра в Google Play Console
Создаем подписанный .aab файл в Android Studio | Моя игра в Google Play Console
Компилируем игру и присылаем на внутреннее тестирование в Google Play Console | Моя игра в Google Play Console
Google автоматически запустил тесты и сделал картинки, отчет как запускается игра на разных марках телефонах | Моя игра в Google Play Console
Как задать Google Play Developer Console вопрос в поддержку?
Google Play Developer Console support feedback
Темы про Google Play Billing & in-app purchase | Google Play Console
Можно использовать (интегрировать) платежи в моей Google игре если я разработчик из Беларуси? | Монетизация в Google Play Console
Как изменить язык Google Play Console? | Google Chrome
Как изменить страну в платежном профиле? | Google Play Console
Как в Google Play посмотреть(открыть) платежную страницу? | Google Play Console

  Ваши вопросы присылайте по почте: info@dir.by  
Яндекс.Метрика