<?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" version="2.0"><channel><title><![CDATA[Yogendra's blog]]></title><description><![CDATA[Yogendra's blog]]></description><link>https://blogs.yogendramanawat.com</link><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 11:22:53 GMT</lastBuildDate><atom:link href="https://blogs.yogendramanawat.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to Chroma key in Godot]]></title><description><![CDATA[https://youtu.be/zKX3F8OnaLA
 
Chroma key, commonly known as the “green screen” or “blue screen” effect, allows you to remove a specific color from an image or video and replace it with another background. This effect is widely used in video producti...]]></description><link>https://blogs.yogendramanawat.com/how-to-chroma-key-in-godot</link><guid isPermaLink="true">https://blogs.yogendramanawat.com/how-to-chroma-key-in-godot</guid><category><![CDATA[Godot]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[indiedev]]></category><category><![CDATA[Chroma Key]]></category><dc:creator><![CDATA[Yogendra Manawat]]></dc:creator><pubDate>Sat, 29 Jul 2023 15:47:04 GMT</pubDate><content:encoded><![CDATA[<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/zKX3F8OnaLA">https://youtu.be/zKX3F8OnaLA</a></div>
<p> </p>
<p>Chroma key, commonly known as the “green screen” or “blue screen” effect, allows you to remove a specific color from an image or video and replace it with another background. This effect is widely used in video production to composite different elements together seamlessly.</p>
<h3 id="heading-how"><strong>How?</strong></h3>
<p>We will achieve the chroma key effect by writing a custom shader in GDScript and using a <code>VideoStreamPlayer</code> node to display the video content.</p>
<p>I think, instead of knowing what to write in shader it is important to know Why?</p>
<p>So, Have a look at this RGB space :</p>
<p><img src="https://cdn-images-1.medium.com/max/1000/1*OGqnIJbTDOjWX-3OYX_iCQ.png" alt class="image--center mx-auto" /></p>
<p>In this RGB space, each color is represented by a set of three numerical values serving as coordinates. For instance, the color green is expressed as (76, 153, 0), where these values are denoted as (R, G, B).</p>
<p><img src="https://cdn-images-1.medium.com/max/1000/1*olnAjhDthjlSvb_V-K9OZQ.png" alt class="image--center mx-auto" /></p>
<p>Our next step involves selecting a color from the editor. Afterward, we will remove all pixels that match this color. However, it’s important to note that the entire green screen won’t be entirely composed of just this exact color; there may be varying shades of green. To address this, we will consider color values close to this chosen green color in the 3D color space and set a limit on how far we can deviate from this color in space.</p>
<h3 id="heading-scene-setup"><strong>Scene Setup</strong></h3>
<p>Ensure that the scene contains a <code>VideoStreamPlayer</code> node to play the video and a <code>Control</code> node to hold the UI elements for controlling the chroma key effect.</p>
<p><img src="https://cdn-images-1.medium.com/max/1000/1*L7rkH3SuikXCN9ZhqR9oTg.png" alt class="image--center mx-auto" /></p>
<p><strong>HSlider1</strong> is to control the <code>pickup_range</code> how far we can go from the chosen color. </p>
<p><strong>HSlider2</strong> is to control the <code>fade</code> effect to smoothly discard the pixels near the chosen colors.</p>
<h3 id="heading-writing-the-custom-shader"><strong>Writing the Custom Shader</strong></h3>
<p>To implement the chroma key effect, follow these steps:</p>
<p>1. Select the <code>VideoStreamPlayer</code> node in the scene and go to its properties. Under <code>CanvasItem &gt; Material</code>, create a new shader named <code>ChromaKeyShader.gdshader</code></p>
<p>2. In the <code>ChromaKeyShader.gdshader</code> file, write the custom shader code as shown below:</p>
<pre><code class="lang-plaintext">shader_type canvas_item;

