{"id":82,"date":"2021-11-27T00:09:30","date_gmt":"2021-11-27T00:09:30","guid":{"rendered":"https:\/\/writingagame.com\/?p=82"},"modified":"2022-08-03T16:37:27","modified_gmt":"2022-08-03T16:37:27","slug":"chapter-3-hello-windows","status":"publish","type":"post","link":"https:\/\/writingagame.com\/index.php\/2021\/11\/27\/chapter-3-hello-windows\/","title":{"rendered":"Chapter 3. Hello Windows"},"content":{"rendered":"\n<p><strong>Visual Studio, Windows, C++, OpenGL ES, GLFW, GLAD<\/strong><\/p>\n\n\n\n<p>Using OpenGL ES on the PC is less straight forward than on Android. The reason is that GL ES is intended for mobile devices, NOT for desktops. Fortunately, solutions do exist. OpenGL producers strongly advise to use a window toolkit (GLFW) and an OpenGL loading libraries (GLAD). Well, let\u2019s download them.<\/p>\n\n\n\n<p>1. Create a placeholder for these libraries.<br>In <strong>Windows File Explorer<\/strong> in our <strong>root<\/strong> C:\\CPP folder create subfolder \u201cp_windows\u201d (&#8220;p&#8221; is for &#8220;platform&#8221;). We\u2019ll keep there all platform-specific stuff that is applicable to ALL our projects.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<ol class=\"wp-block-list\" start=\"2\"><li><strong>Download GLFW<\/strong>.<\/li><\/ol>\n\n\n\n<p>Go to <a href=\"https:\/\/www.glfw.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.glfw.org\/<\/a><\/p>\n\n\n\n<p>Proceed to Download link on top:<\/p>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b01\/c03\/01.jpg\"><\/p>\n\n\n\n<p>We need 32-bit Windows <strong>pre-compiled<\/strong> binaries. Why 32? Well, they fit 32 AND 64-bit Windows as well, so we\u2019ll pick 32 as a more \u201ccross-platform\u201d option:<\/p>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b01\/c03\/02.jpg\"><\/p>\n\n\n\nOR: you can download it <a href=\"https:\/\/writingagame.com\/img\/b01\/c03\/glfw-3.3.5.bin.WIN32.zip\" download=\"\">here<\/a>.\n\n\n\n<p>After download finished, in <strong>Windows File Explorer<\/strong> go to your Downloads folder, unzip <strong>glfw-3.3.5.bin.WIN32.zip<\/strong> (right-click on file -&gt; <em>Open with -&gt; 7-Zip File Manager -&gt; Extract<\/em>).<\/p>\n\n\n\n<p><strong>IMPORTANT<\/strong>: Change the destination (Copy to) to <em>C:\\CPP\\p_windows\\<\/em><\/p>\n\n\n\n<p>Then \u2013 <strong>Ok<\/strong>.<\/p>\n\n\n\n<p>In  <strong>Windows File Explorer<\/strong> go to  <em>C:\\CPP\\p_windows\\<\/em>  folder and <strong>rename <\/strong>extracted <em>glfw-3.3.5.bin.WIN32<\/em> folder to <strong>glfw335win32<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<ol class=\"wp-block-list\" start=\"3\"><li><strong>Download GLAD<\/strong>.<\/li><\/ol>\n\n\n\n<p>First &#8211; add subfolder \u201c<strong>glad<\/strong>&#8221; under <em>C:\\CPP\\p_windows\\<\/em>.<\/p>\n\n\n\n<p>Then &#8211; go to <a href=\"https:\/\/glad.dav1d.de\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/glad.dav1d.de\/<\/a><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Language: <strong>C\/C++<\/strong>, <\/li><li>Specification: <strong>OpenGL<\/strong><\/li><li>Change Profile to <strong>Core<\/strong>,<\/li><li>Under gles2 pick <strong>Version 3.2<\/strong>:<\/li><\/ul>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b01\/c03\/03.jpg\"><\/p>\n\n\n\n<p>Scroll down.<\/p>\n\n\n\n<p>Leave \u201cGenerate a loader\u201d selected.<\/p>\n\n\n\n<p>Click <strong>Generate<\/strong>:<\/p>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b01\/c03\/04.jpg\"><\/p>\n\n\n\n<p>On the next screen click on \u201c<strong>glad.zip<\/strong>\u201d to download.<\/p>\n\n\n\nOR: you can download it <a href=\"https:\/\/writingagame.com\/img\/b01\/c03\/glad.zip\" download=\"\">here<\/a>.\n\n\n\n<p>When downloaded, go to <em>Downloads <\/em>folder and unzip <em>glad.zip<\/em> to <strong>C:\\CPP\\p_windows\\glad<\/strong>.<\/p>\n\n\n\n<p>Now our folders structure is:<\/p>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b01\/c03\/05.jpg\"><\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<ol class=\"wp-block-list\" start=\"4\"><li><strong>Create VS projec<\/strong>t.<\/li><\/ol>\n\n\n\n<p>GLFW website has a nice tutorial\/sample, which we will use here.  This sample was intended for OpenGL ES <strong>2.0<\/strong>. To make it compatible with <strong>3.2<\/strong> I had to modify it a bit. Also, it uses GLFW to create a window,  so we will create a <strong>Console <\/strong>project.<\/p>\n\n\n\n<p>So, open Visual Studio, <strong>Create a new project<\/strong>, pick <em>Windows <\/em>filter, pick <em>Windows Desktop Wizard<\/em>:<\/p>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b01\/c03\/05a.jpg\"><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Then &#8211; <strong>Next<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Project name \u2013 \u201c<strong>p_windows<\/strong>\u201d (&#8220;p&#8221; for &#8220;platform&#8221;).<\/li><li>Location &#8211; <em>C:\\CPP\\a999hello<\/em><\/li><li>Place solution and project in the same directory &#8211; yes:<\/li><\/ul>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b01\/c03\/06.jpg\"><\/p>\n\n\n\n<p>Then \u2013 <strong>Create<\/strong>.<\/p>\n\n\n\n<p>On the next screen pick \u201c<em>Console Application (.exe)<\/em>\u201d and \u201c<em>Empty project<\/em>\u201d:<\/p>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b01\/c03\/07.jpg\"><\/p>\n\n\n\n<p>Then \u2013 <strong>Ok<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<ol class=\"wp-block-list\" start=\"5\"><li><strong>Source code<\/strong>.<\/li><\/ol>\n\n\n\n<p>Right-click on \u201cp_windows\u201d <strong>project <\/strong>(not on solution), then <em>Add -&gt; New item<\/em>.<\/p>\n\n\n\n<p>On &lt;Add New Item&gt; screen pick \u201cC++ File (.cpp)\u201d, name \u2013 \u201c<strong>main.cpp<\/strong>\u201d:<\/p>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b01\/c03\/08.jpg\"><\/p>\n\n\n\n<p>Then \u2013 <strong>Add<\/strong>.<\/p>\n\n\n\n<p>Copy-Paste following code to <em>main.cpp<\/em>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; highlight: [3,22,35,58,67,68,80,85,86]; title: ; notranslate\" title=\"\">\n#include &lt;glad\/glad.h&gt;\n#define GLFW_INCLUDE_NONE\n#include &lt;GLFW\/glfw3.h&gt;\n\n#include &quot;linmath.h&quot;\n\n#include &lt;stdlib.h&gt;\n#include &lt;stdio.h&gt;\n\nstatic const struct\n{\n    float x, y;\n    float r, g, b;\n} vertices&#91;3] =\n{\n    { -0.6f, -0.4f, 1.f, 0.f, 0.f },\n    {  0.6f, -0.4f, 0.f, 1.f, 0.f },\n    {   0.f,  0.6f, 0.f, 0.f, 1.f }\n};\n\nstatic const char* vertex_shader_text =\n&quot;#version 320 es\\n&quot;\n&quot;precision lowp float;\\n&quot;\n&quot;uniform mat4 MVP;\\n&quot;\n&quot;in vec3 vCol;\\n&quot;\n&quot;in vec2 vPos;\\n&quot;\n&quot;out vec3 color;\\n&quot;\n&quot;void main()\\n&quot;\n&quot;{\\n&quot;\n&quot;    gl_Position = MVP * vec4(vPos, 0.0, 1.0);\\n&quot;\n&quot;    color = vCol;\\n&quot;\n&quot;}\\n&quot;;\n\nstatic const char* fragment_shader_text =\n&quot;#version 320 es\\n&quot;\n&quot;precision lowp float;\\n&quot;\n&quot;in vec3 color;\\n&quot;\n&quot;out vec4 FragColor;\\n&quot;\n&quot;void main()\\n&quot;\n&quot;{\\n&quot;\n&quot;    FragColor = vec4(color, 1.0);\\n&quot;\n&quot;}\\n&quot;;\n\nstatic void error_callback(int error, const char* description)\n{\n    fprintf(stderr, &quot;Error: %s\\n&quot;, description);\n}\n\nstatic void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)\n{\n    if (key == GLFW_KEY_ESCAPE &amp;&amp; action == GLFW_PRESS)\n        glfwSetWindowShouldClose(window, GLFW_TRUE);\n}\n\nint main(void)\n{\n    GLFWwindow* window;\n    unsigned int vao_buffer, vertex_buffer, vertex_shader, fragment_shader, program;\n    int mvp_location, vpos_location, vcol_location;\n    float angle_z = 0;\n\n    glfwSetErrorCallback(error_callback);\n\n    if (!glfwInit())\n        exit(EXIT_FAILURE);\n\n    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);\n    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);\n\n    window = glfwCreateWindow(640, 480, &quot;OurProject&quot;, NULL, NULL);\n    if (!window)\n    {\n        glfwTerminate();\n        exit(EXIT_FAILURE);\n    }\n\n    glfwSetKeyCallback(window, key_callback);\n\n    glfwMakeContextCurrent(window);\n    gladLoadGLES2Loader((GLADloadproc)glfwGetProcAddress); \/\/gladLoadGL(glfwGetProcAddress);\n    glfwSwapInterval(1);\n\n    \/\/ NOTE: OpenGL error checks have been omitted for brevity\n\n    glGenVertexArrays(1, &amp;vao_buffer);\n    glBindVertexArray(vao_buffer);\n\n    glGenBuffers(1, &amp;vertex_buffer);\n    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);\n    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);\n\n    vertex_shader = glCreateShader(GL_VERTEX_SHADER);\n    glShaderSource(vertex_shader, 1, &amp;vertex_shader_text, NULL);\n    glCompileShader(vertex_shader);\n\n    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);\n    glShaderSource(fragment_shader, 1, &amp;fragment_shader_text, NULL);\n    glCompileShader(fragment_shader);\n\n    program = glCreateProgram();\n    glAttachShader(program, vertex_shader);\n    glAttachShader(program, fragment_shader);\n    glLinkProgram(program);\n\n    mvp_location = glGetUniformLocation(program, &quot;MVP&quot;);\n    vpos_location = glGetAttribLocation(program, &quot;vPos&quot;);\n    vcol_location = glGetAttribLocation(program, &quot;vCol&quot;);\n\n    glEnableVertexAttribArray(vpos_location);\n    glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,\n        sizeof(vertices&#91;0]), (void*)0);\n    glEnableVertexAttribArray(vcol_location);\n    glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,\n        sizeof(vertices&#91;0]), (void*)(sizeof(float) * 2));\n\n    while (!glfwWindowShouldClose(window))\n    {\n        float ratio;\n        int width, height;\n        mat4x4 m, p, mvp;\n\n        glfwGetFramebufferSize(window, &amp;width, &amp;height);\n        ratio = width \/ (float)height;\n\n        glViewport(0, 0, width, height);\n        glClear(GL_COLOR_BUFFER_BIT);\n\n        mat4x4_identity(m);\n        mat4x4_rotate_Z(m, m, (float)glfwGetTime());\n        mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);\n        mat4x4_mul(mvp, p, m);\n\n        glUseProgram(program);\n        glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*)mvp);\n        glDrawArrays(GL_TRIANGLES, 0, 3);\n\n        glfwSwapBuffers(window);\n        glfwPollEvents();\n    }\n\n    glfwDestroyWindow(window);\n\n    glfwTerminate();\n    exit(EXIT_SUCCESS);\n}\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>ES <strong>3.2<\/strong>-related changes are highlighted.<\/li><\/ul>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p>6. Also this sample uses &#8220;<em>linmath.h<\/em>\u201d &#8211; a small library for linear math.<\/p>\n\n\n\nYou can download it <a href=\"https:\/\/writingagame.com\/img\/b01\/c03\/linmath.h\" download=\"\">here<\/a>.\n\n\n\n<p>Since we will use it in other projects too, let\u2019s place it <strong>outside <\/strong>of <em>a999hello <\/em>folder.<\/p>\n\n\n\n<p>In <strong>Windows File Explorer<\/strong> create a new folder for it: C:\\CPP\\<strong>engine<\/strong>\\<\/p>\n\n\n\n<p>Copy downloaded <em>linmath.h<\/em> file from <em>Downloads <\/em>directory to <\/p>\n\n\n\n<p><em>C:\\CPP\\engine\\<\/em><\/p>\n\n\n\n<p>In <strong>Visual Studio<\/strong> right-click on <strong>p_windows <\/strong>project -&gt; <em>Add -&gt; New <strong>Filter<\/strong><\/em>.<\/p>\n\n\n\n<p>Name &#8211; <strong>xEngine<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>&#8220;Filter&#8221; &#8211; is kind of virtual sub-folder inside of VS project.<\/li><li>&#8220;x&#8221; before &#8220;Engine&#8221; &#8211; just to keep it after &#8220;Source Files&#8221; (it will be <strong>after <\/strong>when You open VS next time).<\/li><\/ul>\n\n\n\n<p>Now &#8211; right-click on <em>xEngine <\/em>-&gt; <em>Add -&gt; <strong>Existing <\/strong>Item<\/em><\/p>\n\n\n\n<p><em>C:\\CPP\\engine\\<strong>linmath.h<\/strong><\/em><\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p>7. Also we need to add <em>glad.c<\/em> file (from GLAD download) to the project. <\/p>\n\n\n\n<p>Right-click on \u201c<strong>Source Files<\/strong>\u201d -&gt; <em>Add -&gt; <strong>Existing<\/strong> item<\/em><\/p>\n\n\n\n<p><em>C:\\CPP\\p_windows\\glad\\src\\<strong>glad.c<\/strong><\/em><\/p>\n\n\n\n<p><strong>Add<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<ol class=\"wp-block-list\" start=\"8\"><li>Now we need to include references to downloaded libraries.<\/li><\/ol>\n\n\n\n<p>Right-click on \u201c<strong>p_windows<\/strong>\u201d project -&gt; <em>Properties<\/em>.<\/p>\n\n\n\n<p><strong>IMPORTANT<\/strong>: Change Configuration from \u201cDebug\u201d to \u201c<strong>All configurations<\/strong>\u201d. Also, make sure that platform is set to <strong>Win32<\/strong> (x64 won&#8217;t work with GLFW32):<\/p>\n\n\n\n<p>Now navigate to <em>Configuration properties -&gt; C++ -&gt; General<\/em> and open <em>Additional Include Directories -&gt; Edit<\/em>:<\/p>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b01\/c03\/09.jpg\"><\/p>\n\n\n\n<p>In the Edit window add new line:<\/p>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b01\/c03\/10.jpg\"><\/p>\n\n\n\n<p> and browse to <em>C:\\CPP\\p_windows\\glad\\include<\/em>, <strong>Select Folder<\/strong> <\/p>\n\n\n\n<p>Then add another new line and navigate to<\/p>\n\n\n\n<p> <em>C:\\CPP\\p_windows\\glfw335win32\\include<\/em>, <strong>Select Folder<\/strong>.<\/p>\n\n\n\n<p>Add another new line and navigate to<\/p>\n\n\n\n<p><em>C:\\CPP\\engine<\/em>, <strong>Select Folder<\/strong>.<\/p>\n\n\n\n<p>Now we have:<\/p>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b01\/c03\/11.jpg\"><\/p>\n\n\n\n<p>Then \u2013 <strong>Ok<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p>9. Now navigate to <em>Configuration properties -&gt; Linker -&gt; General<\/em> and open<em> Additional Library Directories -&gt; Edit<\/em>.<\/p>\n\n\n\n<p>Add new line and navigate to <em>C:\\CPP\\p_windows\\glfw335win32\\lib-vc2022<\/em><\/p>\n\n\n\n<p><strong>Select Folder<\/strong>, then \u2013 <strong>Ok<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p>10. Now move to <em>Configuration properties -&gt; Linker -&gt; Input<\/em> and open <em>Additional Dependencies -&gt; Edit<\/em>.<\/p>\n\n\n\n<p>Copy-Paste following libraries:<\/p>\n\n\n\n<p><em>opengl32.lib; glfw3.lib; glfw3dll.lib<\/em><\/p>\n\n\n\n<p><strong>Ok, Apply, Ok<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p>11. One more thing: We don\u2019t want our resulting executable to be called \u201cp_windows.exe\u201d (as it is defined by project\/solution name). We can change it in project properties. Right-click on <strong>p_windows <\/strong>project -&gt; <em>Properties -&gt; Configuration Properties -&gt; General<\/em>, pick <em>Target name<\/em>. To change it &#8211; click arrow-down, then <em>Edit<\/em>. Change name to \u201c<em>OurProject<\/em>\u201d. Then \u2013 Ok, Apply, Ok.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p>12. Now let\u2019s try to run (green arrow).<\/p>\n\n\n\n<p>Make sure that selected platform (in the top menu) is set to <strong>x86<\/strong> (32 bit, x64 won&#8217;t work because of GLFW32).<br>Works:<\/p>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b01\/c03\/12.jpg\"><\/p>\n\n\n\n<p>Sample is running, but it has TWO windows: Console window AND Application window. The reason is that we didn\u2019t want to create our window the \u201cWindows way\u201d, that\u2019s why we picked \u201cConsole application\u201d and then created our window using GLFW. <\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">How to rid of Console window:<\/h2>\n\n\n\n<p>13. Actually, having <em>Console window<\/em> is quite beneficial, since It can handle printf statements (OpenGL window can\u2019t), which is priceless for development, so we\u2019ll better keep Console window in Debug configuration as is, but will rid of it in Release.<\/p>\n\n\n\n<p>Right-click on \u201cp_windows\u201d project, open Properties.<\/p>\n\n\n\n<p>Change Configuration to <strong>Release<\/strong>.<\/p>\n\n\n\n<p>Go to <em>Configuration Properties -&gt; Linker -&gt; System<\/em> and change <em>SubSystem<\/em> from Console to <strong>Windows<\/strong><\/p>\n\n\n\n<p>Apply, Ok.<\/p>\n\n\n\n<p>Now, if we will try to compile our program (just don\u2019t forget to switch to Release configuration) we\u2019ll get an error:<\/p>\n\n\n\n<p><em>Error LNK2001 unresolved external symbol _WinMain@16<\/em><\/p>\n\n\n\n<p>This is because now (after switch) linker is looking for a <em>WinMain()<\/em> entry point, not a <em>main()<\/em> one.<\/p>\n\n\n\n<p>If we want to keep our <strong>main()<\/strong> entry point (we do), we need to set the entry point to <em>mainCRTStartup<\/em> under Advanced Linker.<\/p>\n\n\n\n<p>So, again, open project Properties, <strong>Release <\/strong>configuration.<\/p>\n\n\n\n<p>Go to <em>Configuration Properties -&gt; Linker -&gt; Advanced<\/em>. Open <em>Entry Point -&gt; Edit<\/em>. Change to <strong>mainCRTStartup<\/strong><\/p>\n\n\n\n<p>Ok, Apply, Ok.<\/p>\n\n\n\n<p>Now Debug configuration works with Console window, Release \u2013 without.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b01\/c03\/13.jpg\"><\/p>\n\n\n\n<p><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n","protected":false},"excerpt":{"rendered":"<p class=\"mb-2\">Visual Studio, Windows, C++, OpenGL ES, GLFW, GLAD Using OpenGL ES on the PC is less straight forward than on Android. The reason is that GL ES is intended for mobile devices, NOT for desktops. Fortunately, solutions do exist. OpenGL producers strongly advise to use a window toolkit (GLFW) and an OpenGL loading libraries (GLAD). [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":214,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-82","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cross-platform-3d"],"_links":{"self":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/82","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=82"}],"version-history":[{"count":30,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/82\/revisions"}],"predecessor-version":[{"id":1620,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/82\/revisions\/1620"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/media\/214"}],"wp:attachment":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/media?parent=82"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/categories?post=82"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/tags?post=82"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}