{"id":497,"date":"2021-12-05T00:45:40","date_gmt":"2021-12-05T00:45:40","guid":{"rendered":"https:\/\/writingagame.com\/?p=497"},"modified":"2022-01-11T00:14:35","modified_gmt":"2022-01-11T00:14:35","slug":"chapter-13-basic-classes-2","status":"publish","type":"post","link":"https:\/\/writingagame.com\/index.php\/2021\/12\/05\/chapter-13-basic-classes-2\/","title":{"rendered":"Chapter 13. Basic classes 2"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\"> Windows<\/h2>\n\n\n\n<p>1. Start VS. Open&nbsp;<em>C:\\CPP\\a998engine\\p_windows\\p_windows.sln<\/em><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p><strong>MyColor class<\/strong><\/p>\n\n\n\n<p>The reason to have it as a separate class, is that we will need to keep colors in THREE different formats:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>as an array of 4 single byte integers (from 0 to 255, as it is stored in files)<\/li><li>as an array of 4 floats (from 0.0 to 1.0, as required by OpenGL)<\/li><li>as a single 32-bit integer (4 bytes, 1 byte for each channel)<\/li><\/ul>\n\n\n\n<p>Any change to either of these formats must be reflected in the other two.<\/p>\n\n\n\n<p>2. Under <em>xEngine <\/em>add new header (.h) file <strong>MyColor.h<\/strong><\/p>\n\n\n\n<p>Location &#8211; <em>C:\\CPP\\engine<\/em><\/p>\n\n\n\n<p>Code:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; highlight: [8]; title: ; notranslate\" title=\"\">\n#pragma once\n#include &quot;platform.h&quot;\n\nclass MyColor\n{\nprivate:\n    float rgba&#91;4] = { 0,0,0,0 };\n    union {\n        myUint32 uint32value = 0;\n        myUint8  channel&#91;4]; \/\/4 channels\n    } RGBA;\npublic:\n    float* forGL() { return rgba; };\n    static void cloneIntToFloat(MyColor* pCl);\n    static void cloneFloatToInt(MyColor* pCl);\n    void setRGBA(float* rgba) { return setRGBA(this, rgba); };\n    static void setRGBA(MyColor* pCl, float* rgba);\n    void setRGBA(float r, float g, float b, float a) { return setRGBA(this, r, g, b, a); };\n    static void setRGBA(MyColor* pCl, float r, float g, float b, float a);\n    void setRGBA(int R, int G, int B, int A) { return setRGBA(this, R, G, B, A); };\n    static void setRGBA(MyColor* pCl, int R, int G, int B, int A);\n    void setRGBA(unsigned char* RGBA) { return setRGBA(this, RGBA); };\n    static void setRGBA(MyColor* pCl, unsigned char* RGBA);\n    void setUint32(unsigned int RGBA) { return setUint32(this, RGBA); };\n    static void setUint32(MyColor* pCl, unsigned int RGBA);\n    bool isZero() { return (RGBA.uint32value == 0); };\n    bool isSet() { return (RGBA.uint32value != 0); };\n    void clear() { setUint32(0); };\n    unsigned int getUint32() { return (unsigned int)RGBA.uint32value; };\n};\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Please note: we are using here 2 custom defined variable types: <em>myUint32 <\/em>and <em>myUint8<\/em>. <\/li><li>Can&#8217;t use &#8220;normal&#8221; <em>_int32 <\/em>or <em>_int8<\/em> because they are <em>Windows-specific<\/em>, Android has different definitions.<\/li><\/ul>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>3. Open <em>platform.h<\/em> and replace code by following:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; highlight: [6,8]; title: ; notranslate\" title=\"\">\n#pragma once\n#include &lt;glad\/glad.h&gt;\n#include &lt;stdio.h&gt;\n\ntypedef unsigned _int64 myUint64;\ntypedef unsigned _int32 myUint32;\ntypedef unsigned _int16 myUint16;\ntypedef unsigned _int8  myUint8;\n\nvoid mylog(const char* _Format, ...);\nvoid mySwapBuffers();\nvoid myPollEvents();\nint myFopen_s(FILE** pFile, const char* filePath, const char* mode);\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>4. Under <em>xEngine <\/em>add new C++ File (.cpp) file <strong>MyColor.cpp<\/strong><\/p>\n\n\n\n<p>Location &#8211; <em>C:\\CPP\\engine<\/em><\/p>\n\n\n\n<p>Code:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n#include &quot;MyColor.h&quot;\n\nfloat chanIntToFloat = 1.0f \/ 255;\n\nvoid MyColor::cloneIntToFloat(MyColor* pCl) {\n\tfor (int i = 0; i &lt; 4; i++)\n\t\tpCl-&gt;rgba&#91;i] = chanIntToFloat * pCl-&gt;RGBA.channel&#91;i];\n}\nvoid MyColor::cloneFloatToInt(MyColor* pCl) {\n\tfor (int i = 0; i &lt; 4; i++)\n\t\tpCl-&gt;RGBA.channel&#91;i] = (int)(pCl-&gt;rgba&#91;i] * 255);\n}\nvoid MyColor::setRGBA(MyColor* pCl, float* rgba) {\n\tfor (int i = 0; i &lt; 4; i++)\n\t\tpCl-&gt;rgba&#91;i] = rgba&#91;i];\n\tcloneFloatToInt(pCl);\n}\nvoid MyColor::setRGBA(MyColor* pCl, float r, float g, float b, float a) {\n\tpCl-&gt;rgba&#91;0] = r;\n\tpCl-&gt;rgba&#91;1] = g;\n\tpCl-&gt;rgba&#91;2] = b;\n\tpCl-&gt;rgba&#91;3] = a;\n\tcloneFloatToInt(pCl);\n}\nvoid MyColor::setRGBA(MyColor* pCl, int R, int G, int B, int A) {\n\tpCl-&gt;RGBA.channel&#91;0] = R;\n\tpCl-&gt;RGBA.channel&#91;1] = G;\n\tpCl-&gt;RGBA.channel&#91;2] = B;\n\tpCl-&gt;RGBA.channel&#91;3] = A;\n\tcloneIntToFloat(pCl);\n}\nvoid MyColor::setRGBA(MyColor* pCl, unsigned char* RGBA) {\n\tfor (int i = 0; i &lt; 4; i++)\n\t\tpCl-&gt;RGBA.channel&#91;i] = RGBA&#91;i];\n\tcloneIntToFloat(pCl);\n}\nvoid MyColor::setUint32(MyColor* pCl, unsigned int RGBA) {\n\tpCl-&gt;RGBA.uint32value = RGBA;\n\tcloneIntToFloat(pCl);\n}\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p><strong>Material class<\/strong><\/p>\n\n\n\n<p>&#8220;Material&#8221; in our case is an instruction HOW to render, which shader to use, which textures and colors, etc. For example, &#8220;Draw green surface with ucolor_flat shader&#8221; is one Material. &#8220;Draw red surface with same shader&#8221; is another one. WHAT to render &#8211; is a separate question. We don&#8217;t have much to store in this class yet, but we will later.<\/p>\n\n\n\n<p>5. Under <em>xEngine <\/em>add new header (.h) file <strong>Material.h<\/strong><\/p>\n\n\n\n<p>Location &#8211; <em>C:\\CPP\\engine<\/em><\/p>\n\n\n\n<p>Code:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n#pragma once\n#include &quot;MyColor.h&quot;\n\nclass Material\n{\npublic:\n\tint shaderN = -1;\n\tint primitiveType = GL_TRIANGLES;\n\tMyColor uColor;\n\tint uTex0 = -1;\n};\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>6. Under <em>xEngine <\/em>add new C++ (.cpp) file <strong>Material.cpp<\/strong><\/p>\n\n\n\n<p>Location &#8211; <em>C:\\CPP\\engine<\/em><\/p>\n\n\n\n<p>We can leave it empty so far.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>Now we are ready for our engine&#8217;s key class, which will represent WHAT to render. Also it will have <em>Material <\/em>info, so it will know WHAT to render and HOW. I will call it a <strong>DrawJob<\/strong>.<\/p>\n\n\n\n<p>Each game subject can have 1 or a few <em>DrawJobs<\/em>. For example, let&#8217;s say we want to draw a red cube with a picture on 1 side. So, the subject will have 2 <em>DrawJobs<\/em>:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>5-sided mesh with color reference and <em>ucolor_flat<\/em> shader<\/li><li>1-sided mesh with texture reference and <em>tex_flat<\/em> shader<\/li><\/ul>\n\n\n\n<p><em>TheGame <\/em>class will scan game subjects and their <em>DrawJobs <\/em>and will execute them.<\/p>\n\n\n\n<p>Each <em>DrawJob <\/em>must have a reference to involved data sources, in our sample &#8211; a single vertex_buffer VBO (Vertex Buffer Object which was generated from vertices array). Each element of this VBO consists of 5 floats  (alternatively it could be two arrays\/VBOs: one keeping xyz info and another one &#8211; tUV).<\/p>\n\n\n\n<p>Also, <em>DrawJob <\/em>must include instructions how to interpret these data: for each involved variable (such as aPos or aTuv) it must tell where it is located (in which VBO and a position\/offset inside of this VBO). So, we&#8217;ll need an extra structure, we&#8217;ll call it <em>AttribRef <\/em>(for Attribute Reference).<\/p>\n\n\n\n<p>VBOs themselves will reside separately (in GPU). In the <em>DrawJob <\/em>(in <em>AttribRefs <\/em>to be more accurate) we&#8217;ll need only VBO ids.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p><strong>DrawJob class<\/strong><\/p>\n\n\n\n<p>7. Under <em>xEngine <\/em>add new header (.h) file <strong>DrawJob.h<\/strong><\/p>\n\n\n\n<p>Location &#8211; <em>C:\\CPP\\engine<\/em><\/p>\n\n\n\n<p>Code:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n#pragma once\n#include &quot;Material.h&quot;\n#include &lt;vector&gt;\n\nstruct AttribRef \/\/attribute reference\/description\n{\n\tunsigned int glVBOid = 0; \/\/buffer object id\n\tint offset = 0; \/\/variable&#039;s offset inside of VBO&#039;s element\n\tint stride = 0; \/\/Buffer&#039;s element size in bytes\n};\n\nclass DrawJob\n{\npublic:\n\tMaterial mt;\n\tint pointsN = 0; \/\/N of points to draw\n\tunsigned int glVAOid = 0; \/\/will hold data stream attributes mapping\/positions\n\n\t\/\/common attributes\n\tAttribRef aPos;\n\tAttribRef aTuv;\n\n\t\/\/static arrays (vectors) of all loaded DrawJobs, VBO ids\n\tstatic std::vector&lt;DrawJob*&gt; drawJobs;\n\tstatic std::vector&lt;unsigned int&gt; buffersIds;\npublic:\n\tDrawJob();\n\tvirtual ~DrawJob(); \/\/destructor\n\tstatic int cleanUp();\n\tstatic int newBufferId();\n\tint buildVAO() { return buildVAOforShader(this, mt.shaderN); };\n\tstatic int buildVAOforShader(DrawJob* pDJ, int shaderN);\n\tstatic int attachAttribute(int varLocationInShader, int attributeSizeInFloats, AttribRef* pAttribRef);\n\n\tvirtual int setDesirableOffsets(int* pStride, int shaderN) { return setDesirableOffsetsBasic(this, pStride, shaderN); };\n\tstatic int setDesirableOffsetsBasic(DrawJob* pDJ, int* pStride, int shaderN);\n\n\tint execute(float* uMVP, Material* pMt) { return executeDrawJob(this, uMVP, pMt); };\n\tstatic int executeDrawJob(DrawJob* pDJ, float* uMVP, Material* pMt);\n};\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>8. Under <em>xEngine <\/em>add new C++ (.cpp) file <strong>DrawJob.cpp<\/strong><\/p>\n\n\n\n<p>Location &#8211; <em>C:\\CPP\\engine<\/em><\/p>\n\n\n\n<p>Code:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n#include &quot;DrawJob.h&quot;\n#include &quot;platform.h&quot;\n#include &quot;utils.h&quot;\n#include &quot;Shader.h&quot;\n#include &quot;Texture.h&quot;\n\n\/\/static arrays (vectors) of all loaded DrawJobs, VBO ids\nstd::vector&lt;DrawJob*&gt; DrawJob::drawJobs;\nstd::vector&lt;unsigned int&gt; DrawJob::buffersIds;\n\nDrawJob::DrawJob() {\n\tdrawJobs.push_back(this);\n}\nDrawJob::~DrawJob() {\n\tglBindBuffer(GL_ARRAY_BUFFER, 0);\n\tglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);\n\tif (glVAOid &gt; 0)\n\t\tglDeleteVertexArrays(1, &amp;glVAOid);\n}\nint DrawJob::newBufferId() {\n\tunsigned int bufferId;\n\tglGenBuffers(1, &amp;bufferId);\n\tbuffersIds.push_back(bufferId);\n\treturn (int)bufferId;\n}\n\nint DrawJob::setDesirableOffsetsBasic(DrawJob* pDJ, int* pStride, int shaderN) {\n\t\/\/sets desirable offsets and stride according to given shader needs\n\t\/\/assuming that we have 1 single VBO\n\tShader* pSh = Shader::shaders.at(shaderN);\n\tint stride = 0;\n\tpDJ-&gt;aPos.offset = 0; \/\/attribute o_aPos, always 0\n\tstride += sizeof(float) * 3; \/\/aPos size - 3 floats (x,y,z)\n\tif (pSh-&gt;l_aTuv &gt;= 0) { \/\/attribute TUV (texture coordinates)\n\t\tpDJ-&gt;aTuv.offset = stride; \/\/attribute TUV (texture coordinates)\n\t\tstride += sizeof(float) * 2;\n\t}\n\t*pStride = stride;\n\treturn 1;\n}\nunsigned int activeVBOid;\nint DrawJob::buildVAOforShader(DrawJob* pDJ, int shaderN) {\n\t\/\/delete VAO if exists already\n\tif (pDJ-&gt;glVAOid &gt; 0) {\n\t\tglBindBuffer(GL_ARRAY_BUFFER, 0);\n\t\tglDeleteVertexArrays(1, &amp;(pDJ-&gt;glVAOid));\n\t}\n\tglGenVertexArrays(1, &amp;pDJ-&gt;glVAOid);\n\tglBindVertexArray(pDJ-&gt;glVAOid);\n\n\t\/\/open shader descriptor to access variables locations\n\tShader* pShader = Shader::shaders.at(pDJ-&gt;mt.shaderN);\n\n\tactiveVBOid = 0;\n\tattachAttribute(pShader-&gt;l_aPos, 3, &amp;pDJ-&gt;aPos);\n\tattachAttribute(pShader-&gt;l_aTuv, 2, &amp;pDJ-&gt;aTuv);\n\treturn 1;\n}\n\nint DrawJob::attachAttribute(int varLocationInShader, int attributeSizeInFloats, AttribRef* pAR) {\n\tif (varLocationInShader &lt; 0)\n\t\treturn 0; \/\/not used in this shader\n\tif (pAR-&gt;glVBOid == 0) {\n\t\tmylog(&quot;ERROR in DrawJob::attachAttribute, nk such attribute\/VBO\\n&quot;);\n\t\treturn -1;\n\t}\n\tglEnableVertexAttribArray(varLocationInShader);\n\tif (activeVBOid != pAR-&gt;glVBOid) {\n\t\tactiveVBOid = pAR-&gt;glVBOid;\n\t\t\/\/attach input stream data\n\t\tglBindBuffer(GL_ARRAY_BUFFER, activeVBOid);\n\t}\n\tglVertexAttribPointer(varLocationInShader, attributeSizeInFloats, GL_FLOAT, GL_FALSE, pAR-&gt;stride, (void*)(long)pAR-&gt;offset);\n\treturn 1;\n}\nint DrawJob::executeDrawJob(DrawJob* pDJ, float* uMVP, Material* pMt) {\n\tif (pMt == NULL)\n\t\tpMt = &amp;(pDJ-&gt;mt);\n\tglBindVertexArray(pDJ-&gt;glVAOid);\n\tShader* pShader = Shader::shaders.at(pMt-&gt;shaderN);\n\tglUseProgram(pShader-&gt;GLid);\n\tglUniformMatrix4fv(pShader-&gt;l_uMVP, 1, GL_FALSE, (const GLfloat*)uMVP);\n\n\t\/\/attach textures\n\tif (pShader-&gt;l_uTex0 &gt;= 0) {\n\t\tint textureId = Texture::getGLid(pMt-&gt;uTex0);\n\t\t\/\/pass textureId to shader program\n\t\tglActiveTexture(GL_TEXTURE0); \/\/ activate the texture unit first before binding texture\n\t\tglBindTexture(GL_TEXTURE_2D, textureId);\n\t\t\/\/ Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.    \n\t\tglUniform1i(pShader-&gt;l_uTex0, 0);\n\t}\n\t\/\/other uniforms\n\tif (pShader-&gt;l_uColor &gt;= 0) {\n\t\t\/\/float uColor&#91;4] = { 1.f, 0.f, 1.f, 1.f }; \/\/R,G,B, alpha\n\t\tglUniform4fv(pShader-&gt;l_uColor, 1, pMt-&gt;uColor.forGL());\n\t}\n\tglDrawArrays(pMt-&gt;primitiveType, 0, pDJ-&gt;pointsN);\n\treturn 1;\n}\nint DrawJob::cleanUp() {\n\tint itemsN = drawJobs.size();\n\t\/\/delete all drawJobs\n\tfor (int i = 0; i &lt; itemsN; i++) {\n\t\tDrawJob* pDJ = drawJobs.at(i);\n\t\tdelete pDJ;\n\t}\n\tdrawJobs.clear();\n\t\/\/delete Buffers\n\titemsN = buffersIds.size();\n\t\/\/delete all buffers\n\tfor (int i = 0; i &lt; itemsN; i++) {\n\t\tunsigned int id = buffersIds.at(i);\n\t\tglDeleteBuffers(1, &amp;id);\n\t}\n\tbuffersIds.clear();\n\n\treturn 1;\n}\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>Try to pay a bit closer attention to this class, especially to <em>AttribRef <\/em>structure and to it&#8217;s usage. If it&#8217;s too difficult now, don&#8217;t worry, you can come back to this later.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>9. Open <em>TheGame.cpp<\/em> and replace code by:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n#include &quot;TheGame.h&quot;\n#include &quot;platform.h&quot;\n#include &quot;linmath.h&quot;\n#include &quot;Texture.h&quot;\n#include &quot;Shader.h&quot;\n#include &quot;DrawJob.h&quot;\n\nextern std::string filesRoot;\n\nstatic const struct\n{\n    float x, y, z, tu, tv;\n} vertices&#91;4] =\n{\n    { -0.5f,  0.5f, 0.f, 0.f, 0.f }, \/\/top-left\n    { -0.5f, -0.5f, 0.f, 0.f, 1.f }, \/\/bottom-left\n    {  0.5f,  0.5f, 0.f, 1.f, 0.f }, \/\/top-right\n    {  0.5f, -0.5f, 0.f, 1.f, 1.f }  \/\/bottom-right\n};\n\nDrawJob* pDJ;\nfloat angle_z = 0;\n\nint TheGame::getReady() {\n    bExitGame = false;\n    Shader::loadShaders();\n\n    pDJ = new DrawJob();\n    \/\/define material\n    pDJ-&gt;mt.shaderN = Shader::spN_flat_tex; \n    pDJ-&gt;mt.primitiveType = GL_TRIANGLE_STRIP;\n    pDJ-&gt;mt.uTex0 = Texture::loadTexture(filesRoot + &quot;\/dt\/sample_img.png&quot;);\n    \/\/pDJ-&gt;mt.color0.setRGBA(1.f, 0.f, 1.f, 1.f);\n    \/\/pDJ-&gt;mt.color0.setRGBA(255, 0, 255,255);\n\n    \/\/build and attach data source(s)\n    pDJ-&gt;pointsN = 4; \/\/number of vertices\n    unsigned int glVBOid = pDJ-&gt;newBufferId();\n    glBindBuffer(GL_ARRAY_BUFFER, glVBOid);\n    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);\n    \/\/describe data source\n    int stride = sizeof(float) * 5;\n    \/\/attributes references\n    AttribRef* pAR;\n    pAR = &amp;pDJ-&gt;aPos; pAR-&gt;offset = 0;                 pAR-&gt;glVBOid = glVBOid; pAR-&gt;stride = stride;\n    pAR = &amp;pDJ-&gt;aTuv; pAR-&gt;offset = sizeof(float) * 3; pAR-&gt;glVBOid = glVBOid; pAR-&gt;stride = stride;\n\n    \/\/create and fill vertex attributes array (VAO)\n    pDJ-&gt;buildVAO();\n    \/\/end of data stream setting, now it is stored in VAO\n    return 1;\n}\nint TheGame::drawFrame() {\n    myPollEvents();\n\n    mat4x4 m, p, mvp;\n    \/\/glClearColor(0.0, 0.0, 0.5, 1.0);\n    glClear(GL_COLOR_BUFFER_BIT);\n    angle_z += 0.01f;\n    mat4x4_identity(m);\n    mat4x4_rotate_Z(m, m, angle_z);\n    mat4x4_scale_aniso(m, m, 2.0, 1.0, 1.0);\n    mat4x4_ortho(p, -screenRatio, screenRatio, -1.f, 1.f, 1.f, -1.f);\n    mat4x4_mul(mvp, p, m);\n\n    pDJ-&gt;execute((float*)mvp, NULL);\n    mySwapBuffers();\n    return 1;\n}\nint TheGame::cleanUp() {\n    Texture::cleanUp();\n    Shader::cleanUp();\n    DrawJob::cleanUp();\n    return 1;\n}\nint TheGame::onScreenResize(int width, int height) {\n    if (screenSize&#91;0] == width &amp;&amp; screenSize&#91;1] == height)\n        return 0;\n    screenSize&#91;0] = width;\n    screenSize&#91;1] = height;\n    screenRatio = (float)width \/ (float)height;\n    glViewport(0, 0, width, height);\n    mylog(&quot; screen size %d x %d\\n&quot;, width, height);\n    return 1;\n}\nint TheGame::run() {\n    getReady();\n    while (!bExitGame) {\n        drawFrame();\n    }\n    cleanUp();\n    return 1;\n}\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>10. Build and run &#8211; good.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>Now let&#8217;s try on<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Android<\/h2>\n\n\n\n<p>11. Re-start VS. Open&nbsp;<em>C:\\CPP\\a998engine\\p_android\\p_android.sln<\/em>.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>12. Under <em>xEndine <\/em>add Existing Item<\/p>\n\n\n\n<p>Go to <em>C:\\CPP\\engine<\/em><\/p>\n\n\n\n<p>Pick<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>DrawJob.cpp<\/li><li>DrawJob.h<\/li><li>Material.cpp<\/li><li>Material.h<\/li><li>MyColor.cpp<\/li><li>MyColor.h<\/li><\/ul>\n\n\n\n<p><strong>Add<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>Add Android&#8217;s <em>myUint32\/8<\/em> implementations.<\/p>\n\n\n\n<p>13. Open <em>platform.h<\/em> and replace code by:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n#pragma once\n\ntypedef uint32_t myUint64;\ntypedef uint32_t myUint32;\ntypedef uint8_t  myUint16;\ntypedef uint8_t  myUint8;\n\nvoid mylog(const char* _Format, ...);\nvoid mySwapBuffers();\nvoid myPollEvents();\nint myFopen_s(FILE** pFile, const char* filePath, const char* mode);\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>14. Switch on, <strong>unlock <\/strong>and plug in Android, allow debugging.<\/p>\n\n\n\n<p>Build and run &#8211; perfect.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p class=\"mb-2\">Windows 1. Start VS. Open&nbsp;C:\\CPP\\a998engine\\p_windows\\p_windows.sln MyColor class The reason to have it as a separate class, is that we will need to keep colors in THREE different formats: as an array of 4 single byte integers (from 0 to 255, as it is stored in files) as an array of 4 floats (from 0.0 to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-497","post","type-post","status-publish","format-standard","hentry","category-cross-platform-3d"],"_links":{"self":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/497","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/comments?post=497"}],"version-history":[{"count":19,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/497\/revisions"}],"predecessor-version":[{"id":1248,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/497\/revisions\/1248"}],"wp:attachment":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/media?parent=497"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/categories?post=497"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/tags?post=497"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}