// Uniform variables for chroma key effect
uniform vec3 chroma_key_color : source_color = vec3(0.0, 1.0, 0.0);
uniform float pickup_range : hint_range(0.0, 1.0) = 0.1;
uniform float fade_amount : hint_range(0.0, 1.0) = 0.1;

void fragment() {
    // Get the color from the texture at the given UV coordinates
    vec4 color = texture(TEXTURE, UV);

    // Calculate the distance between the current color and the chroma key color
    float distance = length(color.rgb - chroma_key_color);

    // If the distance is within the pickup range, discard the pixel
    // The lesser the distance, the more likely the colors are similar
    if (distance &lt;= pickup_range) {
        discard;
    }

    // Calculate the fade factor based on the pickup range and fade amount
    float fade_factor = smoothstep(pickup_range, pickup_range + fade_amount, distance);

    // Set the output color with the original RGB values and the calculated fade factor
    COLOR = vec4(color.rgb, fade_factor);
}
</code></pre>
<h4 id="heading-shader-explanation">Shader Explanation:</h4>
<p>The shader uses the distance calculation to identify pixels close to our chosen chroma key color and discards them, effectively removing the selected color. Pixels that are slightly further away from the chroma key color are faded based on the fade_factor, blending them smoothly with the surrounding colors. This process creates the desired chroma key effect, making it appear as if the background has been replaced with another image or video.</p>
<h3 id="heading-ui-controls"><strong>UI Controls</strong></h3>
<p>To allow users to manipulate the chroma key effect in real-time, I created sliders in the <code>Control</code> node. The <code>Control</code> node’s script contains the following functions:</p>
<pre><code class="lang-plaintext">extends Control

func _on_color_picker_button_color_changed(color):
    # Update the "chroma_key_color" shader parameter of the VideoStreamPlayer's material
    $VideoStreamPlayer.material.set("shader_parameter/chroma_key_color", color)

func _on_h_slider_value_changed(value):
    # Update the "pickup_range" shader parameter of the VideoStreamPlayer's material
    $VideoStreamPlayer.material.set("shader_parameter/pickup_range", value)

func _on_h_slider_2_value_changed(value):
    # Update the "fade_amount" shader parameter of the VideoStreamPlayer's material
    $VideoStreamPlayer.material.set("shader_parameter/fade_amount", value)

func _on_video_stream_player_finished():
    # Restart the video playback when it's finished
    $VideoStreamPlayer.play()
</code></pre>
<p>also make sure that the range of the sliders are appropriate, my settings are :</p>
<p><img src="https://cdn-images-1.medium.com/max/1000/1*asP-Hbp1TJVOE6k6Ay573A.png" alt /></p>
<p>Also you can set steps by hint_range in the shader.</p>
<pre><code class="lang-plaintext">hint_range(MIN_VALUE, MAX_VALUE, STEPS)
</code></pre>
<h3 id="heading-signal-handling"><strong>Signal Handling</strong></h3>
<p>Connect the appropriate signal from the UI elements to the <code>Control</code> node’s script. you created in the <code>Control</code> node’s script to control the chroma key effect. These signal handlers will update the shader’s uniform variables in response to user input.</p>
<p>Connect sliders change signal to the sliders, finished signal to VideoStreamPlayer and Color changed to the ColorPicker.</p>
<h3 id="heading-woah"><strong>Woah!</strong></h3>
<p>Save and run the scene to see the chroma key effect in action! With the provided UI controls, you can now adjust the chroma key color, pickup range, and fade amount in real-time, achieving the desired chroma key functionality for your video content.</p>
]]></content:encoded></item><item><title><![CDATA[Endless game in Godot 4.0]]></title><description><![CDATA[https://www.youtube.com/watch?v=wVo9m_KsGlc
 
How did it all start?
One day, while exploring the world of games, I got an idea in my mind — an endless game similar to some other endless arcade games. Inspired and motivated, I took action to bring thi...]]></description><link>https://blogs.yogendramanawat.com/endless-game-in-godot-40</link><guid isPermaLink="true">https://blogs.yogendramanawat.com/endless-game-in-godot-40</guid><category><![CDATA[indiedev]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[Godot]]></category><dc:creator><![CDATA[Yogendra Manawat]]></dc:creator><pubDate>Wed, 19 Jul 2023 17:18:14 GMT</pubDate><content:encoded><![CDATA[<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=wVo9m_KsGlc">https://www.youtube.com/watch?v=wVo9m_KsGlc</a></div>
<p> </p>
<h1 id="heading-how-did-it-all-start"><strong>How did it all start?</strong></h1>
<p>One day, while exploring the world of games, I got an idea in my mind — an endless game similar to some other endless arcade games. Inspired and motivated, I took action to bring this game to life. In this blog post, I will walk you through the exciting development process of this game in Godot 4.0. Join me as we dive into the player movement, level generation, collision detection, and more!</p>
<h1 id="heading-1-the-dance-of-the-star"><strong>1. The Dance of the Star</strong></h1>
<p>To begin, I needed to tackle the player's movement mechanics. To visualize I used traditional pen and paper ideation, I visualized two primary positions for the player, one above a line and another below it.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:875/1*a-qzFWhd4I4hNP9ncwDOUA.gif" alt /></p>
<p><strong>Calculating Player Positions</strong><br />To make it responsive for future and different devices, I made two positions :</p>
<pre><code class="lang-plaintext">#above point
startPosition = (x, screenHeight/4)

