dir.by  
  Search  
Programming, development, testing
Android, Google Play phone, tablet (writing an app, a game)
C++ game (for Android phone) in Android Studio | Android NDK, OpenGL ES
Create a project "Android Native C++ Game" for the phone | Android Studio, Android NDK, OpenGL ES, C++
  Looked at 21804 times       Comments 1  
 Last Comment: (8 June 2023 14:35) Good read...       Write a comment...
 Create a project "Android Native C++ Game" for the phone | Android Studio, Android NDK, OpenGL ES, C++ 
last updated: 18 March 2024
 
What can this project "Android Native C++ Game" do?                  Updated March 17, 2024
This project contains only C++ code and the code is minimal.
Renders the screen 50 times per second using OpenGL
Works on an old tablet, phone with version Android 4 (this version was released in 2011)
The project is very, very simple. Contains 4 files:

main.cpp ... with 150 lines of Android system code (init device, gain focus, kill focus, handle use events like finger touch, move). This file main.cpp is finished and you don't need to edit it (you can edit it if you really want to).
 
graphic.cpp ... with 180 lines of OpenGL code (initialize OpenGL surface, close OpenGL, has implemented class MyPolygon for drawing connected lines with fill color inside). This file graphic.cpp is finished and you don't need to edit it (you can edit it if you really want to).
 
my_game.cpp ... with 90 lines of code: this is indicating the coordinates of my plane, enemy planes at the beginning of the game, indicating the coordinates of trees, a lake. Camera movement. Handling tapping on the screen and moving my plane left, right.
 
my_game_assets.h ... 130 lines: here are only the coordinates of the points and colors for my plane, the enemy plane, the lake, the tree. Vector graphics were drawn in Adobe Illustrator and exported to SVG files, and from SVG files I copied points and colors here.
 
This application uses Android NDK ( this is the C++ system library for Android phone) ... and therefore works very fast
This application uses OpenGL ES ( it is a C++ graphics library for Android phone) ... and therefore draws 2D and 3D graphics very quickly
This project does not use the large Google library Android Games Development Kit ....
This project does not contain Java code.
Step 1. Download the project "Android Native C++ Game"
Download from github.com:
In Google Chrome open github.com/EvgenProjects/AndroidNative_BasicGame
Github project "Android Native C++ Game" for the phone |  Android Studio  Android NDK  OpenGL ES  C++
Github project "Android Native C++ Game" for the phone | Android Studio, Android NDK, OpenGL ES, C++
Step 2. Open the project "Android Native C++ Game" in Android Studio
If you do not have Android Studio installed, then you need to: download and install Android Studio for Windows 10 ...
Open Android Studio
 
Press Open.
Choose the path to the downloaded project:
 
It's been 2 minutes.
The project is fully loaded:
Step 3. Launching the project
 
[1] Select Android Virtual Appliance
   I'm using "My Nexus 5 API 27" created his own virtual device Android ...

[2] Launching the project
   To start, click on the menu RunRun 'app'.

[3] Select the tab Emulator
   To see the phone emulator

[4] We look at the result inside the phone emulator.
Step 4. Look at the project files and explanation                  Updated March 17, 2024
D:\ndk-samples-master\native-activity
        build.gradle
        gradle.properties
        gradlew
        gradlew.bat
        settings.gradle
        gradle
                wrapper
                        gradle-wrapper.jar
                        gradle-wrapper.properties
        app
                build.gradle
                src
                        main
                                AndroidManifest.xml
                                cpp
                                        CMakeLists.txt
                                        main.cpp
                                        graphic.cpp
                                        graphic.h
                                        my_game.cpp
                                        my_game.h
                                        my_game_assets.h
                                res
                                        mipmap-hdpi
                                                ic_launcher.png
                                        mipmap-mdpi
                                                ic_launcher.png
                                        mipmap-xhdpi
                                                ic_launcher.png
                                        mipmap-xxhdpi
                                                ic_launcher.png
                                        values
                                                strings.xml
 
←       
←       
←       
←        DO NOT EDIT these gradle files
←        These gradle files are used to build the project in Android
←        These gradle files are the same for all projects
←        
←       
←       
 
  build.gradle         file to specify the version Android. This file can be changed
 

  AndroidManifest.xml     file in which we specify Activity in the project. This file can be changed
 
  CMakeLists.txt         In this file, we describe our cpp files for compilation. This file can be changed
  main.cpp                   In this file, we write code in the language C++. This file can be changed
  graphic.cpp            In this file, we write code in the language C++. This file can be changed
  graphic.h            In this file, we write code in the language C++. This file can be changed
  my_game.cpp            In this file, we write code in the language C++. This file can be changed
  my_game.h              In this file, we write code in the language C++. This file can be changed
  my_game_assets.h           In this file, we write code in the language C++. This file can be changed
  

   ic_launcher.png
  
   ic_launcher.png
  
   ic_launcher.png
 
   ic_launcher.png
 
  strings.xml contains the text "Android Native C++ Game"     

Updated March 17, 2024
File build.gradle
apply plugin: 'com.android.application'

android {
     compileSdkVersion 30
     ndkVersion '22.1.7171670'

     defaultConfig {
          applicationId = 'com.game.my_native_activity'
          minSdkVersion 14
          targetSdkVersion 31
          externalNativeBuild {
               cmake {
                    arguments '-DANDROID_STL=c++_static'
               }
          }
     }
     buildTypes {
          release {
               minifyEnabled false
               proguardFiles getDefaultProguardFile('proguard-android.txt'),
                         'proguard-rules.pro'
          }
     }
     externalNativeBuild {
          cmake {
               version '3.18.1'
               path 'src/main/cpp/CMakeLists.txt'
          }
     }
}

dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
}
Description:
 
 
  
 
 
 
 
 
minSdkVersion 14   specified the minimum version Android SDK.
Android SDK is an emulator (copy) of the operating system Android.
Android SDK 14 corresponds to the operating system Android 4 (released in 2011)
That is, in 2011 I bought a tablet.
The tablet had the operating system Android 4.
I specified minSdkVersion 14 in this file, which means that this program should work on my ancient tablet.

 
 
 
 
 
externalNativeBuild
    path 'src/main/cpp/CMakeLists.txt'   indicated that we are using CMakeLists.txt
