<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ SpriteKit - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ SpriteKit - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 25 May 2026 05:07:04 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/spritekit/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ SpriteKit Advanced — How to build a 2,5D game (Part II) ]]>
                </title>
                <description>
                    <![CDATA[ By Luke Konior Intro This article shows how to write basic shaders in the SpriteKit. It’s split into two parts: first we play, then we learn. It also contains information how to use SKAttribute and SKAttributeValue classes that were added in iOS SDK ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/spritekit-advanced-how-to-build-a-2-5d-game-part-ii-30ddb613b568/</link>
                <guid isPermaLink="false">66c35f62b8711219e1e72dfb</guid>
                
                    <category>
                        <![CDATA[ Game Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ indie game ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SpriteKit ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sun, 01 Oct 2017 20:06:08 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*MYgdND4CCLf9eONh2LfRSg.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Luke Konior</p>
<h3 id="heading-intro">Intro</h3>
<p>This article shows how to write basic shaders in the SpriteKit. It’s split into two parts: first we play, then we learn.</p>
<p>It also contains information how to use <code>SKAttribute</code> and <code>SKAttributeValue</code> classes that were added in iOS SDK 10.0.</p>
<p>If you haven’t already read it, <a target="_blank" href="https://medium.freecodecamp.org/spritekit-advanced-how-to-build-a-2-5d-game-part-i-2dc76c7c65e2">here’s part 1 of this article series</a>.</p>
<h3 id="heading-prepare-the-project">Prepare the project</h3>
<p>Let’s get quick and dirty.</p>
<ul>
<li>Open XCode 8 and create a new project from template: iOS &gt; Game.</li>
<li>Open the <code>GameScene.sks</code> and remove the label in the center of the screen.</li>
<li>Download <a target="_blank" href="http://cosmicteapotgames.com/wp-content/uploads/2017/06/trees.png">this</a> and put it inside <code>Assets.xcassets</code></li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/MxZmGjoG9xkRbOf3TFew3ePoayMqXZd8qsQa" alt="Image" width="800" height="312" loading="lazy"></p>
<ul>
<li>Name it “Trees”</li>
<li>Open the <code>GameScene.m</code></li>
<li>remove all instance variables</li>
<li>remove all methods</li>
</ul>
<h3 id="heading-the-fragment-shader">The Fragment Shader</h3>
<p>Now we create an empty <strong>fragment <code>shader</code></strong> In XCode:</p>
<ul>
<li>In the Project Navigator select Supporting Files</li>
<li>Choose: File &gt; New &gt; File…</li>
<li>Select: Other &gt; Empty</li>
<li>Name it “<code>myShader.fsh</code>” and press Create.</li>
<li>Put this inside:</li>
</ul>
<pre><code><span class="hljs-comment">// currently a boring pass-thru shader void main( void ) { vec4 color = texture2D(utexture, vtexcoord); // here will emerge something worthy glFragColor = color;}</span>
</code></pre><p>Above fragment <code>shader</code> does nothing perceptible. Quick explanation:</p>
<ul>
<li><code>void main()</code><br>this function gets called for each pixel of the sprite and outputs color for that pixel<br>Gets input data from surrounding globals and must set the <code>gl_FragColor</code> variable</li>
<li><code>vec2</code>, <code>vec3</code>and <code>vec4</code> are the types similar to C's: <code>float array[2]</code>, <code>float array[3]</code> and <code>float array[4]</code></li>
<li>_u<em>texture</em> is a texture ID<br>Leave it alone :-)</li>
<li><code>v_tex_coord</code> is a <code>vec2</code> which contains our current position in texture</li>
<li><code>texture2D(tex , p)</code> is a function that returns color from texture <code>tex</code> in <code>point p</code> as <code>vec4</code><br>which contains rgba</li>
<li><code>gl_FragColor</code> is an output color<br>We must assign it a <code>vec4</code></li>
</ul>
<h3 id="heading-loading-code">Loading code</h3>
<p>What’s left is the loading code.</p>
<ul>
<li>Open the <code>GameScene.m</code></li>
<li>add method <code>-didMoveToView:</code></li>
</ul>
<pre><code>- (<span class="hljs-keyword">void</span>)didMoveToView:(SKView *)view {    <span class="hljs-comment">// 1. load the shader's source from myShaderFile.fsh    NSString *file = [[NSBundle mainBundle] pathForResource:@"myShader" ofType:@"fsh"];    NSString *sourceString = [NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil];            // 2. create the shader    SKShader *shader = [SKShader shaderWithSource:sourceString];        // 3. assign the shader to a newly created sprite node    SKSpriteNode *spriteNode = [SKSpriteNode spriteNodeWithImageNamed:@"Trees"];    spriteNode.shader = shader;        // 4. finally add the sprite to the scene    [self addChild:spriteNode];}</span>
</code></pre><p>Ensure that <code>myShader.fsh</code> figures in ProjectFile &gt; Target &gt; Build Phases &gt; Copy Bundle Resources!</p>
<p>You may now run the project on the iOS device. There shall be no errors in the XCode’s console and you should see a screen similar to this below:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/4TnLiWjcn9mTO94Y-lcdZ3L9Y46zJe7iKZUN" alt="Image" width="337" height="600" loading="lazy"></p>
<h3 id="heading-lets-play-a-bit">Let’s play a bit!</h3>
<p>Now is the fun part. We’ll replace the shader’s main function.</p>
<h3 id="heading-color-with-red-with-alpha-preservation">Color with red with alpha preservation</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/sGVOlBZaNhox2S1oXJutpLyAHMAKc-luelcG" alt="Image" width="337" height="600" loading="lazy"></p>
<pre><code><span class="hljs-keyword">void</span> main( <span class="hljs-keyword">void</span> ){    vec4 color = texture2D(u_texture, v_tex_coord);    float alpha = color.a;    gl_FragColor = vec4(<span class="hljs-number">1</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>, <span class="hljs-number">1.0</span>) * alpha; <span class="hljs-comment">//google "premultiplied alpha"}</span>
</code></pre><h3 id="heading-scale-down-by-2x">Scale down by 2x</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/L18M4oDhBB4a09tcqOz7LQk12QRaI45BzHEr" alt="Image" width="337" height="600" loading="lazy"></p>
<pre><code><span class="hljs-keyword">void</span> main( <span class="hljs-keyword">void</span> ){    vec4 color = texture2D(u_texture, v_tex_coord * <span class="hljs-number">2.0</span>);    gl_FragColor = color;}
</code></pre><h3 id="heading-swap-colors-after-1-second">Swap colors after 1 second</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/szn2VF1e3TpEyod6Vvc2kPXaqP5P9AqBt1sb" alt="Image" width="270" height="480" loading="lazy"></p>
<pre><code><span class="hljs-keyword">void</span> main( <span class="hljs-keyword">void</span> ){    vec4 color = texture2D(u_texture, v_tex_coord);    float alpha = color.a;    float phase = mod(u_time, <span class="hljs-number">3</span>);    vec3 outputColor = color.rgb;    <span class="hljs-keyword">if</span> (phase &lt; <span class="hljs-number">1.0</span>) {        outputColor = color.bgr;    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (phase &lt; <span class="hljs-number">2.0</span>) {        outputColor = color.brg;    }    gl_FragColor = vec4(outputColor, <span class="hljs-number">1.0</span>) * alpha;}
</code></pre><h3 id="heading-colorize-over-time">Colorize over time</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/eOR06sIrv-Gja1ymP6RCgb-un73qHSOFuzgb" alt="Image" width="270" height="480" loading="lazy"></p>
<pre><code><span class="hljs-keyword">void</span> main( <span class="hljs-keyword">void</span> ){    vec4 color = texture2D(u_texture, v_tex_coord);    float alpha = color.a;    float r = (sin(u_time+ <span class="hljs-number">3.14</span> * <span class="hljs-number">0.00</span>)+<span class="hljs-number">1.0</span>)*<span class="hljs-number">0.5</span>;    float g = (sin(u_time+ <span class="hljs-number">3.14</span> * <span class="hljs-number">0.33</span>)+<span class="hljs-number">1.0</span>)*<span class="hljs-number">0.5</span>;    float b = (sin(u_time+ <span class="hljs-number">3.14</span> * <span class="hljs-number">0.66</span>)+<span class="hljs-number">1.0</span>)*<span class="hljs-number">0.5</span>;    gl_FragColor = vec4(r,g,b, <span class="hljs-number">1.0</span>) * alpha;}
</code></pre><h3 id="heading-waves">Waves</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/nOcOdOxNc3mt-y8ZLgmJlFFLHYcLFLbarzbN" alt="Image" width="270" height="480" loading="lazy"></p>
<pre><code><span class="hljs-keyword">void</span> main( <span class="hljs-keyword">void</span> ){    float deltaX = sin(v_tex_coord.y*<span class="hljs-number">3.14</span>*<span class="hljs-number">10</span> + u_time * <span class="hljs-number">4</span>)*<span class="hljs-number">0.01</span>;    vec2 coord = v_tex_coord;    coord.x = coord.x + deltaX;    vec4 color = texture2D(u_texture, coord);    gl_FragColor = color;}
</code></pre><h3 id="heading-new-attributes">New Attributes</h3>
<p>At WWDC 2016 Apple introduced an important update to SpriteKit — the <code>SKAttribute</code> and <code>SKAttributeValue</code> classes.</p>
<p>Before this SDK update, if we wanted to pass custom parameters into the <code>shader</code> program, we had to pass the data through a uniform value.</p>
<p>This had two serious drawbacks:</p>
<ul>
<li>every uniform change caused shader recompilation</li>
<li>shader program handled every sprite in the exact same way</li>
</ul>
<p>For example: if we wanted to dye a group of sprites red, and one of them blue, we had two ways. First we create two separate <code>SKShader</code> instances and change our custom <code>myColor</code> uniform.</p>
<p>Second we make one <code>shader</code> instance and change its uniform which causes a recompilation.</p>
<p>Both ways cannot be drawn on same pass. And the second one requires complex management code.</p>
<p>SDK 10.0 introduced the <code>SKAttribute</code> and <code>SKAttributeValue</code> classes. These two allow (finally!) passing data to the shader programs without recompilation. The usage algorithm is simple:</p>
<ul>
<li><p>The shader part:</p>
</li>
<li><p>Create a shader program<br><code>SKShader</code></p>
</li>
<li>Create an array of <code>SKAttributes</code></li>
<li><p>Assign array of attributes to the shader program</p>
</li>
<li><p>The <code>sprite</code> part:</p>
</li>
<li><p>Assign the shader program to a sprite</p>
</li>
<li>Assign a dictionary of <code>SKAttributeValues</code></li>
</ul>
<h3 id="heading-example-with-attributes">Example with attributes</h3>
<p>In the last example, we’ll add two more sprites. Every one of them will have the same shader program and will differ only in attributes. Let’s modify the <em>-</em><code>didMoveToView: inGameScene.m:</code></p>
<pre><code>- (<span class="hljs-keyword">void</span>)didMoveToView:(SKView *)view {    NSString *file = [[NSBundle mainBundle] pathForResource:@<span class="hljs-string">"myShader"</span> ofType:@<span class="hljs-string">"fsh"</span>];    NSString *sourceString = [NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil];    SKShader *shader = [SKShader shaderWithSource:sourceString];        <span class="hljs-comment">// 1. Add a custom attribute to shader    SKAttribute *attrProgress = [SKAttribute attributeWithName:@"THE_MIGHTY_DARK_FACTOR" type:SKAttributeTypeFloat];    shader.attributes = @[attrProgress];    // 2. Create tree sprites    NSArray *trees = @[                       [self createTreeWithShader:shader mightyFactor:0.3f zPosition:1],                       [self createTreeWithShader:shader mightyFactor:0.6f zPosition:2],                       [self createTreeWithShader:shader mightyFactor:0.9f zPosition:3],                       ];    for (SKSpriteNode *tree in trees) {        [self addChild:tree];    }}- (SKSpriteNode*)createTreeWithShader:(SKShader*)shader mightyFactor:(CGFloat)mightyFactor zPosition:(CGFloat)zPosition {    SKSpriteNode *treeNode = [SKSpriteNode spriteNodeWithImageNamed:@"Trees"];    treeNode.shader = shader;    // 3. Fill the custom attribute on the sprite    treeNode.attributeValues = @{@"THE_MIGHTY_DARK_FACTOR": [SKAttributeValue valueWithFloat:mightyFactor]};    treeNode.zPosition = zPosition;return treeNode;}</span>
</code></pre><p>… and the shader program:</p>
<pre><code><span class="hljs-keyword">void</span> main( <span class="hljs-keyword">void</span> ){    vec4 color = texture2D(u_texture, v_tex_coord * (<span class="hljs-number">2.5</span> * THE_MIGHTY_DARK_FACTOR));    float alpha = color.a;    vec3 baseColor = color.rgb * THE_MIGHTY_DARK_FACTOR;    gl_FragColor = vec4(baseColor, <span class="hljs-number">1.0</span>) * alpha;}
</code></pre><p>... and see the parameterized result!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/BqTQUZBmVKfeJI4C97kqJR2gX3VyispHHaep" alt="Image" width="337" height="600" loading="lazy"></p>
<h3 id="heading-caveats">Caveats</h3>
<ul>
<li>The shader’s source code is typically loaded from a <code>.fsh</code> file to a plain <code>NSString</code><br>This code must compile on the target device during the runtime<br>no buildtime checks!</li>
<li>Older devices may use different version of OpenGL ES so beware GLSL syntax differences!<br>In Raft Challenge’s case there was the need to replace <code>__constant</code> (valid in OpenGL ES 3.0) to <code>const</code> for OpenGL ES 2.0.</li>
<li>It’s a good idea to keep a reference to SKShader object somewhere and reuse it as frequently as needed to avoid visible frame rate drop<br>While allocation and shader compilation takes less than 1/60 sec, it may become a huge burden in render loop</li>
<li>When using SpriteKit’s Texture Atlases be cautious of <code>vtexcoord</code><br>XCode may rotate some textures which swap <code>X</code> and <code>Y</code> axis<br><strong>Color modification is safe, geometry is not</strong></li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Nh9NYKX2tYvNvLca66dRsJAQTY7CmGd2EhqL" alt="Image" width="800" height="353" loading="lazy"></p>
<h3 id="heading-summary">Summary</h3>
<p>We learned by examples how to use fragment shaders in the Sprite Kit. We added parameters to sprites so our shader program can render every instance in a different way without any performance loss.</p>
<p>The <a target="_blank" href="http://cosmicteapotgames.com/wp-content/uploads/2017/06/ShaderDemo.zip">complete project</a> is available for a download.</p>
<p>You can <a target="_blank" href="https://medium.freecodecamp.org/spritekit-advanced-how-to-build-a-2-5d-game-part-iii-e058b99cfbc3">read part 3 of this series here</a>.</p>
<p>About the author: Kamil Ziętek is an iOS Developer at <a target="_blank" href="http://www.allinmobile.co">www.allinmobile.co</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ SpriteKit Advanced — How to build a 2,5D game (Part I) ]]>
                </title>
                <description>
                    <![CDATA[ By Luke Konior Intro This article is about graphical evolution of Raft Challenge from the prototype to the final product. It’s AIM-ed for the people who are thinking about making their own game with graphics like Raft, but don’t know exactly how to s... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/spritekit-advanced-how-to-build-a-2-5d-game-part-i-2dc76c7c65e2/</link>
                <guid isPermaLink="false">66c35f60e9895571912a0d2f</guid>
                
                    <category>
                        <![CDATA[ Game Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mobile app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SpriteKit ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sun, 01 Oct 2017 20:04:38 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*UfZWvFeWyuKgOIlkuU1log.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Luke Konior</p>
<h3 id="heading-intro">Intro</h3>
<p>This article is about graphical evolution of <a target="_blank" href="https://itunes.apple.com/app/apple-store/id1073887270?pt=117756562&amp;ct=Develop%20Articles&amp;mt=8">Raft Challenge</a> from the prototype to the final product. It’s <a target="_blank" href="https://www.allinmobile.co">AIM</a>-ed for the people who are thinking about making their own game with graphics like Raft, but don’t know exactly how to start.</p>
<h3 id="heading-the-very-beginning-of-raft-challenge">The very beginning of Raft Challenge</h3>
<p>Raft Challenge was born during the first hackathon organized by <a target="_blank" href="https://www.allinmobile.co">All In Mobile</a>. The idea was to make a game where a player avoids obstacles. We wanted to keep things as simple as possible.</p>
<p>After the weekend, we had a prototype that looked like this:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/2IVkfJ6Zhe1RZbQhi-7d7ofu1jjmQwxdyjFD" alt="Image" width="237" height="422" loading="lazy"></p>
<p>Raft Challenge won the hackathon. The company announced that it’ll make the resources to improve the game.</p>
<h3 id="heading-lets-make-it-25d">Let’s make it 2,5D!</h3>
<p>At the start of the project, Raft had the simplest possible graphics. A view was directly over a flat ground texture, with colored circles that indicated the player and the enemies. It was beautiful and as simple as the code underneath. Then our <a target="_blank" href="https://dribbble.com/allinmobile">graphic designer</a> came and messed up everything. He said, “Let’s make it 2,5D!”. The challenge was accepted and the animation above was the result.</p>
<p>After the hackathon he showed up once again. This time it was something more than one sentence.</p>
<p>It was an evil smile and this video:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/EUGZnxZdfPYruZCbvOQYer-2Mg858pUe4RrA" alt="Image" width="260" height="462" loading="lazy"></p>
<h3 id="heading-perspective-explained">Perspective explained</h3>
<p>Ok, let’s drop the act :-). I’ve wanted to give him the feeling that he’s in charge. But I’m the boss here! The perspective is easy to implement in code, regardless of what 2D engine we use.</p>
<p>First, we have to determine where we want to put the <a target="_blank" href="https://en.wikipedia.org/wiki/Perspective_%28graphical%29#One-point_perspective">vanishing point</a>. The example below shows this point in the center of the canvas.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/7-ygj-gLXH3jM-z430XHGVEtxqgsvOqfMQXa" alt="Image" width="260" height="462" loading="lazy"></p>
<p>Raft Challenge has this point in the upper half of the screen, because the sky and everything overhead isn’t as important as obstacles on the river.</p>
<p>How are the sprites themselves made? While it may be obvious for someone with artistic background, it isn’t necessarily clear for a technical person.</p>
<p>There are two rules:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/W9bUzPWIZwFZdXJRvUm4swbWjMlOoXbrmMOR" alt="Image" width="225" height="600" loading="lazy"></p>
<ul>
<li>Moving parts must be drawn along the helper lines as shown above<br>All those lines intersect in the vanishing point</li>
</ul>
<p><strong>Note:</strong> The coast part isn’t reaching the vanishing point. It stops somewhere in the middle, leaving the transparent area behind.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/8L66ks8EFml12WsVuZzyiA791N7pKWx0-cX6" alt="Image" width="403" height="500" loading="lazy"></p>
<ul>
<li>That empty area between the graphic and the vanishing point has an important purpose<br>It’ll hold elements that are further away.</li>
</ul>
<p>Those parts are made by applying a twice smaller scale for each step. The resulting image should be seamless if the texture is well-made.</p>
<h3 id="heading-assembling-the-scene">Assembling the scene</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/e2CuoGVjG4UBNTO1rKtcGs1ySZUw7lMwTwF3" alt="Image" width="685" height="530" loading="lazy"></p>
<p>After we’ve prepared all our assets, we need to put them all into the scene.</p>
<p>Let’s see how it looks in Raft Challenge.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/BtVv7dU8oH3xX-xccye5FxzcIhMaC3wpAcf8" alt="Image" width="692" height="940" loading="lazy"></p>
<p>Starting from the bottom:</p>
<ol>
<li><p>Background layers<br>Background<br>Grass<br>Fog bottom<br>Sun<br>Mountains<br>Horizon Line</p>
</li>
<li><p>These layers are all static they don’t move</p>
</li>
<li>Background acts for both the sky and water</li>
<li>The background is a plain gradient<br>It’s stretched to fill the entire device’s screen<br>The aspect ratio is ignored</li>
<li>We may merge layers other than Background for increased performance unless we want to change some properties</li>
<li><p>We may move the sun during the gameplay<br>or replace mountains for something different</p>
</li>
<li><p>Perspective layers<br>Trees with reflections<br>Coast<br>Obstacles</p>
</li>
<li><p>For the clarity of the image above, layers with similar content were grouped<br>There were:<br>2 layers of Obstacles<br>8 layers of Coast<br>8 layers of Trees with reflections</p>
</li>
<li>These layers are scaled up by 2 when a player is moving forward</li>
<li><p>Order of these layers depends on<br>distance<br>closer ones are on top<br>priority<br>Obstacle &gt; Coast &gt; Trees</p>
</li>
<li><p>Character</p>
</li>
<li><p>If an Obstacle is in the closest possible position, it may have z-position higher than the Character itself<br>In this case, the Obstacle covers the Character, which is desirable</p>
</li>
<li><p>GUI</p>
</li>
<li><p>Good graphics should depend on illusions and tricks instead of hardware</p>
</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/N9yKZLZ8BBoBIfjSzyLjf1sxUdx8h08DPUtT" alt="Image" width="337" height="600" loading="lazy"></p>
<h3 id="heading-summary">Summary</h3>
<p>This article should give us an idea how to approach the problem of making assets to a 2,5D game and organizing them into a scene.</p>
<p>You can read <a target="_blank" href="https://medium.freecodecamp.org/spritekit-advanced-how-to-build-a-2-5d-game-part-ii-30ddb613b568">part 2 of this series here</a>.</p>
<p>About the author: Kamil Ziętek is an iOS Developer at <a target="_blank" href="http://www.allinmobile.co">www.allinmobile.co</a></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