#below point
targetPosition = (x, 3*(screenHeight/4))
</code></pre>
<p><strong>Movement Pattern</strong><br />The player will move between these two points. so when the player will move to startPosition to targetPosition then next time the previous startPosition is the targetPosition these time and previous targetPosition is now startPosition to make these functionality i made a function to toggle between these two positions:</p>
<pre><code class="lang-plaintext">func toggle_movement():
  var temp = startPosition
  startPosition = targetPosition
  targetPosition = temp
</code></pre>
<p><strong>Finally the movement</strong><br />To make player move i used a Vector2 offset that will add up to the position of player and make the player reach to the targetPosition from startPosition. I made this movement to trigger with a key on pressing the key i make the moveDistance = targetPosition-startPosition which is also equal to the screenHeight/2. and i’m moving player till the distance get 0.</p>
<pre><code class="lang-plaintext">func _physics_process():
  if (moveDistance &gt; 0):
    position += offset
    moveDistance -= offset
</code></pre>
<p>but again there is thing that my offset should also invert after a movement because in one movement I have to go from up to down so +offset and when go from down to up -offset.</p>
<p><strong>Invert Offset</strong><br />To implement this I made an extra statement in toggle_movement() function to multiply the offset every time we toggle movement.</p>
<pre><code class="lang-plaintext">func toggle_movement():
  offset*=Vector2(1, -1)

  #also can do it like this
  offset.y *= (-1)