CMakeLists.txt is used to compile cpp files.
File AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.game.my_native_activity"
     android:versionCode="1"
     android:versionName="1.0">

     <application
 
         android:allowBackup="false"
          android:fullBackupContent="false"
          android:icon="@mipmap/ic_launcher"
          android:label="@string/app_name"
          android:hasCode="true">

          <!-- activity -->
          <activity
               android:name="android.app.NativeActivity"
               android:configChanges="orientation|keyboardHidden"
               android:exported="true">

               <!-- activity will be extended with C++ library: MyCPlusPlusActivity -->
               <meta-data
                    android:name="android.app.lib_name"
                    android:value="MyCPlusPlusActivity"
               />

               <intent-filter>
                    <action android:name="android.intent.action.MAIN" ></action>
                    <category android:name="android.intent.category.LAUNCHER"></category>
               </intent-filter>
 
          </activity>
     </application>

</manifest>
Description:
 
 


 

 


android:icon="@mipmap/ic_launcher"       Icon for the application. Taken from resources
android:label="@string/app_name"        The name of the application. Taken from resources
 
<activity                     We describe the activity. Activity is a screen
android:name="android.app.NativeActivity"
android.app.NativeActivity is a reserved word, that is, the name of the activity from the Android library.
If you do not use NDK, then the name of the activity will be the name of our Java class. Like this: android:name=".MainActivity". And MainActivity is a Java class.

<meta-data
android:name="android.app.lib_name"    android.app.lib_name this means that below we will indicate the name C++ of the library for the activity
 
android:value="MyCPlusPlusActivity"    Name C++ of the library for the activity
/>

</activity>
File CMakeLists.txt
#
# Copyright (C) The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

cmake_minimum_required(VERSION 3.4.1)

# build native_app_glue as a static lib
set(${CMAKE_C_FLAGS}, "${CMAKE_C_FLAGS}")
add_library(native_app_glue STATIC
     ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)

# now build app's shared lib
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall -Werror")

# Export ANativeActivity_onCreate(),
# Refer to: https://github.com/android-ndk/ndk/issues/381.
set(CMAKE_SHARED_LINKER_FLAGS
     "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")

add_library(MyCPlusPlusActivity
          SHARED
          main.cpp
          graphic.cpp
          my_game.cpp)
 
 
 
target_include_directories(MyCPlusPlusActivity PRIVATE
     ${ANDROID_NDK}/sources/android/native_app_glue)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  
 
 
 
# add lib dependencies
target_link_libraries(MyCPlusPlusActivity
     android
     native_app_glue
     EGL
     GLESv1_CM
     log)
Description:
 
 
 
  
  
  
  

  
 
 
 
 

 
 

 
 
 
 
 
 
 
 
 
 
 
add_library(MyCPlusPlusActivity    Compilation will create a library (file) named MyCPlusPlusActivity
main.cpp         added your own file
graphic.cpp         added your own file
my_game.cpp         added your own file
 
 
 
target_include_directories( MyCPlusPlusActivity    In the Android Studio project, the files from the ${ANDROID_NDK}/sources/android/native_app_glue folder will automatically appear:

 
 
target_link_libraries(MyCPlusPlusActivity    Add system libraries:
android
native_app_glue
EGL
GLESv1_CM        This is OpenGL ES 1.0
log
 
File main.cpp
#include <android_native_app_glue.h>
#include <android/sensor.h>
#include <cassert>

#include "my_game.h"

// my settings
class MySettings
{
     // fields
     public: constexpr static const float TURN_TIMES_IN_SECONDS = 0.02f; // 50 times per second
     public: bool m_IsPause = false;
     public: MyGame MyGame;

     // local variables
     private: struct timespec _currentTime;
     private: struct timespec _lastTime;

     // constructor
     public: MySettings(AAssetManager* pAssetManager) : MyGame(pAssetManager)
     {
          _currentTime.tv_sec = 0;
          _currentTime.tv_nsec = 0;
          _lastTime.tv_sec = 0;
          _lastTime.tv_nsec = 0;
     }

     public: bool IsNextGameTick()
     {
          // get current time
          _currentTime.tv_sec = _currentTime.tv_nsec = 0;
          clock_gettime(CLOCK_MONOTONIC, &_currentTime);

          // is ellapsed time
          if ( ((_currentTime.tv_sec - _lastTime.tv_sec) + (_currentTime.tv_nsec - _lastTime.tv_nsec) / 1000000000.f) >= TURN_TIMES_IN_SECONDS )
          {
               // set last time
               _lastTime.tv_sec = _currentTime.tv_sec;
               _lastTime.tv_nsec = _currentTime.tv_nsec;
               return true;
          }
          return false;
     }
};

/**
* touch events:
*/

int32_t engine_handle_input(struct android_app* app, AInputEvent* pEvent)
{
     MySettings* pMySettings = (MySettings*)app->userData;

     bool isMotion = AInputEvent_getType(pEvent) == AINPUT_EVENT_TYPE_MOTION;
     bool isTouchDown = (AMOTION_EVENT_ACTION_MASK & AMotionEvent_getAction(pEvent)) == AMOTION_EVENT_ACTION_DOWN;
     bool isTouchUp = (AMOTION_EVENT_ACTION_MASK & AMotionEvent_getAction(pEvent)) == AMOTION_EVENT_ACTION_UP;
     float xDevicePixel = AMotionEvent_getX(pEvent, 0);
     float yDevicePixel = AMotionEvent_getY(pEvent, 0);

     return pMySettings->MyGame.OnHandleTouch(pEvent, isMotion, isTouchDown, isTouchUp, xDevicePixel, yDevicePixel);
}

/**
* application events: application on focus, lost focus, window create, window close
*/

void engine_handle_cmd(struct android_app* app, int32_t cmd)
{
     MySettings* pMySettings = (MySettings*)app->userData;

     switch (cmd) {
          case APP_CMD_SAVE_STATE:
               break;

          case APP_CMD_INIT_WINDOW:
               pMySettings->MyGame.OnCreateWindow(app->window);
               break;

          case APP_CMD_TERM_WINDOW:
               pMySettings->MyGame.OnKillWindow();
               break;

          case APP_CMD_GAINED_FOCUS:
          {
               pMySettings->m_IsPause = false;
               pMySettings->MyGame.OnActiveFocus();
               break;
          }

          case APP_CMD_LOST_FOCUS:
          {
               pMySettings->m_IsPause = true;
               pMySettings->MyGame.OnLostFocus();
               break;
          }

          default:
               break;
     }
}

/**
* This is the main entry point of a native application that is using android_native_app_glue.
* It runs in its own thread, with its own event loop for receiving input events and draw scene.
*/

void android_main(struct android_app* pAndroidApp)
{
     MySettings mySettings(pAndroidApp->activity->assetManager);

     pAndroidApp->userData = &mySettings;
     pAndroidApp->onAppCmd = engine_handle_cmd;
     pAndroidApp->onInputEvent = engine_handle_input;

     // events.
     int ident;
     int events;
     struct android_poll_source* source;

     // loop waiting for stuff to do.
     while (true)
     {
          // If -1, we will block forever waiting for events.
          // If 0, we loop until all events are read, then continue to draw the next frame of animation.
          if ((ident = ALooper_pollOnce(0 /* -1 0 */, nullptr, &events,(void**)&source)) >= 0)
          {
               // Process this event.
               if (source != nullptr) {
                    source->process(pAndroidApp, source);
               }

               // stop application
               if (pAndroidApp->destroyRequested != 0)
               {
                    mySettings.MyGame.OnKillWindow();
                    return;
               }
          }

          if (!mySettings.m_IsPause)
          {
               // draw scene
               mySettings.MyGame.OnDraw();

               // next tick
               if (mySettings.IsNextGameTick())
               {
                    mySettings.MyGame.OnNextTick();
               }
          }
     }
}
Description:

In this file, we process phone events, draw, recalculate the next move 50 times per second.

This file contains C++ methods and can be modified:

engine_handle_input(...)                handle touch events

engine_handle_cmd(...)                handle application events: application on focus, lost focus, window create, window close

android_main(...)                entry point when app is run
File my_game.cpp
#include <android/native_window.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include "my_game.h"
#include "my_game_assets.h"

MyGame::MyGame(AAssetManager* pAssetManager)
{
     m_pAssetManager = pAssetManager;
     m_isButtonPressed = false;
     m_2DcameraPosition.x = 0;
     m_2DcameraPosition.y = 0;
}

void MyGame::OnActiveFocus()
{
}

void MyGame::OnLostFocus()
{
}

bool MyGame::OnHandleTouch(AInputEvent* pEvent, bool isMotion, bool isTouchDown, bool isTouchUp, float xDevicePixel, float yDevicePixel)
{
     if (isMotion && isTouchDown)
     {
          m_isButtonPressed = true;
          m_ptInDevicePixelWhenTouched = XY(xDevicePixel, yDevicePixel);
          return true;
     }
     else if (isMotion && isTouchUp)
     {
          m_isButtonPressed = false;
          return true;
     }
     return false; // event not handled
}

void MyGame::OnNextTick()
{
     m_2DcameraPosition.y -= 0.008;

     for (int i=0; i<m_arrEnemyAirPlane.size(); i++)
          m_arrEnemyAirPlane[i].MoveByOffset(0, -0.004);

     if (m_isButtonPressed)
     {
          if (m_ptInDevicePixelWhenTouched.x < m_Graphic.GetWidth()/2.0f)
               m_MyAirPlane.MoveByOffset(-0.008, 0);
          else
               m_MyAirPlane.MoveByOffset(0.008, 0);
     }
}

void MyGame::OnDraw()
{
     m_Graphic.DrawBackground(0.72f, 0.87f, 0.55f, 1);

     // no move
     glLoadIdentity();
     glTranslatef(0, 0, 0);
     m_MyAirPlane.Draw();

     // move camera
     glLoadIdentity();
     glTranslatef(m_2DcameraPosition.x, m_2DcameraPosition.y, 0);

     for (int i=0; i<m_arrEnemyAirPlane.size(); i++)
          m_arrEnemyAirPlane[i].Draw();

     for (int i=0; i<m_arrBackgroundObject.size(); i++)
          m_arrBackgroundObject[i].Draw();

     m_Graphic.DrawGraphicEnd();
}

void MyGame::OnKillWindow()
{
     m_Graphic.CloseGraphic();
}

void MyGame::OnCreateWindow(ANativeWindow *pWindow)
{
     m_Graphic.InitGraphic(pWindow);

     m_2DcameraPosition.x = 0;
     m_2DcameraPosition.y = 0;

     m_MyAirPlane = TEMPLATE_MyAirPlane.CreateByTemplate(XY(0.5, 0.8), 0.2, 0.1);
     m_arrEnemyAirPlane.push_back(TEMPLATE_EnemyAirPlane.CreateByTemplate(XY(0.1, -1.4), 0.2, 0.1));
     m_arrEnemyAirPlane.push_back(TEMPLATE_EnemyAirPlane.CreateByTemplate(XY(0.15, -1.8), 0.2, 0.1));

     m_arrBackgroundObject.push_back(TEMPLATE_Lake.CreateByTemplate(XY(0.4, -1.3), 0.5, 0.5));
     m_arrBackgroundObject.push_back(TEMPLATE_Tree.CreateByTemplate(XY(0.88, -0.9), 0.08, 0.06));
     m_arrBackgroundObject.push_back(TEMPLATE_Tree.CreateByTemplate(XY(0.9, -1.2), 0.08, 0.06));
     m_arrBackgroundObject.push_back(TEMPLATE_Tree.CreateByTemplate(XY(0.3, -1.3), 0.08, 0.06));
}
Description:

In this file, we have to do all the logic.
Now in this file I create objects: my plane, enemy planes, trees, a lake.

This file contains C++ methods and they need to be changed:

MyGame::MyGame(AAssetManager* pAssetManager)
{
...
}

void MyGame::OnActiveFocus()
{
...
}

void MyGame::OnLostFocus()
{
...
}

bool MyGame::OnHandleTouch(AInputEvent* pEvent)
{
...
}

void MyGame::OnNextTick()
{
...
}

void MyGame::OnDraw()
{
...
}

bool MyGame::OnKillWindow()
{
...
}

void MyGame::OnCreateWindow(ANativeWindow* pWindow)
{
...
}
File my_game.h
#include <android/input.h>
#include <android/asset_manager.h>
#include <EGL/egl.h>
#include "graphic.h"

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

     // fields
     protected: AAssetManager* m_pAssetManager;
     protected: MyGraphic m_Graphic;
     protected: bool m_isButtonPressed;
     protected: XY m_ptInDevicePixelWhenTouched;
     protected: float m_moveStep;

     // my game
     protected: MyObject m_MyAirPlane;
     protected: std::vector<MyObject> m_arrEnemyAirPlane;
     protected: std::vector<MyObject> m_arrBackgroundObject;
     protected: XY m_2DcameraPosition;

     // events
     public: void OnActiveFocus();
     public: void OnLostFocus();
     public: bool OnHandleTouch(AInputEvent* pEvent, bool isMotion, bool isTouchDown, bool isTouchUp, float xDevicePixel, float yDevicePixel);
     public: void OnNextTick();
     public: void OnCreateWindow(ANativeWindow* pWindow);
     public: void OnKillWindow();
     public: void OnDraw();
};
File my_game_assets.h
#include <EGL/egl.h>

#define colorBlue RGBA{0.0f, 0.0f, 0.7f, 0.8f}
#define colorLightBlue RGBA{0.0f, 0.0f, 0.5f, 0.7f}
#define colorWhite RGBA{0.9f, 0.9f, 0.9f, 1.0f}
#define colorVeryLightBlue RGBA{0.3f, 0.4f, 0.8f, 0.7f}

MyObject TEMPLATE_Lake = MyObject({

MyPolygon(GL_TRIANGLE_FAN, { // lake (points from Adobe Illustrator)
     {XY(50,50), colorLightBlue}, // center point
     {XY(43,0), colorBlue}, // first point
     {XY(68,2), colorBlue},
     {XY(85,10), colorBlue},
     {XY(94,23), colorBlue},
     {XY(100,36), colorBlue},
     {XY(100,64), colorBlue},
     {XY(84,88), colorBlue},
     {XY(59,100), colorBlue},
     {XY(41,100), colorBlue},
     {XY(19,94), colorBlue},
     {XY(4,75), colorBlue},
     {XY(1,50), colorBlue},
     {XY(5,27), colorBlue},
     {XY(14,10), colorBlue},
     {XY(43,0), colorBlue}, // first point
}),

});

MyObject TEMPLATE_MyAirPlane = MyObject({

     MyPolygon(GL_TRIANGLE_FAN, { // cabin (points from Adobe Illustrator)
          {XY(50, 14), colorLightBlue}, // center point
          {XY(48, 6), colorBlue}, // first point
          {XY(53, 6), colorBlue},
          {XY(56, 10), colorBlue},
          {XY(56, 20), colorBlue},
          {XY(44, 20), colorBlue},
          {XY(44, 10), colorBlue},
          {XY(48, 6), colorBlue}, // first point
     }),

     MyPolygon(GL_TRIANGLE_FAN, { // body (points from Adobe Illustrator)
          {XY(50,50), colorVeryLightBlue}, // center point
          {XY(41,10), colorVeryLightBlue}, // first point
          {XY(47,4), colorVeryLightBlue},
          {XY(54,4), colorVeryLightBlue},
          {XY(59,10), colorVeryLightBlue},
          {XY(55,93), colorWhite},
          {XY(45,93), colorWhite},
          {XY(41,10), colorVeryLightBlue}, // first point
     }),

     MyPolygon(GL_TRIANGLE_FAN, { // front wing (points from Adobe Illustrator)
          {XY(50,40), colorWhite}, // center point
          {XY(2,30), colorVeryLightBlue}, // first point
          {XY(98,30), colorVeryLightBlue},
          {XY(98,43), colorWhite},
          {XY(70,47), colorWhite},
          {XY(29, 47), colorWhite},
          {XY(2,43), colorWhite},
          {XY(2,30), colorVeryLightBlue}, // first point
     }),

     MyPolygon(GL_TRIANGLE_FAN, { // back wing (points from Adobe Illustrator)
          {XY(50,84), colorWhite}, // center point
          {XY(34,80), colorVeryLightBlue}, // first point
          {XY(66,80), colorVeryLightBlue},
          {XY(66,88), colorWhite},
          {XY(34,88), colorWhite},
          {XY(34,80), colorVeryLightBlue}, // first point
     }),
});

MyObject TEMPLATE_EnemyAirPlane = MyObject({

     // Cabin
     MyPolygon(GL_TRIANGLE_FAN, "#D10000", XY(50, 79),
"45.928,71.216 53.928,71.216 54.72,77.501 55.047,80.93 53.948,84.656 45.948,84.656 44.733,81.084 45.011,77.667"),

     // Gun_right_on_wing
     MyPolygon(GL_TRIANGLE_FAN, "#726658", XY(75, 75),
"72.636,71.216 72.636,77.438 79.303,77.438 79.303,71.344 "),

     // Gun_right_on_wing
     MyPolygon(GL_TRIANGLE_FAN, "#726658", XY(22, 75),
"18.386,71.216 18.386,77.438 25.053,77.438 25.053,71.344"),

     // Wing_back_right
     MyPolygon(GL_TRIANGLE_FAN, "#D10000", XY(60, 13),
"52.594,7.364 56,7.364 56,4.958 60.656,4.958 60.656,6.161 66.094,6.161 68.844,9.989 68.844,15.958 65.969,18.896 53.656,19.864"),

     // Wing_back_left
     MyPolygon(GL_TRIANGLE_FAN, "#D10000", XY(40, 13),
"47.219,7.208 44.052,7.208 44.052,4.375 38.719,4.375 38.719,5.792 34.886,5.792 30.886,9.708 30.886,15.542 32.219,18.542 46.552,20.042"),

     // Body
     MyPolygon(GL_TRIANGLE_FAN, "#726658", XY(50, 50),
"46.511,4.959 48.886,2.875 50.886,2.875 53.323,4.875 54.011,15.688 54.636,24.563"
" 55.636,44.75 56.448,51.875 56.948,69.5 58.011,71.125 58.011,78.813 59.073,80.813 59.073,85.375 57.323,87.375 56.886,89.563"
" 42.886,89.563 42.386,87.531 40.604,85.375 40.604,80.813 41.698,79.209 41.714,70.969 42.636,69.126 43.481,51.883 44.167,44.656"
" 44.979,24.75 45.677,16"),

     // BlackBody
     MyPolygon(GL_TRIANGLE_FAN, "#414042", XY(50, 60),
"38.698,75.25 41.448,77.438 58.011,77.438 60.261,75.625 59.636,49.125 56.323,46.219 43.448,46.219 39.698,49.125"),

     // Wings_Front
     MyPolygon(GL_TRIANGLE_FAN, "#D10000", XY(50, 60),
          "41.802,48.792 5.802,54.209 2.302,58.125 2.302,65.959 5.469,71.292"
                    " 37.886,75.042 61.136,75.042 95.053,70.959 98.219,67.459 98.219,59.709 94.469,53.959 58.553,48.792"),

     // Propeller_center
     MyPolygon(GL_TRIANGLE_FAN, "#414042", XY(50, 92),
          "47.386,88.375 47.386,94.375 49.479,97.125 50.386,97.125 51.995,94.281 51.995,88.375"),

     // Propeller_left
     MyPolygon(GL_TRIANGLE_FAN, "#414042", XY(40, 93),
          "47.823,92.75 31.636,92.75 31.636,93.938 33.636,95.75 40.604,95.75 45.261,93.688 47.823,93.625"),

     // Propeller_right
     MyPolygon(GL_TRIANGLE_FAN, "#414042", XY(61, 93),
          "51.636,93.688 67.823,93.688 67.823,92.5 65.823,90.688 58.854,90.688 54.198,92.75 51.636,92.813"),
});

MyObject TEMPLATE_Tree = MyObject({

     // Body
     MyPolygon(GL_TRIANGLE_FAN, "#7E4E35", XY(50, 83),
          "43.145,67.725 55.25,67.725 56.729,98.876 40.25,98.876 "),

     // Leaves
     MyPolygon(GL_TRIANGLE_FAN, "#619E5B", XY(52, 35),
          "8.187,21.838 7.687,18.922 8.52,15.797 12.104,12.547 16.937,11.047 17.979,8.755 "
                    " 20.02,6.38 22.687,4.63 26.604,4.213 28.729,3.047 31.437,2.213 34.687,2.213 37.937,3.213 40.104,4.838 43.187,3.463 46.979,2.213 "
                    " 49.854,2.713 53.813,4.963 56.188,3.63 59.979,2.422 63.229,2.713 66.563,4.255 68.938,6.63 69.688,9.922 73.354,9.963 "
                    " 76.729,11.005 79.563,12.755 81.646,15.797 84.729,15.922 87.438,16.797 90.063,18.505 91.896,20.088 93.646,23.38 93.188,27.547 "
                    " 94.479,29.463 96.938,31.255 97.813,32.713 98.396,35.506 98.188,37.756 96.063,41.006 96.813,43.297 97.104,45.963 96.271,47.797 "
                    " 93.688,49.962 91.146,50.837 89.479,52.838 87.479,54.129 86.979,55.129 85.771,57.088 83.854,59.297 79.938,60.172 79.313,61.963 "
                    " 77.438,63.588 76.646,65.547 75.188,67.588 72.479,69.254 70.146,69.879 68.563,70.797 64.521,71.504 60.979,70.422 57.688,72.004 "
                    " 54.313,73.213 52.396,73.213 39.813,73.213 32.771,69.547 31.438,66.172 25.063,65.547 22.021,62.754 18.896,59.588 15.313,58.504 "
                    " 12.688,54.422 12.438,49.13 8.854,47.756 3.896,43.422 3.604,39.172 6.271,35.463 2.854,33.005 1.604,29.505 3.646,24.588 "),
});
File graphic.cpp
#include <android/native_window.h>
#include <EGL/egl.h>
#include <GLES/gl.h>
#include <GLES2/gl2.h>
#include <string>
#include <sstream>
#include <iostream>
#include "graphic.h"

MyGraphic::MyGraphic()
{
     m_Width = 0;
     m_Height = 0;
     m_isGraphicInited = false;
}

void MyGraphic::DrawBackground(float red, float green, float blue, float alpha)
{
     if (m_Display == EGL_NO_DISPLAY || m_Surface == EGL_NO_SURFACE || m_Context == EGL_NO_CONTEXT)
          return;

     glClearColor(red, green, blue, alpha);
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

void MyGraphic::DrawGraphicEnd()
{
     if (m_Display == EGL_NO_DISPLAY || m_Surface == EGL_NO_SURFACE || m_Context == EGL_NO_CONTEXT)
          return;

     eglSwapBuffers(m_Display, m_Surface);
}

void MyGraphic::CreateSurfaceFromWindow(ANativeWindow* pWindow)
{
     const EGLint attribs[] = {EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                                   EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
                                   EGL_BLUE_SIZE, 8,
                                   EGL_GREEN_SIZE, 8,
                                   EGL_RED_SIZE, 8,
                                   EGL_NONE};
     EGLint format;
     EGLint numConfigs;

     eglChooseConfig(m_Display, attribs, &m_configOpenGL, 1, &numConfigs);

     eglGetConfigAttrib(m_Display, m_configOpenGL, EGL_NATIVE_VISUAL_ID, &format);

     m_Surface = eglCreateWindowSurface(m_Display, m_configOpenGL, pWindow, NULL);
}

void MyGraphic::InitGraphic(ANativeWindow* pWindow)
{
     if (m_isGraphicInited)
     {
          CreateSurfaceFromWindow(pWindow);
          eglMakeCurrent(m_Display, m_Surface, m_Surface, m_Context);
          return;
     }

     // init Display
     m_Display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     eglInitialize(m_Display, nullptr, nullptr);

     // init Surface
     CreateSurfaceFromWindow(pWindow);

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

     if (eglMakeCurrent(m_Display, m_Surface, m_Surface, m_Context) == EGL_FALSE)
          return;

     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
     //glEnable(GL_CULL_FACE);
     glEnable(GL_DEPTH_TEST);
     glEnable(GL_TEXTURE_2D);

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

     // enable draw lines and colors
     glEnableClientState(GL_VERTEX_ARRAY);// allow to use glVertexPointer
     glEnableClientState(GL_COLOR_ARRAY); // allow to use glColorPointer

     m_isGraphicInited = true;
}

void MyGraphic::CloseGraphic()
{
     if (m_Display != EGL_NO_DISPLAY)
     {
          eglMakeCurrent(m_Display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);

          if (m_Context != EGL_NO_CONTEXT) {
               eglDestroyContext(m_Display, m_Context);
          }

          if (m_Surface != EGL_NO_SURFACE) {
               eglDestroySurface(m_Display, m_Surface);
          }

          eglTerminate(m_Display);
     }

     m_Display = EGL_NO_DISPLAY;
     m_Context = EGL_NO_CONTEXT;
     m_Surface = EGL_NO_SURFACE;
}

// my polygon
MyPolygon::MyPolygon()
{
     m_DrawMode = 0;
}

MyPolygon::MyPolygon(int drawMode, std::vector<XYZ_RGBA> arrPoint)
{
     m_DrawMode = drawMode;
     for (int i=0; i<arrPoint.size(); i++)
          m_arrPositionColor.push_back(arrPoint[i]);
}

MyPolygon::MyPolygon(int drawMode, const char* textColorRGB, XY centerPoint, const char* textPoints)
{
     m_DrawMode = drawMode;

     // convert textColorRGB = "#BE1E2D" -> r(0..1), g(0..1), b(0..1)
     RGBA color;
     std::string stringColorRGB = textColorRGB;
     int hexMode = 16;
     color.red = strtol(stringColorRGB.substr(1, 2).c_str(), NULL, hexMode);
     color.red /= 255.0f;

     color.green = strtol(stringColorRGB.substr(3, 2).c_str(), NULL, hexMode);
     color.green /= 255.0f;

     color.blue = strtol(stringColorRGB.substr(5, 2).c_str(), NULL, hexMode);
     color.blue /= 255.0f;

     color.alpha = 1; // no alpha

     // split string by space
     std::string stringPoints = textPoints;
     std::istringstream f(stringPoints);
     std::string textPoint;
     while (std::getline(f, textPoint, ' '))
     {
          int pos = std::string(textPoint).find(',');
          XY position;
          position.x = atof(textPoint.substr(0, pos).c_str());
          position.y = atof(textPoint.substr(pos+1).c_str());

          m_arrPositionColor.push_back(XYZ_RGBA(position, color));
     }

     // add first point to end
     m_arrPositionColor.push_back(m_arrPositionColor[0]);

     // add center point at begin
     m_arrPositionColor.insert(m_arrPositionColor.begin(), XYZ_RGBA(centerPoint, color));
}

void MyPolygon::Draw()
{
     int countOfPointsToDraw = m_arrPositionColor.size();

     // point (x,y,z)
     glVertexPointer(3, // it is count of fields: x,y,z
                         GL_FLOAT,
                         sizeof(XYZ_RGBA),
                         (GLvoid*)m_arrPositionColor.data()
     );

     // color (r,g,b,alpha)
     glColorPointer(4, // it is count of fields: red,green,blue, alpha
                    GL_FLOAT,
                    sizeof(XYZ_RGBA),
                    (GLvoid*) ((char*)m_arrPositionColor.data()+sizeof(XYZ))
     );

     glDrawArrays(m_DrawMode, 0 /*first index to draw*/, countOfPointsToDraw);
}

void MyPolygon::MoveByOffset(float xOffset, float yOffset)
{
     for (int i=0; i<m_arrPositionColor.size(); i++) {
          m_arrPositionColor[i].position.x += xOffset;
          m_arrPositionColor[i].position.y += yOffset;
     }
}

/////////
MyObject::MyObject()
{}

MyObject::MyObject(std::vector<MyPolygon> arrPolygon)
{
     for (int i=0; i<arrPolygon.size(); i++)
          m_arrPolygon.push_back(arrPolygon[i]);
}

void MyObject::AddPolygon(MyPolygon myPolygon)
{
     m_arrPolygon.push_back(myPolygon);
}

void MyObject::Draw()
{
     for (int i=0; i<m_arrPolygon.size(); i++)
          m_arrPolygon[i].Draw();
}

void MyObject::MoveByOffset(float xOffset, float yOffset)
{
     for (int i=0; i<m_arrPolygon.size(); i++)
          m_arrPolygon[i].MoveByOffset(xOffset, yOffset);
}

MyObject MyObject::CreateByTemplate(XY realPos, float realWidth, float realHeight)
{
     MyObject resultObject;

     float minX = 0, maxX = 0;
     float minY = 0, maxY = 0;
     for (int iPolygon=0; iPolygon<m_arrPolygon.size(); iPolygon++)
     {
          MyPolygon myPolygon = m_arrPolygon[iPolygon];
          for (int i=0; i<myPolygon.ItemsCount(); i++)
          {
               XYZ_RGBA& rItem = myPolygon.GetItem(i);
               if (rItem.position.x<minX)
                    minX = rItem.position.x;
               if (rItem.position.x>maxX)
                    maxX = rItem.position.x;
               if (rItem.position.x<minY)
                    minY = rItem.position.y;
               if (rItem.position.x>maxY)
                    maxY = rItem.position.y;
          }
     }
     float imgWidth = maxX-minX;
     if (imgWidth<=0)
          return resultObject;

     float imgHeight = maxY-minY;
     if (imgHeight<=0)
          return resultObject;

     for (int iPolygon=0; iPolygon<m_arrPolygon.size(); iPolygon++)
     {
          MyPolygon myPolygon = m_arrPolygon[iPolygon];

          // convert each point
          for (int i=0; i<myPolygon.ItemsCount(); i++)
          {
               XYZ_RGBA& rItem = myPolygon.GetItem(i);
               XY pt = XY (
                         realPos.x + realWidth * rItem.position.x / imgWidth,
                         realPos.y + realHeight * rItem.position.y / imgHeight);

               // convert from 0..1 to -1 ... 1
               rItem.position.x = pt.x*2.f-1.f;
               rItem.position.y = 2.f*(1.f-pt.y)-1.f;
          }
          resultObject.AddPolygon(myPolygon);
     }
     return resultObject;
}
Description:

Only in this file OpenGL are the graphics.

In the MyGraphic class, the graphics are initialized OpenGL.

In the MyPolygon class, draw a polygon by points and paint inside.

The MyObject class contains the MyPolygon collection. For example, when I create an airplane, I create a MyObject. An airplane contains a wing is one polygon, a body is another polygon, a tail is another polygon.
File graphic.h
#include <android/input.h>
#include <android/asset_manager.h>
#include <GLES/gl.h>
#include <vector>

struct RGBA
{
     GLfloat red; // [0...1]
     GLfloat green; // [0...1]
     GLfloat blue; // [0...1]
     GLfloat alpha; // [0...1]
};

struct XYZ
{
     GLfloat x;
     GLfloat y;
     GLfloat z;
     XYZ(float x=0, float y=0, float z=0) { this->x=x; this->y=y; this->z=z;}
};

struct XY
{
     float x;
     float y;
     XY(float x=0, float y=0) { this->x=x; this->y=y; }
};


struct XYZ_RGBA
{
     XYZ position;
     RGBA color;
     XYZ_RGBA(XY pos, RGBA color, GLfloat z=0) { this->position.x=pos.x; this->position.y=pos.y; this->position.z=z; this->color=color; }
     XYZ_RGBA(XYZ position, RGBA color) { this->position=position; this->color=color; }
};

class MyGraphic
{
     // constructor
     public: MyGraphic();

     // 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;
     private: bool m_isGraphicInited = false;
     protected: int32_t m_Width;
     protected: int32_t m_Height;

     // OpenGL private
     private: void CreateSurfaceFromWindow(ANativeWindow* pWindow);

     // OpenGL
     public: void InitGraphic(ANativeWindow* pWindow);
     public: void CloseGraphic();
     public: void DrawBackground(float red, float green, float blue, float alpha);
     public: void DrawGraphicEnd();
     int GetWidth(){ return m_Width; }
     int GetHeight(){ return m_Height; }
};

class MyPolygon
{
     public: MyPolygon();
     public: MyPolygon(int drawMode, std::vector<XYZ_RGBA> arrPoint);
     MyPolygon(int drawMode, const char* textColorRGB, XY centerPoint, const char* textPoints);

     public: void Draw();
     public: void MoveByOffset(float xOffset, float yOffset);
     public: int ItemsCount() {return m_arrPositionColor.size();}
     public: XYZ_RGBA& GetItem(int i) {return m_arrPositionColor[i];}

     // points
     protected: int m_DrawMode;
     protected: std::vector<XYZ_RGBA> m_arrPositionColor;
};

class MyObject
{
     public: MyObject();
     public: MyObject(std::vector<MyPolygon> arrPolygon);

     public: void Draw();
     public: void MoveByOffset(float xOffset, float yOffset);
     public: MyObject CreateByTemplate(XY realPos, float realWidth, float realHeight);
     public: void AddPolygon(MyPolygon myPolygon);

     protected: std::vector<MyPolygon> m_arrPolygon;
};
 I draw the lake as vector graphics in Adobe Illustrator. I take the coordinates of the points from Adobe Illustrator and add them to my 2D game on C++ OpenGL 
I'm doing a 2D game airplane flying and I want to draw water or a lake.

In OpenGL you can draw using triangles like this:
Step 1. Open Adobe Illustrator
If you don't have Adobe Illustrator CS5 installed, you need to Download and install the trial version Adobe CS5 Master Collection ...

Open Adobe Illustrator CS5:
Open Adobe Illustrator CS5 | Vector Graphics
Open Adobe Illustrator CS5 | Vector Graphics
Step 2. How to Create a New 100 x 100 Dot Canvas
Step 3. How to Draw a Lake
Step 4. Pressing the lake to the borders
Step 5. Taking all the points of the lake
Step 6. Added points to the project
Added dots (water) to my Phone game Android Native C++ Game in Android Studio using Android NDK, OpenGL ES, C++ ...

I have a file my_game_assets.h in my project Android Native C++ Game and in this file in the variable g_Lake:
• Coordinates of points and colors are stored as an array
• Mode how to connect Points. I'm using GL_TRIANGLE_FUN.
 
How does OpenGL draw?
The OpenGL library needs dots and a drawing mode to draw.
I'm using GL_TRIANGLE_FUN mode and here are my points:
I've set 16 points in the array:

Center Point   XY(50, 50)
Point 1   XY(43, 0)
Point 2   XY(68, 2)
Point 3   XY(85, 10)
Point 4   XY(94, 23)
Point 5   XY(100, 36)
Point 6   XY(100, 64)
Point 7   XY(84, 88)
Point 8   XY(59, 100)
Point 9   XY(41, 100)
Point 10   XY(19, 94)
Point 11   XY(4, 75)
Point 12   XY(1, 50)
Point 13   XY(5, 27)
Point 14   XY(14, 10)
Point 1   XY(43, 0)
OpenGL will make a triangle on three points and paint it inside.
The [eng]GL_TRIANGLE_FUN mode will make triangles like this:
 
1st triangle: center point, Point 1, Point 2
 
2nd triangle: center point, Point 2, Point 3
 
3rd Triangle: center point, Point 3, Point 4
 
4th triangle: center point, Point 4, Point 5
 
5th triangle: center point, Point 5, Point 6

etc.
 Drawing an enemy airplane as a vector graphic in Adobe Illustrator. I take the coordinates of the points from Adobe Illustrator and add them to my 2D game on C++ OpenGL 
I'm doing a 2D game airplane flying and I want to draw an enemy airplane.

In OpenGL you can draw using triangles like this:
Step 1. Open Adobe Illustrator
If you don't have Adobe Illustrator CS5 installed, you need to Download and install the trial version Adobe CS5 Master Collection ...

Open Adobe Illustrator CS5:
Open Adobe Illustrator CS5 | Vector Graphics
Open Adobe Illustrator CS5 | Vector Graphics
Step 2. How to Create a New 100 x 100 Dot Canvas
Step 3. How to Draw an Enemy Plane
 
← Previous topic
What is Android OpenGL ES for Android phone? This is the C++ graphics library for the Android phone.
 
Next topic →
Drawing a lake by points for the 2D game
 
Your feedback ... 1 Comments
guest
8 June 2023 14:35
   
Your Name
Your comment (www links can only be added by a logged-in user)

  Объявления  
  Объявления  
 
What is the Android operating system? What version numbers were in Android
What are ARM processors? | Android
Что такое AndroidX?
Java application (for Android phone) in Android Studio
Why Android applications are written in Java?
Download and install Android Studio to write programs for Android phones in Java, Kotlin
Open Android Studio on the computer (Windows 10)
Create a new project on Java with one simple Activity in Android Studio (write a program for Android phones, tablets) in Windows 10
Compile and run the application in Android Studio on computer (Windows) in emulator mode Android Device
Running the application Android Studio in debugging on computer (Windows) in emulator mode Android Device
Error "error while waiting for device: the emulator process for ..... has terminated" when running an application in Android Studio on a computer (Windows) in emulator mode Android Device
Error "Error while waiting for device: Illegal char <*> at index 0: *.lock ..." when running the application in Android Studio
Error "AVD is already running ..." when running the application in Android Studio
Error "CMake "3.18.1" was not found in SDK, PATH, or by cmake.dir property" when compiling a project to Android Studio
Error "Execution failed for task ":app:compressDebugAssets" when compiling a project to Android Studio
All errors when starting the Android application
What is Android SDK (a copy of the Android operating system)? Installing Android SDK 8.1 in Android Studio ...
Create a Android virtual device in Android Studio
Install HAXM
Activity in Android
Kotlin application (for Android phone) in Android Studio
Download and install Android Studio to write programs for Android phones in Java, Kotlin
Create a new project "Empty Views Activity" on Kotlin in Android Studio (write a program for Android phones, tablets) in Windows 10
Compile and run Kotlin an application in Android Studio on a computer (Windows) in emulator mode Android Device
Run Kotlin an application in Android Studio in debugging on a computer (Windows) in emulator mode Android Device
Running and debugging Kotlin Android Studio app on my phone via USB
Long wait when running Kotlin Android application. I see the message: "I/zygote:Waiting for a blocking GC ProfileSaver"
Create Android project, add TextView and show the value on the phone | Android Telephone, Android Studio, Kotlin, Windows 10
Copy the data in the class and object. We use the attribute @Parcelize and the interface Parcelable. | Kotlin | Android Studio
Error "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
Show a window with 2 buttons: yes, no and you don't need to add any resource, layout | I call the AlertDialog function in Kotlin | Android Studio
Android Kotlin application takes photo using camera and draws in the application | Android Studio | Kotlin
Android Kotlin choose photo from gallery and draws in the application | Android Studio | Kotlin ...
getExternalFilesDir - function that returns the full path to an external directory where our application can place persistent files | Android Studio, Kotlin
getFilesDir - function that returns the full path to directory where our application can place files | Android Studio, Kotlin
How do I work with files media in Android? What are content Uri and file path. The difference between getExternalFilesDir and getFilesDir ... | Android Studio, Kotlin
How to Make a Variable in the build.gradle File and Pass It to the Manifest File AndroidManifest.xml | Android Studio | Kotlin
How to Make a Variable in a build.gradle File and Pass It to a Kotlin File | Android Studio | Kotlin
Moshi (converting json text to a class object) | deserialization in Kotlin | Android Studio
Moshi (converting array json to list of object) | deserialization in Kotlin | Android Studio
Error "Failed to find the generated JsonAdapter class for class com.example.androidkotlinapp1.MyBook" | Exception | Kotlin | Moshi | Android Studio
Error "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]" | When compiling a Kotlin, Moshi project in Android Studio
Jetpack application (for Android phone) in Android Studio | Kotlin
What is Jetpack for Android?
Create a new project "Jetpack Compose" on Kotlin in Android Studio (write a program for Android phones, tablets) in Windows 10
Compilation error "Dependency 'androidx.core:core-ktx:1.17.0' requires Android Gradle plugin 8.9.1 or higher" | Jetpack | Kotlin | Android Studio
C++ game (for Android phone) in Android Studio | Android NDK, OpenGL ES
What is Android NDK for Android phone? This is the C++ library for the Android phone.
What is Android OpenGL ES for Android phone? This is the C++ graphics library for the Android phone.
Create a project "Android Native C++ Game" for the phone | Android Studio, Android NDK, OpenGL ES, C++
Drawing a lake by points for the 2D game
Drawing an enemy airplane as a vector graphic in Adobe Illustrator. I take the coordinates of the points from Adobe Illustrator and add them to my 2D game on C++ OpenGL
Compile and run "Android Native C++ Game" in Android Studio on a computer (Windows) in Android Device emulator mode
Error "[CXX1405] error when building with cmake using CMakeLists.txt: C build system [configure] failed while executing cmake.exe" when compiling Android Native C++ an application to Android Studio on computer (Windows)
Error "ninja: error: rebuilding 'build.ninja': subcommand failed" when compiling Android Native C++ an application to Android Studio on computer (Windows)
Draw a triangle with paint inside in "Android Native C++ Game" for phone | Android Studio, Android NDK, OpenGL ES v1, C++
Download bmp file from Assets and draw textures in "Android Native C++ Game" for your phone | Android Studio, Android NDK, OpenGL ES v2 (shader), C++
How to get bmp file located in Assets inside apk file ? | Android Studio, NDK, C++
How to use alpha transparency in displaying texture using OpenGL? | Android Studio, OpenGL ES, NDK, C++
Why does glTexImage2D return error code 1280? | Android Studio, OpenGL ES, NDK, C++
What are cpp and h files in C++? | Android Studio, NDK, C++
How to create new h file and add to project android NDK C++? | Android Studio, NDK, C++
How to create new cpp file and add to project android NDK C++? | Android Studio, NDK, C++, CMakeLists.txt
dynamic_cast in C++ (converting a pointer to a different type and checking validity in runtime) | Android Studio, NDK, C++
std::map<Key, Value> is a set of keys and values in C++. | Android Studio, NDK, C++
Pass a function as a parameter to a function (callback) | C++ | Android Studio, NDK, C++
How to find event when display rotated (changed orientation) in Android phone | Android Studio, NDK, C++
How to handle events in Android phone (create/terminate window event, set focus, lost focus, touch in phone) | Android Studio, NDK, C++
Create a signed apk file in Android Studio | Android NDK, OpenGL ES
Google Play Console (for developer)
Creating a Google Play account developer | Google Play Console
The developer in Google Play Console needs to verify the identity | Google Play Console
The developer in Google Play Console needs to confirm developer account | Google Play Console
Developer account is not in use | Developer account is at risk of being closed | Google Play Console
Compile app and send it for production in Google Play Console | My app in Google Play Console
Policy status "Invalid Privacy policy" | Provide link to a valid privacy policy page | My app in 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" | My app in 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" | My app in Google Play Console
Policy app content "Remove Photo and video permissions permission or submit declaration" | My app in Google Play Console
Create an application in Google Play Console (in the option I select that it will be a game) | My game in Google Play Console
Important parameters: package, applicationId, versionCode, versionName, android:label (in AndroidManifest.xml, build.gradle) to create a test version for Google Play Console | My game in Google Play Console
Create a signed .aab file in Android Studio | My game in Google Play Console
Compile the game and send it for internal testing in Google Play Console | My game in Google Play Console
Google automatically ran tests and made pictures, a report on how the game runs on different brands of phones | My game in Google Play Console
How do I ask Google Play Developer Console a support question?
Google Play Developer Console support feedback
Topics about Google Play Billing & in-app purchase | Google Play Console
Can I use (integrate) payments in my Google game if I am a developer from Belarus? | Monetization in Google Play Console
How can I change the Google Play Console language? | Google Chrome
How to change country in payments profile? | Google Play Console
How do I view (open) a payment page in Google Play? | Google Play Console

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