</code></pre>
<h1 id="heading-2-endless-level-generation"><strong>2. Endless Level Generation</strong></h1>
<p>Creating an endless level was another crucial aspect of the game. I wanted to generate random lines and obstacles for a better gameplay experience.<br />As the Godot is and open source engine and v4.0 is newer there is no specific tutorial for different things you wanna do. But there is an approach maximum people follow which is repeating blocks.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:875/1*Wd2fMqHV2Qy4RFVVhX1yqQ.gif" alt /></p>
<p><strong>Repeating blocks approach</strong><br />If I were to use this approach, I could create a level within a node and repeat that node alongside the previous one. However, in doing so, I would encounter a challenge — repeating the same pattern and difficulty over and over again. so for generating more random level, I got an idea.</p>
<p><strong>Grid-based(TileMap) approach</strong><br />I was sitting in my college lectures and getting bored so I picked up my game and started ideating the things, How to? and my lecture was more productive than ever before, haha kidding, not kidding.<br />I decided to use a grid-based approach. Each cell in the grid represented a tile, allowing for flexible level generation.</p>
<p>In TileMap we can set a tile to any cell we want by using the coordinates, just like a 2d grid. So I calculated an y_index from the screenHeight which lies in between the screen, approximately if not exact.</p>
<p>Then I just need to place my tiles at (x, y_index). now what is x? and what it should be? So the x is the x axis of the tile that is about to be generated I named this next_tile_position and after generating a tile I increased it.</p>
<p><strong>Placing line and obstacles</strong><br />Now I figured out how and where the tiles to be placed, but which tile? I have two tiles one is my “Line” tile and another is “Obstacle”. So my logic was that i can generate the lines consecutively but obstacles to be alternatively.</p>
<p>So I thought why not place some random lines first and then place an obstacle? So I took a random value range (1,5) and generated the lines and then I generated an obstacle tile.</p>
<pre><code class="lang-plaintext">var value = randi_range(1,5)
for i in range(value):
    set_cell(next_tile_position, lineTileIndex)
    next_tile_position.x += 1
set_cell(next_tile_position, obstacleTileIndex)
next_tile_position += 1
</code></pre>
<p>This is a pseudo code for the generation of cells.<br />here the lineTileIndex and the obstacleTileIndex are the index of the tiles in TileSet. If you want to know more about it, follow <a target="_blank" href="https://docs.godotengine.org/en/stable/classes/class_tilemap.html">here</a>.</p>
<p><strong>Dynamic Tile Management</strong><br />To ensure optimal performance, I implemented dynamic tile management. I’m generating the tiles that are next to the screen and deleting assed tiles from the grid, reducing memory consumption.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:875/1*n1G4KG8UpqMOw6VPwJuVvQ.gif" alt /></p>
<p>To do this I simply maintained a prev_tile_position as well and erased that cell with the erase_cell() method.</p>
<p>used a simple approach to check whether the next_tile_position is in the screen or out and whether the prev_tile_position is in the screen or out of the screen and performed accordingly.</p>
<pre><code class="lang-plaintext">if next_tile_position.x &lt; (playerPosition.x + screenWidth):
  generate_tiles()

if prev_tile_position.x &lt; playerPosition.x - 2*tile_size.x:
  remove_cells()
</code></pre>
<h1 id="heading-3-collision-and-the-fateful-encounter"><strong>3. Collision and the Fateful Encounter</strong></h1>
<p>As the game gained shape and form, I wanted to add behavior to the player and tiles. Collision detection emerged as a vital component, an encounter between the player and the obstacles.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:875/1*34b23odEBXeVZDYNvKAhCQ.gif" alt /></p>
<p>Now the problem here is that maybe Godot does not provide any inbuilt functionality for the tiles as the area_entered() thing, which will emit a signal and the game will know that I collided with an obstacle or line. It’s completely fair because these tiles are used to generate static levels but I used it in another way.</p>
<p>So now I cracked all of the things and created all but now what? So again I thought of an idea that calculates the cell coordinates by the player’s position and then matches it with any of the tiles. But I just knew that there is a function to get the coordinates of the physics body when it collides with the tile.</p>
<p>If the player collides with any of the tiles, I will check whether it is the line or the obstacle. and we can check this by simply comparing the indexes of both tiles.</p>
<pre><code class="lang-plaintext">var playerCell= cell(playerPosition)
var tileI = get_cell_id(playerCell)
  if tileI == LineTileIndex:
    Game over
  if tileI == obstacleTileIndex:
    Destory obstacle and increase score
</code></pre>
<p>Thanks a lot for taking the time to read.<br />Here is the game:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://yogendram.itch.io/star-dodge">https://yogendram.itch.io/star-dodge</a></div>
<p> </p>
<p>by the way here are my secret notes to make a game like this.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:875/1*U35jZGg4r6l2WIJoLABA8g.jpeg" alt /></p>
]]></content:encoded></item></channel></rss>