<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Patrick O'Dacre</title>
    <description>The latest articles on DEV Community by Patrick O'Dacre (@patrickodacre).</description>
    <link>https://dev.to/patrickodacre</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F26307%2F1b6d9afc-4de0-475d-a6bf-f723e3855b4a.png</url>
      <title>DEV Community: Patrick O'Dacre</title>
      <link>https://dev.to/patrickodacre</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/patrickodacre"/>
    <language>en</language>
    <item>
      <title>Variables, Data Types, and Functions - Learn to Code Part 2</title>
      <dc:creator>Patrick O'Dacre</dc:creator>
      <pubDate>Fri, 06 Jan 2023 10:48:28 +0000</pubDate>
      <link>https://dev.to/patrickodacre/variables-data-types-and-functions-learn-to-code-part-2-20bg</link>
      <guid>https://dev.to/patrickodacre/variables-data-types-and-functions-learn-to-code-part-2-20bg</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/JlpSO1-m_bo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compiler: a program to turn your code into something your computer can understand and execute.&lt;/li&gt;
&lt;li&gt;Variables: a variable is a construct that allows you to store and use data throughout your program.&lt;/li&gt;
&lt;li&gt;Data Types: data types help your program understand the type or kind of data you use in your program.&lt;/li&gt;
&lt;li&gt;Functions: a construct that wraps or contains a set of instructions for the computer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Compiler
&lt;/h2&gt;

&lt;p&gt;The Odin compiler, itself a program, turns your written Odin code into something the computer can understand. The computer cannot understand your program as you have written it. The compiler must turn it into "machine code."&lt;/p&gt;

&lt;p&gt;Type &lt;code&gt;odin run main.odin -file&lt;/code&gt; into your console to "build" and "execute" your program.&lt;/p&gt;

&lt;h2&gt;
  
  
  Variables
&lt;/h2&gt;

&lt;p&gt;Variables are "names" you give a piece of data in your program.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;first_name : string = "Patrick"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we have a variable named "first_name," and the value of that variable is "Patrick."&lt;/p&gt;

&lt;p&gt;Instead of typing "Patrick" everywhere in our program, we can use the variable. Then, if we need to change the first name to something else, we only need to change the value once.&lt;/p&gt;

&lt;p&gt;Variables can be assigned to a value once or multiple times.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;first_name : string = "Patrick"

first_name = "Not Patrick"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you update a variable with a new value, that value must be of the same "type."&lt;/p&gt;

&lt;p&gt;What is a data type?&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Types
&lt;/h2&gt;

&lt;p&gt;Data types describe what "type" of data you have. They are necessary for your compiler to understand what your program can and cannot do.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=JlpSO1-m_bo"&gt;This video&lt;/a&gt; covers three different data types:&lt;/p&gt;

&lt;p&gt;1) strings&lt;br&gt;
2) integer&lt;br&gt;
3) floats&lt;/p&gt;

&lt;p&gt;These types help the compiler understand that you can perform arithmetic on numbers and floats, not strings.&lt;/p&gt;
&lt;h3&gt;
  
  
  Strings
&lt;/h3&gt;

&lt;p&gt;Strings are text in double quotations. Odin distinguishes between double and single quotation marks, so make sure your strings are in double quotation marks.&lt;/p&gt;

&lt;p&gt;Strings can contain letters, numbers, and symbols.&lt;/p&gt;

&lt;p&gt;When you write numbers in double quotation marks, they are considered a string, not a number. Some languages automatically convert numbers in quotation marks (a string) into a number type to perform arithmetic, but thankfully Odin doesn't do that. Unfortunately, automatic conversion can be problematic -- it doesn't teach you to think carefully about your data types.&lt;/p&gt;
&lt;h3&gt;
  
  
  Integers
&lt;/h3&gt;

&lt;p&gt;Integers are whole numbers. There are different types of integers -- some small, others large; some can be negative, and others only positive.&lt;/p&gt;

&lt;p&gt;When first learning, you will likely use &lt;code&gt;int&lt;/code&gt; most often. It is the default integer type. Depending on your system, &lt;code&gt;int&lt;/code&gt; with either be 32-bits or 64-bits in size.&lt;/p&gt;

&lt;p&gt;64-bit numbers are larger than 32-bit numbers.&lt;/p&gt;

&lt;p&gt;The maximum number allowed in 64 bits of memory space would be 9,223,372,036,854,775,807, allowing for negative numbers, or (2^64)-1 (inclusive), allowing for only positive numbers.&lt;/p&gt;

&lt;p&gt;If your machine is a 32-bit machine, the largest would be 2,147,483,647, allowing for negative numbers, or 4,294,967,295, allowing for only positive numbers.&lt;/p&gt;

&lt;p&gt;In game programming, x and y positional coordinates will be an integer type because positions on a screen are pixels, and you cannot have less than a whole pixel.&lt;/p&gt;
&lt;h3&gt;
  
  
  Floats
&lt;/h3&gt;

&lt;p&gt;Floats are similar to integers, but they allow for decimals. If you require more precision in your arithmetic, floats are the type you want to use.&lt;/p&gt;

&lt;p&gt;In game programming, fine movement speed calculation will be in floats and later rounded to whole numbers to determine x and y positioning.&lt;/p&gt;
&lt;h2&gt;
  
  
  Functions
&lt;/h2&gt;

&lt;p&gt;In this video, we practice writing some new functions. Our functions accept &lt;code&gt;arguments&lt;/code&gt;. Arguments are pieces of data we can pass to our function, so it can use that data to do its work.&lt;/p&gt;

&lt;p&gt;Notice that we specify the data type for each function argument because Odin cannot infer the data type of an argument.&lt;/p&gt;

&lt;p&gt;Odin often can infer a data type by the value assigned to a variable, but it is different with function signatures.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// Odin infers that str is of type "string"
str := "Hello, World"

// Odin must be told that the my_arg argument is of type "string"
my_print_str :: proc(my_arg: string)
{}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Practice
&lt;/h2&gt;

&lt;p&gt;This video contains examples of printing different data types to the console. Take a look at the &lt;a href="http://odin-lang.org/docs/overview/"&gt;Odin Documentation&lt;/a&gt; to examine other data types. Practice creating variables of different types and print those to the console.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>codenewbie</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Learn to Code with Odin Programming Language - Introduction</title>
      <dc:creator>Patrick O'Dacre</dc:creator>
      <pubDate>Fri, 06 Jan 2023 10:35:50 +0000</pubDate>
      <link>https://dev.to/patrickodacre/learn-to-code-with-odin-programming-language-introduction-ga5</link>
      <guid>https://dev.to/patrickodacre/learn-to-code-with-odin-programming-language-introduction-ga5</guid>
      <description>

&lt;p&gt;I started learning to code back in 2015. I started with PHP and JavaScript, and I had a great time.&lt;/p&gt;

&lt;p&gt;This is my attempt to explain programming to my younger self using a lower-level language -- Odin. &lt;/p&gt;

&lt;p&gt;Odin is a modern, systems-level programming language that is simple to use and easy to learn. &lt;/p&gt;

&lt;p&gt;Programming simple games using Odin is a lot easier and less complicated than webdev, hence a great way to learn to program.&lt;/p&gt;




&lt;h1&gt;
  
  
  Introduction to Programming
&lt;/h1&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/9Z91u7Qwg0A"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Before we start, we must go over a few new terms.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Package - a collection of .odin files within a given folder in your program.&lt;/li&gt;
&lt;li&gt;Function - a construct that wraps or contains a set of instructions for the computer.&lt;/li&gt;
&lt;li&gt;Program Entry Point - the first function ran or called by the computer when executing your program.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Package
&lt;/h2&gt;

&lt;p&gt;A Package is a folder or directory that contains .odin files for your program.&lt;/p&gt;

&lt;p&gt;Consider the following folder structure:&lt;/p&gt;

&lt;p&gt;-&amp;gt; my-program/main.odin&lt;br&gt;
-&amp;gt; my-program/types.odin&lt;br&gt;
-&amp;gt; my-program/map.odin&lt;br&gt;
-&amp;gt; my-program/entities/player.odin&lt;br&gt;
-&amp;gt; my-program/entities/enemy.odin&lt;/p&gt;

&lt;p&gt;In this example, the root folder of your program has three files -- main.odin, types.odin, and map.odin. All of these files are in the same Package. You can name Packages anything you want, but all three files must share the same Package name. We'll use "main" because that is what you see in the Odin documentation.&lt;/p&gt;

&lt;p&gt;The sub-folder "entities" has two files. These files also share a Package, but this Package is distinct from the "main" Package. Therefore, we must give this Package a different name. We'll call this sub-folder / Package "entities."&lt;/p&gt;

&lt;p&gt;Our files will look like this:&lt;/p&gt;

&lt;p&gt;// main.odin&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

main :: proc()
{

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;// types.odin&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

// code

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;// map.odin&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

// code

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;// entities/player.odin&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package entities

// code

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;// entities/enemy.odin&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package entities

// code

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next thing we must understand is the "function."&lt;/p&gt;

&lt;h2&gt;
  
  
  Functions
&lt;/h2&gt;

&lt;p&gt;Functions contain one or more instructions for the computer to run, and they are "run" or "called" by typing the function name, followed by brackets: &lt;code&gt;somefunction()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can write functions in different ways. Here are some examples of how you can write &lt;code&gt;somefunction&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;1) &lt;code&gt;some_function()&lt;/code&gt;&lt;br&gt;
2) &lt;code&gt;Some_Function()&lt;/code&gt;&lt;br&gt;
3) &lt;code&gt;someFunction()&lt;/code&gt;&lt;br&gt;
4) &lt;code&gt;some_function()&lt;/code&gt;&lt;br&gt;
5) &lt;code&gt;some_function_2()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And many more. Except for the underscore, function names cannot contain any other special symbols or punctuation, nor can they begin with a number.&lt;/p&gt;
&lt;h2&gt;
  
  
  Program Entry Point
&lt;/h2&gt;

&lt;p&gt;Every program your computer runs has an Entry Point. The entry point to your odin program is the &lt;code&gt;main()&lt;/code&gt; function. Your program may only have one &lt;code&gt;main()&lt;/code&gt; function. It is the first function that runs, and your program will end when this function has finished executing all of its code.&lt;/p&gt;

&lt;p&gt;Many programs you use -- games, photoshop, a web browser -- stay open for a long time. They stay open for a long time because their &lt;code&gt;main()&lt;/code&gt; functions don't end until you tell them to end. In a later part, we'll look at how games continue to run indefinitely.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using Other People's Code with "import"
&lt;/h2&gt;

&lt;p&gt;Programming languages have a "standard library" or "core library." A "library" is code written by someone else and intended for others to use. A "standard" or "core" library is a library of code that comes with the programming language and contains functions and other things needed in most programs. For example, one such library or Package in Odin is "fmt."&lt;/p&gt;

&lt;p&gt;We use other Packages by "importing" them into our file. Here is an example of importing the "fmt" package into our &lt;code&gt;main.odin&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package main

import "core:fmt"

main :: proc()
{
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "fmt" package defines a function called &lt;code&gt;println()&lt;/code&gt;. &lt;code&gt;println()&lt;/code&gt; allows us to print data to the console screen. Since &lt;code&gt;println()&lt;/code&gt; is in the "fmt" package and now our "main" Package, you must prefix the function with the package name like so &lt;code&gt;fmt.println()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Type the following in your &lt;code&gt;main.odin&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package main

import "core:fmt"

main :: proc()
{
    fmt.println("Hello, World")
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now in your console, type &lt;code&gt;odin run main.odin - file&lt;/code&gt; in the project's root folder, and you will see "Hello, World" printed on the console screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practice
&lt;/h2&gt;

&lt;p&gt;Practice printing different things on the screen. You can change the text or even try printing some numbers. How about some arithmetic like &lt;code&gt;fmt.println(2+2)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Experiment and see what happens.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>codenewbie</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Space Shooter Game with SDL2 and Odin - Part 8 - Enemies Attack!</title>
      <dc:creator>Patrick O'Dacre</dc:creator>
      <pubDate>Thu, 05 Jan 2023 07:33:45 +0000</pubDate>
      <link>https://dev.to/patrickodacre/space-shooter-game-with-sdl2-and-odin-part-8-enemies-attack-1hgl</link>
      <guid>https://dev.to/patrickodacre/space-shooter-game-with-sdl2-and-odin-part-8-enemies-attack-1hgl</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/BfetmRros2M"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youtu.be/BfetmRros2M"&gt;YouTube Video&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/channel/UCKXSHFNc-5D9i3heHkHgeUg"&gt;YouTube Channel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.libsdl.org/CategoryAPI"&gt;SDL2 Core Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/odin-lang/Odin/wiki"&gt;Odin Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this guide we'll go through the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create &amp;amp;&amp;amp; Fire Drone Lasers&lt;/li&gt;
&lt;li&gt;Show Entity hitboxes&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Create &amp;amp;&amp;amp; Fire Drone Lasers
&lt;/h2&gt;

&lt;p&gt;We'll create a fixed number of lasers for the drones to use. Much like with our own laser, a drone laser won't fire unless it is available -- &lt;code&gt;health == 0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We need to implement two separate timers -- one master timer, and another for each individual drone. These two timers help us control the number of drone lasers firing at the player.&lt;/p&gt;

&lt;p&gt;We'll add a &lt;code&gt;ready&lt;/code&gt; field to the &lt;code&gt;Entity&lt;/code&gt; struct to control the laser fire-rate of individual drones, and the &lt;code&gt;drone_laser_cooldown&lt;/code&gt; field to the &lt;code&gt;Game&lt;/code&gt; struct as our master timer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
NUM_OF_DRONE_LASERS :: 5

Game :: struct
{
    /// Other stuff ^^^
    /// new
    drone_laser_tex: ^SDL.Texture,
    drone_lasers: [NUM_OF_DRONE_LASERS]Entity,
    drone_laser_cooldown : f64,
}

Entity :: struct
{
    source: SDL.Rect,
    dest: SDL.Rect,
    dx: f64,
    dy: f64,
    health: int,
    ready: f64,
}

create_entities :: proc()
{
    /// create drones ^^

    // drone lasers
    game.drone_laser_tex = SDL_Image.LoadTexture(game.renderer, "assets/drone_laser_1.png")
    assert(game.drone_laser_tex != nil, SDL.GetErrorString())
    drone_laser_w : i32
    drone_laser_h : i32
    SDL.QueryTexture(game.drone_laser_tex, nil, nil, &amp;amp;drone_laser_w, &amp;amp;drone_laser_h)

    for _, idx in 1..=NUM_OF_DRONE_LASERS
    {

        game.drone_lasers[idx] = Entity{
            dest = SDL.Rect{
                x = -100,
                y = -100,
                w = drone_laser_w / 8,
                h = drone_laser_h / 6,
            },
            dx = DRONE_LASER_SPEED,
            dy = DRONE_LASER_SPEED,
            health = 0,
        }
    }


    ///
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The drone lasers aren't shaped quite like I want, so I skew the image by changing the &lt;code&gt;w&lt;/code&gt; and &lt;code&gt;h&lt;/code&gt; a bit to get it as close to round as I can.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fire Lasers
&lt;/h3&gt;

&lt;p&gt;We'll allow drones to fire when within certain boundaries and the cooldown timer has expired:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
if drone.dest.x &amp;gt; 30 &amp;amp;&amp;amp;
drone.dest.x &amp;lt; (WINDOW_WIDTH - 30) &amp;amp;&amp;amp;
drone.ready &amp;lt;= 0 &amp;amp;&amp;amp;
game.drone_laser_cooldown &amp;lt; 0
{
    // fire
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We check this each time we render a drone.&lt;/p&gt;

&lt;p&gt;If the drone's individual timer has expired, ie: &lt;code&gt;drone.ready &amp;lt; 0&lt;/code&gt; then we'll look for the first available drone laser to "fire":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// find a drone laser:
fire_drone_laser : for laser, idx in &amp;amp;game.drone_lasers
{

    // find the first one available
    if laser.health == 0
    {
        // fire
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Drones need to shoot towards our player, so we'll have to calculate a &lt;code&gt;dx&lt;/code&gt; and &lt;code&gt;dy&lt;/code&gt; value that will lead the laser from the position of the drone to the current position of the player:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// fire from the drone's position
laser.dest.x = drone.dest.x
laser.dest.y = drone.dest.y
laser.health = 1

new_dx, new_dy := calc_slope(
    laser.dest.x,
    laser.dest.y,
    game.player.dest.x,
    game.player.dest.y,
    )

if !game.is_paused
{
    laser.dx = new_dx * get_delta_motion(drone.dx + 150)
    laser.dy = new_dy * get_delta_motion(drone.dx + 150)
}

// reset the cooldown to prevent firing too rapidly
drone.ready = DRONE_LASER_COOLDOWN_TIMER_SINGLE
game.drone_laser_cooldown = DRONE_LASER_COOLDOWN_TIMER_ALL

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, we're also careful to reset our timers.&lt;/p&gt;

&lt;p&gt;Now, each time this active laser is rendered, it will move according to the calculated &lt;code&gt;dx&lt;/code&gt; and &lt;code&gt;dy&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Render Drone Lasers -- check collisions -&amp;gt; render
for laser, idx in &amp;amp;game.drone_lasers
{

    if laser.health == 0 do continue

    // check collision based on previous frame's rendered position
    // check player health to make sure drone lasers don't explode
    // while we're rendering our stage_reset() scenes after a player
    // has already died.
    if game.player.health &amp;gt; 0
    {
        hit := collision(
            game.player.dest.x,
            game.player.dest.y,
            game.player.dest.w,
            game.player.dest.h,

            laser.dest.x,
            laser.dest.y,
            laser.dest.w,
            laser.dest.h,
            )

        if hit
        {
            laser.health = 0

            if !game.is_invincible
            {
                explode_player(&amp;amp;game.player)
            }
        }
    }

    if !game.is_paused
    {
        laser.dest.x += i32(laser.dx)
        laser.dest.y += i32(laser.dy)
    }

    // reset laser if it's offscreen
    // checking x and y b/c these drone
    // lasers go in different directions
    if laser.dest.x &amp;lt;= 0 ||
    laser.dest.x &amp;gt;= WINDOW_WIDTH ||
    laser.dest.y &amp;lt;= 0 ||
    laser.dest.y &amp;gt;= WINDOW_HEIGHT
    {
        laser.health = 0
    }

    if laser.health &amp;gt; 0
    {
        when HITBOXES_VISIBLE do render_hitbox(&amp;amp;laser.dest)
        SDL.RenderCopy(game.renderer, game.drone_laser_tex, &amp;amp;laser.source, &amp;amp;laser.dest)
    }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Show Entity hitboxes
&lt;/h2&gt;

&lt;p&gt;To help with visualizing how our collisions are working, let's add a little utility to outline our collision areas.&lt;/p&gt;

&lt;p&gt;We'll add a flag that will be checked at compile time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
HITBOXES_VISIBLE :: false

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll add this helper function to render a red rectangle at a given destination &lt;code&gt;SDL.Rect&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
render_hitbox :: proc(dest: ^SDL.Rect)
{
    r := SDL.Rect{ dest.x, dest.y, dest.w, dest.h }

    SDL.SetRenderDrawColor(game.renderer, 255, 0, 0, 255)
    SDL.RenderDrawRect(game.renderer, &amp;amp;r)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can pass in any entity &lt;code&gt;SDL.Rect&lt;/code&gt; to get an outline of their collision boundaries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
if laser.health &amp;gt; 0
{
    when HITBOXES_VISIBLE do render_hitbox(&amp;amp;laser.dest)
    SDL.RenderCopy(game.renderer, game.laser_tex, nil, &amp;amp;laser.dest)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>gamedev</category>
      <category>sdl2</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Space Shooter Game with SDL2 and Odin - Part 7 - Shooting Drones</title>
      <dc:creator>Patrick O'Dacre</dc:creator>
      <pubDate>Wed, 04 Jan 2023 20:51:37 +0000</pubDate>
      <link>https://dev.to/patrickodacre/space-shooter-game-with-sdl2-and-odin-part-7-shooting-drones-4abp</link>
      <guid>https://dev.to/patrickodacre/space-shooter-game-with-sdl2-and-odin-part-7-shooting-drones-4abp</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/XWrkAyu27og"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youtu.be/XWrkAyu27og"&gt;YouTube Video&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/channel/UCKXSHFNc-5D9i3heHkHgeUg"&gt;YouTube Channel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.libsdl.org/CategoryAPI"&gt;SDL2 Core Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/odin-lang/Odin/wiki"&gt;Odin Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shooting drones involves these 4 steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fire Laser&lt;/li&gt;
&lt;li&gt;Respawn Drones&lt;/li&gt;
&lt;li&gt;Iterate Lasers -- Detect Collisions, Move, and Render&lt;/li&gt;
&lt;li&gt;Iterate Drones -- Move and Render&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While the collision detection code is what decides what has been hit, I found I had to complete these 4 steps in the proper way to make the collision detection work as I expected.&lt;/p&gt;

&lt;p&gt;I was careful to move entities only AFTER collision detection is completed. If collisions are checked against positions not yet rendered, then it looks like the drones are being destroyed too early. In other words, I based my collisions on the positions last visible to the player.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fire Laser
&lt;/h2&gt;

&lt;p&gt;We finished this portion of the code in a previous part of the series.&lt;/p&gt;

&lt;p&gt;Firing a laser means resetting its position from RIGHT offscreen to the player's position, so it will be rendered in a straight path from this new starting position.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// FIRE LASERS
if game.fire &amp;amp;&amp;amp; !(game.laser_cooldown &amp;gt; 0)
{
    // find a laser:
    fire : for laser in &amp;amp;game.lasers
    {
        // find the first one available
        if laser.health == 0
        {

            laser.dest.x = game.player.dest.x + 20
            laser.dest.y = game.player.dest.y
            laser.health = 1
            // reset the cooldown to prevent firing too rapidly
            game.laser_cooldown = LASER_COOLDOWN_TIMER

            break fire
        }
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Respawn Drones
&lt;/h2&gt;

&lt;p&gt;This was also completed in a previous part of the series.&lt;/p&gt;

&lt;p&gt;Spawning a drone means resettings its position from the LEFT offscreen to the RIGHT where it can begin a new flight path moving towards the LEFT again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// Spawn Drones
respawn : for drone in &amp;amp;game.drones
{

    if drone.health == 0 &amp;amp;&amp;amp; !(game.drone_spawn_cooldown &amp;gt; 0)
    {
        drone.dest.x = WINDOW_WIDTH
        drone.dest.y = i32(rand.float32_range(120, WINDOW_HEIGHT - 120))
        drone.health = 1

        game.drone_spawn_cooldown = DRONE_SPAWN_COOLDOWN_TIMER

        break respawn
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we fire our weapon and respawn drones, we need to move onto updating laser and drone positions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Iterate Lasers -- Detect Collisions, Move, and Render
&lt;/h2&gt;

&lt;p&gt;For every laser in flight we need to check each active drone to see if their positions overlap. If their positions overlap, then we know the laser has hit the drone. For now we'll consider a single hit a kill shot, but later we can experiment with multiple hits.&lt;/p&gt;

&lt;p&gt;Our collision detection looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
collision :: proc(x1, y1, w1, h1, x2, y2, w2, h2: i32) -&amp;gt; bool
{
    return (max(x1, x2) &amp;lt; min(x1 + w1, x2 + w2)) &amp;amp;&amp;amp; (max(y1, y2) &amp;lt; min(y1 + h1, y2 + h2))
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're checking the dimensions of 2 rectangles to see if any portion overlaps. If there is an overlap, then we have a collision.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// Check collisions and render lasers
for laser in &amp;amp;game.lasers
{

    if laser.health == 0
    {
        continue
    }

    detect_collision : for drone in &amp;amp;game.drones
    {

        if drone.health == 0
        {
            continue
        }

        hit := collision(
            laser.dest.x,
            laser.dest.y,
            laser.dest.w,
            laser.dest.h,

            drone.dest.x,
            drone.dest.y,
            drone.dest.w,
            drone.dest.h
            )

        if hit
        {

            drone.health = 0
            laser.health = 0

            break detect_collision
        }

    }

    if laser.health &amp;gt; 0
    {
        laser.dest.x += i32(get_delta_motion(laser.dx))
        SDL.RenderCopy(game.renderer, game.laser_tex, nil, &amp;amp;laser.dest)
    }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If our laser doesn't collide with any drone, we can move and render the laser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Iterate Drones -- Move and Render
&lt;/h2&gt;

&lt;p&gt;As before, all surviving drones are moved and rendered in a single step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
for drone in &amp;amp;game.drones
{

    if drone.health &amp;gt; 0
    {
        drone.dest.x -= i32(get_delta_motion(drone.dx))
        SDL.RenderCopy(game.renderer, game.drone_tex, nil, &amp;amp;drone.dest)
    }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Challenges
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Implement more interesting flight behavior for the drones.&lt;/li&gt;
&lt;li&gt;Only destroy drones once they've been hit numerous times.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>gamedev</category>
      <category>sdl2</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to Render Dynamic Text with SDL2</title>
      <dc:creator>Patrick O'Dacre</dc:creator>
      <pubDate>Thu, 29 Dec 2022 20:47:08 +0000</pubDate>
      <link>https://dev.to/patrickodacre/how-to-render-dynamic-text-with-sdl2-4l5b</link>
      <guid>https://dev.to/patrickodacre/how-to-render-dynamic-text-with-sdl2-4l5b</guid>
      <description>&lt;p&gt;The Code :: &lt;a href="https://github.com/patrickodacre/sdl2-odin-examples/tree/master/render-dynamic-text"&gt;https://github.com/patrickodacre/sdl2-odin-examples/tree/master/render-dynamic-text&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/rlH8KMLrrWo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;This is a method I came up with for rendering dynamic text.&lt;/p&gt;

&lt;p&gt;By "dynamic" I mean text that isn't known at compile time -- text that comes from keyboard input events.&lt;/p&gt;

&lt;p&gt;This is a fairly simple example -- things like word-wrapping and line breaks aren't handled.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you haven't already read the guide on Rendering Static Text, please do so before reading this one.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Texture Map
&lt;/h2&gt;

&lt;p&gt;First, we create a &lt;code&gt;map&lt;/code&gt; so we can lookup textures for numbers, letters, and other symbols.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// create a map of chars that be used in make_word
create_chars :: proc()
{

    chars := " ?!@#$%^&amp;amp;*();:',.@_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

    for c in chars[:]
    {
        str := utf8.runes_to_string([]rune{c})
        defer delete(str)

        game.chars[c] = create_text(cstring(raw_data(str)))
    }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our map and related &lt;code&gt;Text&lt;/code&gt; struct are defined and initialized like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Text :: struct
{
    tex: ^SDL.Texture,
    dest: SDL.Rect,
}

Game :: struct
{
    // existing code..

    chars: map[rune]Text,
}

game := Game{
    chars = make(map[rune]Text),
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create the &lt;code&gt;Text&lt;/code&gt; objects stored in our &lt;code&gt;game.chars&lt;/code&gt; map we use the &lt;code&gt;create_text&lt;/code&gt; function from the last guide:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;COLOR_WHITE : SDL.Color : {255,255,255,255}

// create textures for the given str
// optional scale param allows us to easily size the texture generated
// relative to the current game.font_size
create_text :: proc(str: cstring, scale: i32 = 1) -&amp;gt; Text
{
    // create surface
    surface := SDL_TTF.RenderText_Solid(game.font, str, COLOR_WHITE)
    defer SDL.FreeSurface(surface)

    // create texture to render
    texture := SDL.CreateTextureFromSurface(game.renderer, surface)

    // destination SDL.Rect
    dest_rect := SDL.Rect{}
    SDL_TTF.SizeText(game.font, str, &amp;amp;dest_rect.w, &amp;amp;dest_rect.h)

    // scale the size of the text
    dest_rect.w *= scale
    dest_rect.h *= scale

    return Text{tex = texture, dest = dest_rect}
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This map of &lt;code&gt;Text&lt;/code&gt; objects helps us when it comes time to render the text we capture from the TEXTINPUT event.&lt;/p&gt;

&lt;p&gt;We render our captured text in our game loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
game_loop : for
{

    if SDL.PollEvent(&amp;amp;event)
    {
        if end_game(&amp;amp;event) do break game_loop

        handle_events(&amp;amp;event)
    }


    // START update and render

    char_spacing : i32 = 2
    prev_chars_w : i32 = 0

    starting_x : i32 = 100
    starting_y : i32 = 100

    // iterate characters in the string
    for c in game.text_input
    {
        // grab the texture for the single character
        char : Text = game.chars[c]

        // render this character after the previous one
        char.dest.x = starting_x + prev_chars_w
        char.dest.y = starting_y

        SDL.RenderCopy(game.renderer, char.tex, nil, &amp;amp;char.dest)

        prev_chars_w += char.dest.w + char_spacing
    }

    // END update and render

    draw_scene()
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our render code goes through each character in a string -- &lt;code&gt;game.text_input&lt;/code&gt;, finds its corresponding texture in our texture map, then renders that texture next to the previous one. Using &lt;code&gt;prev_chars_w&lt;/code&gt; allows us to keep track of where to place our current character as we iterate through all characters in the string.&lt;/p&gt;

&lt;p&gt;But how do we capture the text input from the keyboard?&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking Keyboard Input
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
handle_events :: proc(event: ^SDL.Event)
{

    scancode := event.key.keysym.scancode

    if event.type == SDL.EventType.TEXTINPUT
    {
        input := cstring(raw_data(event.text.text[:]))
        game.text_input = strings.concatenate({game.text_input, string(input)})
    }

    if scancode == .BACKSPACE
    {
        //
    }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our &lt;code&gt;handle_events()&lt;/code&gt; function we handle all TEXTINPUT events to grab the text from &lt;code&gt;event.text.text&lt;/code&gt;. It's necessary to transform the text slice to a cstring to strip out any odd characters -- &lt;code&gt;cstring(raw_data(event.text.text[:]))&lt;/code&gt;. We then concatenate the current string with the new input. &lt;code&gt;strings.concatenate({game.text_input, string(input)})&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we make a mistake, deleting the last character is easy. We take a slice of the current string being sure to leave off the last character in the string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
handle_events :: proc(event: ^SDL.Event)
{

    scancode := event.key.keysym.scancode

    if event.type == SDL.EventType.TEXTINPUT
    {
        //
    }

    if scancode == .BACKSPACE
    {
        if len(game.text_input) &amp;gt; 0
        {
            input := game.text_input[:len(game.text_input) -1]
            game.text_input = input
        }
    }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  StartTextInput(), StopTextInput(), and SetTextInputRect()
&lt;/h2&gt;

&lt;p&gt;Solid information on these functions is hard to find. They don't seem necessary for running this on Windows, though perhaps they are necessary for running a program on a phone, or accepting non-English text.&lt;/p&gt;

&lt;p&gt;If you have more information to shed some light on these functions, please share.&lt;/p&gt;

</description>
      <category>sdl2</category>
      <category>gamedev</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to Render Static Text with SDL2</title>
      <dc:creator>Patrick O'Dacre</dc:creator>
      <pubDate>Thu, 29 Dec 2022 20:44:45 +0000</pubDate>
      <link>https://dev.to/patrickodacre/how-to-render-static-text-with-sdl2-51l8</link>
      <guid>https://dev.to/patrickodacre/how-to-render-static-text-with-sdl2-51l8</guid>
      <description>&lt;ul&gt;
&lt;li&gt;The Code :: &lt;a href="https://github.com/patrickodacre/sdl2-odin-examples/tree/master/render-static-text"&gt;https://github.com/patrickodacre/sdl2-odin-examples/tree/master/render-static-text&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/tsyYXuWapsU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;To render the text to the screen we still require our game loop. I've tried to move as much of that boilerplate / secondary code outside of the &lt;code&gt;main&lt;/code&gt; function so you can focus on what is necessary for rendering text.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initializing the SDL TrueType Font Library
&lt;/h2&gt;

&lt;p&gt;As with all SDL libraries, we need to initialize the TTF library before we can use it, and this includes chosing the font we want to use for the text textures we want to render. For our example we'll use the Terminal font.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
init_font := SDL_TTF.Init()
assert(init_font == 0, SDL.GetErrorString())
game.font = SDL_TTF.OpenFont("Terminal.ttf", game.font_size)
assert(game.font != nil, SDL.GetErrorString())

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating Textures from Our Chosen Text
&lt;/h2&gt;

&lt;p&gt;Next we'll create a helper function for creating our text textures:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// create textures for the given str
// optional scale param allows us to easily size the texture generated
create_text :: proc(str: cstring, scale: i32 = 1) -&amp;gt; Text
{
    // create surface
    surface := SDL_TTF.RenderText_Solid(game.font, str, COLOR_WHITE)
    defer SDL.FreeSurface(surface)

    // create texture to render
    texture := SDL.CreateTextureFromSurface(game.renderer, surface)

    // destination SDL.Rect
    dest_rect := SDL.Rect{}
    SDL_TTF.SizeText(game.font, str, &amp;amp;dest_rect.w, &amp;amp;dest_rect.h)

    // scale the size of the text
    dest_rect.w *= scale
    dest_rect.h *= scale

    return Text{tex = texture, dest = dest_rect}
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the exception of the text itself and the sizing, the code is the same for creating each texture. Using this helper function allows us to avoid typing the same code again and again.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Text Struct
&lt;/h3&gt;

&lt;p&gt;Notice the &lt;code&gt;create_text&lt;/code&gt; function returns a new object -- &lt;code&gt;Text&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Text :: struct
{
    tex: ^SDL.Texture,
    dest: SDL.Rect,
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This struct holds a reference to our &lt;code&gt;texture&lt;/code&gt; and the &lt;code&gt;SDL.Rect&lt;/code&gt; used to render the texture to the window.&lt;/p&gt;

&lt;p&gt;What is a texture? It is the object we render to the window in the rectangular space designated by the &lt;code&gt;SDL.Rect&lt;/code&gt; created. It is created from the &lt;code&gt;cstring&lt;/code&gt; text we want to display in our chosen font.&lt;/p&gt;

&lt;p&gt;We're creating these textures before our loop. We only need to create our texture once for a given size; there's no need to recreate these textures on each game loop iteration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
game.texts[TextId.Title] = create_text("Testing", 3)
game.texts[TextId.SubTitle] = create_text("One, Two, Three")

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TextId Enum
&lt;/h3&gt;

&lt;p&gt;To help keep track of our Text objects we're storing each in an enumerated array with easy-to-read lookup keys that are enum variants.&lt;/p&gt;

&lt;p&gt;Enums, or Enumeration Types, define a new type with the values we choose. In our case we have a type of &lt;code&gt;TypeId&lt;/code&gt; with possible values &lt;code&gt;Title&lt;/code&gt; and &lt;code&gt;SubTitle&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When we want to render one of our text textures, we just have to get it from our array and tell SDL where to render it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
title := game.texts[TextId.Title]
// render roughly at the center of the window
title.dest.x = (WINDOW_WIDTH / 2) - (title.dest.w / 2)
title.dest.y = (WINDOW_HEIGHT / 2) - (title.dest.h)
SDL.RenderCopy(game.renderer, title.tex, nil, &amp;amp;title.dest)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Changing Font Size
&lt;/h3&gt;

&lt;p&gt;There are two ways we change the font size after we set it with &lt;code&gt;SDL_TTF.OpenFont()&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Re-setting the font_size using &lt;code&gt;SDL_TTF.SetFontSize()&lt;/code&gt; and recreating any textures.&lt;/li&gt;
&lt;li&gt;Scaling our destination SDL.Rect to which we render our texture.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>sdl2</category>
      <category>gamedev</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to Do Things With SDL2</title>
      <dc:creator>Patrick O'Dacre</dc:creator>
      <pubDate>Fri, 09 Dec 2022 11:29:19 +0000</pubDate>
      <link>https://dev.to/patrickodacre/how-to-do-things-with-sdl2-kid</link>
      <guid>https://dev.to/patrickodacre/how-to-do-things-with-sdl2-kid</guid>
      <description>&lt;p&gt;Today I started a new project for sharing concise examples on how to do things with &lt;a href="https://github.com/patrickodacre/sdl2-odin-examples"&gt;SDL2 and the Odin programming language&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'm on a mission to help others program games from scratch. I publish content for complete beginners to programming, and those just new to game programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beginners Learning to Code
&lt;/h2&gt;

&lt;p&gt;Most people interested in learning how to code end up learning to program in the context of web development.&lt;/p&gt;

&lt;p&gt;While web development can be fun, it is complex, and beginners are usually forced to learn a lot of secondary technology before they can start writing interesting programs.&lt;/p&gt;

&lt;p&gt;In the earlier days of computing, many skilled programmers got their start by programming their own games. It is a fun, creative, challenging, and very effective way to learn how to code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn to Code by Making Games
&lt;/h2&gt;

&lt;p&gt;If you'd like to learn how to code, follow me on &lt;a href="https://www.youtube.com/@handmadegamesdev"&gt;YouTube&lt;/a&gt; and &lt;a href="https://twitter.com/_handmadegames"&gt;Twitter&lt;/a&gt;. I'm really busy making a mix of beginner and intermediate-level content to help you learn programming in a unique and fun way.&lt;/p&gt;

</description>
      <category>codenewbie</category>
      <category>odinlang</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Space Shooter Game with SDL2 and Odin - Part 6 - Spawning Enemy Drones</title>
      <dc:creator>Patrick O'Dacre</dc:creator>
      <pubDate>Fri, 09 Dec 2022 11:03:30 +0000</pubDate>
      <link>https://dev.to/patrickodacre/space-shooter-game-with-sdl2-and-odin-part-6-spawning-enemy-drones-g16</link>
      <guid>https://dev.to/patrickodacre/space-shooter-game-with-sdl2-and-odin-part-6-spawning-enemy-drones-g16</guid>
      <description>&lt;h1&gt;
  
  
  Part 6 :: Spawning Enemies
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youtu.be/5ccarSklfVM"&gt;YouTube Video&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/channel/UCKXSHFNc-5D9i3heHkHgeUg"&gt;YouTube Channel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.libsdl.org/CategoryAPI"&gt;SDL2 Core Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/odin-lang/Odin/wiki"&gt;Odin Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/odin-lang/Odin/blob/master/core/math/rand/rand.odin"&gt;Odin Math Rand Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/5ccarSklfVM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In this part we'll focus on spawning some enemy drones. For now, they'll have unrestricted access to the galaxy, but later on we'll be sure to change that.&lt;/p&gt;

&lt;p&gt;The logic to spawn the enemies isn't too complicated, and it gives us an opportunity get more familiar with Odin's Math library. The Rand package will allow us to make our enemies a little more interesting.&lt;/p&gt;

&lt;p&gt;We'll have to make some changes to our Entity struct again. The changes will allow us more fine control over how our enemy drones move.&lt;/p&gt;

&lt;p&gt;Now let's complete the following tasks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add new constants and Game struct fields for our drones&lt;/li&gt;
&lt;li&gt;Create Drones&lt;/li&gt;
&lt;li&gt;Spawn Drones&lt;/li&gt;
&lt;li&gt;Give Drones variable speeds&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Drone Struct Fields and Constants
&lt;/h2&gt;

&lt;p&gt;It's best to follow the same ordering of the constants and Game struct fields added for our lasers. I often try to stick to conventions / ordering like this to make it easier on my eyes to read through the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LASER_SPEED : f64 : 700
LASER_COOLDOWN_TIMER : f64 : 50
NUM_OF_LASERS :: 100

// NEW
DRONE_SPEED : f64 : 700
DRONE_SPAWN_COOLDOWN_TIMER : f64 : 700
NUM_OF_DRONES :: 10
// END NEW

Game :: struct
{
    // ...

    laser_tex: ^SDL.Texture,
    lasers: [NUM_OF_LASERS]Entity,
    fire: bool,
    laser_cooldown : f64,

    // NEW
    drone_tex: ^SDL.Texture,
    drones: [NUM_OF_DRONES]Entity,
    drone_spawn_cooldown: f64,
    // END NEW
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these settings we limit the number of drones that may appear on the screen at the same time to 10. We also use a cooldown timer to make sure drones don't spawn too quickly. We decrement the cooldown timer using our delta multiplier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// TIMERS
game.laser_cooldown -= get_delta_motion(LASER_SPEED)
// NEW
game.drone_spawn_cooldown -= get_delta_motion(DRONE_SPEED)
// END NEW

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can play around with these settings until you get the number of enemies and speeds you like. In the future, these settings can be dynamically changed based on game level changes or other events.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating our Enemy Drones
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;create_entities()&lt;/code&gt; procedure we create our drones after creating our lasers. Again, we try and follow the same pattern as with creating our lasers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// drones
drone_texture := SDL_Image.LoadTexture(game.renderer, "assets/drone_1.png")
assert(drone_texture != nil, SDL.GetErrorString())
drone_w : i32
drone_h : i32
SDL.QueryTexture(drone_texture, nil, nil, &amp;amp;drone_w, &amp;amp;drone_h)

game.drone_tex = drone_texture

for index in 0..=(NUM_OF_DRONES - 1)
{
    destination := SDL.Rect{
        x = -(drone_w),
        y = 0,
        w = drone_w / 5, // drone image is also a bit too large
        h = drone_h / 5,
    }

    game.drones[index] = Entity{
        dest = destination,
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Spawning Drones
&lt;/h2&gt;

&lt;p&gt;Now that we have our fixed array of drones, we are free to spawn them. We'll spawn them on the far-right side of our window, and have them fly towards us on the left until they disappear. Our lasers are spawned once we hit the spacebar, but our drones will just spawn as soon as they become available after disappearing on the left side.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for l in &amp;amp;game.lasers
{
    if l.dest.x &amp;lt; WINDOW_WIDTH
    {
        l.dest.x += i32(get_delta_motion(LASER_SPEED))
        SDL.RenderCopy(game.renderer, game.laser_tex, nil, &amp;amp;l.dest)
    }
}


// NEW
// Spawn Drones
for drone, idx in &amp;amp;game.drones
{

    if drone.dest.x &amp;lt;= 0 &amp;amp;&amp;amp; !(game.drone_spawn_cooldown &amp;gt; 0)
    {
        drone.dest.x = WINDOW_WIDTH
        drone.dest.y = i32(rand.float32_range(120, WINDOW_HEIGHT - 120))

        game.drone_spawn_cooldown = DRONE_SPAWN_COOLDOWN_TIMER
    }

    steps := i32(get_delta_motion(DRONE_SPEED))
    drone.dest.x -= steps

    if drone.dest.x &amp;gt; 0
    {
        SDL.RenderCopy(game.renderer, game.drone_tex, nil, &amp;amp;drone.dest)
    }

}

// END NEW


// TIMERS
game.laser_cooldown -= get_delta_motion(LASER_SPEED)
game.drone_spawn_cooldown -= get_delta_motion(DRONE_SPEED)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is our first look at the Odin Rand library. Look above at the &lt;code&gt;rand.float32_range()&lt;/code&gt; procedure call. It takes two arguments -- a &lt;code&gt;min&lt;/code&gt; and a &lt;code&gt;max&lt;/code&gt; value. We use it to choose a random location on the &lt;code&gt;y&lt;/code&gt; plane so our drones don't all fly along the same path on our y-axis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Variable Drone Speeds
&lt;/h2&gt;

&lt;p&gt;Having the drones all fly at the same speed isn't very interesting. Let's make each drone fly at a slightly different speed.&lt;/p&gt;

&lt;p&gt;To accomplish this, we'll have to add some new fields to our Entity struct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Entity :: struct
{
    dest: SDL.Rect,
    // NEW
    dx: f64,
    dy: f64,
    // END NEW
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These &lt;code&gt;dx&lt;/code&gt; and &lt;code&gt;dy&lt;/code&gt; fields will capture the speed at which the Entity should travel.&lt;/p&gt;

&lt;p&gt;By adding these to the Entity struct, we'll have to update our &lt;code&gt;game.player&lt;/code&gt; and &lt;code&gt;lasers&lt;/code&gt; to use these fields, as well. While we don't strictly need them to use these fields right now, it's nice to be consistent, and eventually we may want to dynamically manipulate their speeds, anyway.&lt;/p&gt;

&lt;p&gt;We'll have to update code in our &lt;code&gt;create_entities()&lt;/code&gt; procedure, as well as wherever we use &lt;code&gt;get_delta_motion()&lt;/code&gt; to get delta movement amounts for each entity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Entity Creation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
game.player_tex = player_texture
game.player = Entity{
    dest = destination,
    // NEW
    dx = PLAYER_SPEED,
    dy = PLAYER_SPEED,
    // END NEW
}

// ...


game.lasers[index] = Entity{
    dest = destination,
    // NEW
    dx = LASER_SPEED,
    dy = LASER_SPEED,
    // END NEW
}

// ...


// NEW
// randomize speed to make things more interesting
max := DRONE_SPEED * 1.2
min := DRONE_SPEED * 0.5
random_speed := rand.float64_range(min, max)
// END NEW

game.drones[index] = Entity{
    dest = destination,
    // NEW
    dx = random_speed,
    dy = random_speed,
    // END NEW
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we see Odin's Rand library again. &lt;code&gt;rand.float64_range()&lt;/code&gt; also takes two arguments -- a &lt;code&gt;min&lt;/code&gt; and a &lt;code&gt;max&lt;/code&gt; value. For now we're making the random speed multiplier the same for both horizontal and vertical movements along the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; axes.&lt;/p&gt;

&lt;p&gt;Of course we now have to update the code where we handle entity position changes -- the update and render portion of our game loop.&lt;/p&gt;

&lt;h3&gt;
  
  
  Entity Updates
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 3. Update and Render

// update player position, etc...
// NEW -- changing our PLAYER_SPEED for the dx and dy on the player entity
delta_motion_x := get_delta_motion(game.player.dx)
delta_motion_y := get_delta_motion(game.player.dy)

if game.left
{
    // NEW
    move_player(-delta_motion_x, 0)
}

if game.right
{
    // NEW
    move_player(delta_motion_x, 0)
}

if game.up
{
    // NEW
    move_player(0, -delta_motion_y)
}

if game.down
{
    // NEW
    move_player(0, delta_motion_y)
}


// ...

for l in &amp;amp;game.lasers
{
    if l.dest.x &amp;lt; WINDOW_WIDTH
    {
        // NEW -- changing our LASER_SPEED for the l.dx setting on this single laser entity
        l.dest.x += i32(get_delta_motion(l.dx))
        SDL.RenderCopy(game.renderer, game.laser_tex, nil, &amp;amp;l.dest)
    }
}

// ...


// Spawn Drones
for drone, idx in &amp;amp;game.drones
{

    if drone.dest.x &amp;lt;= 0 &amp;amp;&amp;amp; !(game.drone_spawn_cooldown &amp;gt; 0)
    {
        drone.dest.x = WINDOW_WIDTH
        drone.dest.y = i32(rand.float32_range(120, WINDOW_HEIGHT - 120))

        game.drone_spawn_cooldown = DRONE_SPAWN_COOLDOWN_TIMER
    }

    // NEW -- changing our DRONE_SPEED for the drone.dx setting on this single drone entity
    steps := i32(get_delta_motion(drone.dx))
    drone.dest.x -= steps

    if drone.dest.x &amp;gt; 0
    {
        SDL.RenderCopy(game.renderer, game.drone_tex, nil, &amp;amp;drone.dest)
    }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For now we're just moving our drones horizontally, but in future parts we'll give them a little bit of vertical movement, as well. Be sure to keep an eye on &lt;a href="https://www.youtube.com/playlist?list=PLuZ3rcIdDc9EA4YqLJSsrzYeUDv8Mucxz"&gt;this series&lt;/a&gt; to catch that update!&lt;/p&gt;

&lt;h2&gt;
  
  
  Suggested Challenges
&lt;/h2&gt;

&lt;p&gt;In the next part we'll give our player the ability to destroy these drones -- they've been terrorizing the galaxy for far too long!&lt;/p&gt;

&lt;p&gt;See if you can figure out the basic collision detection needed to make that happen.&lt;/p&gt;

&lt;p&gt;If you get something working, share it in the comments beneath this &lt;a href="https://youtu.be/5ccarSklfVM"&gt;video&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>odinlang</category>
      <category>odin</category>
      <category>sdl2</category>
    </item>
    <item>
      <title>Learn to Code by NOT Doing What Everyone Else Does</title>
      <dc:creator>Patrick O'Dacre</dc:creator>
      <pubDate>Mon, 28 Nov 2022 22:41:24 +0000</pubDate>
      <link>https://dev.to/patrickodacre/learn-to-code-by-not-doing-what-everyone-else-does-3dci</link>
      <guid>https://dev.to/patrickodacre/learn-to-code-by-not-doing-what-everyone-else-does-3dci</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/A2OXrx4N2fQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Space Shooter Game with SDL2 and Odin - Part 5 - Firing MANY Lasers</title>
      <dc:creator>Patrick O'Dacre</dc:creator>
      <pubDate>Thu, 03 Nov 2022 07:08:16 +0000</pubDate>
      <link>https://dev.to/patrickodacre/space-shooter-game-with-sdl2-and-odin-part-5-firing-many-lasers-1h2m</link>
      <guid>https://dev.to/patrickodacre/space-shooter-game-with-sdl2-and-odin-part-5-firing-many-lasers-1h2m</guid>
      <description>&lt;h1&gt;
  
  
  Part 5 :: Firing Many Lasers
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youtu.be/lw2lde4xN9w"&gt;YouTube Video&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/channel/UCKXSHFNc-5D9i3heHkHgeUg"&gt;YouTube Channel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.libsdl.org/CategoryAPI"&gt;SDL2 Core Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/odin-lang/Odin/wiki"&gt;Odin Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We left Part 4 with a challenge to discover a way to fire more than one laser. If you haven't yet attempted this update, please do so before going through Part 5.&lt;/p&gt;

&lt;p&gt;In this part we'll cover how to fire many lasers.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Some Simple Upkeep&lt;/li&gt;
&lt;li&gt;Store a finite number of lasers in a fixed array.&lt;/li&gt;
&lt;li&gt;Reload our laser cannon once a laser goes offscreen.&lt;/li&gt;
&lt;li&gt;Balance laser speed with the number of lasers so we always have plenty of ammo.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/lw2lde4xN9w"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Some Basic Upkeep
&lt;/h2&gt;

&lt;p&gt;Before we get started I want to highlight some minor fixes made to the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixing Our Frame Rate
&lt;/h3&gt;

&lt;p&gt;Previously we calculated our &lt;code&gt;TARGET_DELTA_TIME&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
TARGET_DELTA_TIME :: 1000 / 60

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This constant defaulted to a &lt;code&gt;int&lt;/code&gt; type, and so our target frame rate was truncated to 16 milliseconds. That resulted in an FPS of 62 frames per second. That was a mistake.&lt;/p&gt;

&lt;p&gt;Rather, the code to calculate our target delta time should have been:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
TARGET_DELTA_TIME :: f64(1000) / f64(60)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would give us an &lt;code&gt;f64&lt;/code&gt; and an accurate frame time of 16.667 milliseconds, which would give us our desired 60 FPS.&lt;/p&gt;

&lt;p&gt;Our new &lt;code&gt;get_delta_motion()&lt;/code&gt; procedure would then have to be updated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
get_delta_motion :: proc(speed: f64) -&amp;gt; f64
{
    return speed * (TARGET_DELTA_TIME / 1000)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Fixed Array of Lasers
&lt;/h2&gt;

&lt;p&gt;To keep tight control over the number of lasers we have to keep track of, we'll start with using a fixed array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
NUM_OF_LASERS :: 100

Game :: struct
{
    // ...

    lasers: [NUM_OF_LASERS]Entity,

    // ...
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adjusting the laser limit and the laser speed will take some trial and error to ensure the player never feels like they don't have enough lasers. In other words, we want to make sure lasers reach the end of the screen and replenish quickly enough so we rarely meet the end of our laser supply.&lt;/p&gt;

&lt;p&gt;We'll create our lasers at game startup, filling in our array with our now-simplified entities.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
laser_texture := SDL_Image.LoadTexture(game.renderer, "assets/bullet_red_2.png")
assert(laser_texture != nil, SDL.GetErrorString())
laser_w : i32
laser_h :i32
SDL.QueryTexture(laser_texture, nil, nil, &amp;amp;laser_w, &amp;amp;laser_h)

game.laser_tex = laser_texture

for index in 0..=(NUM_OF_LASERS-1)
{
    destination := SDL.Rect{
        x = WINDOW_WIDTH + 20, // offscreen means available to fire
        w = laser_w / 3,
        h = laser_h / 3,
    }

    game.lasers[index] = Entity{
        dest = destination,
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the changes to the &lt;code&gt;Game&lt;/code&gt; struct and the &lt;code&gt;Entity&lt;/code&gt; struct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Game :: struct
{
    perf_frequency: f64,
    renderer: ^SDL.Renderer,

    // player
    player: Entity,
    player_tex: ^SDL.Texture, // NEW
    left: bool,
    right: bool,
    up: bool,
    down: bool,


    laser_tex: ^SDL.Texture, // NEW
    lasers: [NUM_OF_LASERS]Entity, // NEW
    fire: bool,
    laser_cooldown : f64, // NEW
}

Entity :: struct
{
    dest: SDL.Rect,
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;laser_tex&lt;/code&gt; and &lt;code&gt;player_tex&lt;/code&gt; are added to the &lt;code&gt;Game&lt;/code&gt; struct and the &lt;code&gt;tex&lt;/code&gt; fields are removed from the &lt;code&gt;Entity&lt;/code&gt; struct.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;We're creating 100 lasers, and there is no need to create 100 textures -- only one texture is needed.&lt;/p&gt;

&lt;p&gt;We also removed our &lt;code&gt;health&lt;/code&gt; field from the &lt;code&gt;Entity&lt;/code&gt; struct. We can track laser lifetimes by checking their &lt;code&gt;x&lt;/code&gt; position. (NOTE :: I went back to using Health later on. It was better.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Reloading our Laser Cannon
&lt;/h2&gt;

&lt;p&gt;Each time a player "fires" a laser we need to iterate through our array of lasers and find the first one whose &lt;code&gt;x&lt;/code&gt; position is greater than the width of the window, i.e.: is offscreen. That one laser that is offscreen is then "reloaded" by having its &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; position reset.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing the Right NUM_OF_LASERS, LASER_SPEED, and LASER_COOLDOWN_TIMER
&lt;/h2&gt;

&lt;p&gt;We have 100 lasers available to us, and our laser cooldown timer counts down each frame by an amount relative to the frame rate and the LASER_SPEED. With the timer set to &lt;code&gt;50&lt;/code&gt;, a laser will move approximately 50 pixels before another can be fired.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// FIRE LASERS
if game.fire &amp;amp;&amp;amp; !(game.laser_cooldown &amp;gt; 0)
{
    // find a laser:
    reload : for l in &amp;amp;game.lasers
    {
        // find the first one available
        if l.dest.x &amp;gt; WINDOW_WIDTH
        {

            l.dest.x = game.player.dest.x + 20
            l.dest.y = game.player.dest.y
            // reset the cooldown to prevent firing too rapidly
            game.laser_cooldown = LASER_COOLDOWN_TIMER

            break reload
        }
    }
}

for l in &amp;amp;game.lasers
{
    if l.dest.x &amp;lt; WINDOW_WIDTH
    {
        l.dest.x += i32(get_delta_motion(LASER_SPEED))
        SDL.RenderCopy(game.renderer, game.laser_tex, nil, &amp;amp;l.dest)
    }
}


// decrement our cooldown
game.laser_cooldown -= LASER_SPEED * (TARGET_DELTA_TIME / 1000)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our cooldown timer is reset each time we fire a laser. We cannot fire a laser until our cooldown timer goes below ZERO.&lt;/p&gt;

&lt;p&gt;With the settings we have right now I don't feel like we run out of ammunition too quickly, but you should feel free to change these settings to match your tastes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Suggested Challenges
&lt;/h2&gt;

&lt;p&gt;In the next part we'll cover adding enemies to the window. By now you should understand how to render images to the screen, so you should try adding a few enemies that our player must battle.&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>odinlang</category>
      <category>odin</category>
      <category>sdl2</category>
    </item>
    <item>
      <title>Space Shooter Game with SDL2 and Odin - Part 4 - Firing a Laser</title>
      <dc:creator>Patrick O'Dacre</dc:creator>
      <pubDate>Fri, 28 Oct 2022 07:07:13 +0000</pubDate>
      <link>https://dev.to/patrickodacre/space-shooter-game-with-sdl2-and-odin-part-4-firing-a-laser-185l</link>
      <guid>https://dev.to/patrickodacre/space-shooter-game-with-sdl2-and-odin-part-4-firing-a-laser-185l</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=bn3QMNSYmgk"&gt;YouTube Video&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/channel/UCKXSHFNc-5D9i3heHkHgeUg"&gt;YouTube Channel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.libsdl.org/CategoryAPI"&gt;SDL2 Core Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/odin-lang/Odin/wiki"&gt;Odin Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/bn3QMNSYmgk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In this part of the series we tackle the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;add a new procedure - create_entities()&lt;/li&gt;
&lt;li&gt;creating a new "laser" entity&lt;/li&gt;
&lt;li&gt;firing a single laser with the spacebar key&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  create_entities()
&lt;/h2&gt;

&lt;p&gt;Our main procedure is getting a little large, so let's move all of code for creating new entities to a dedicated procedure. Normally, I would not be so quick to move things to a dedicated procedure, but this isn't code we need to look at again and again, so I don't mind getting it out of the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Laser Entity
&lt;/h2&gt;

&lt;p&gt;Our Laser Entity is very similar to our main Player Entity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it's a png&lt;/li&gt;
&lt;li&gt;it's not a sprite sheet but a single image&lt;/li&gt;
&lt;li&gt;it's a little large, and it needs to be scaled down&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can download the laser image &lt;a href="https://github.com/patrickodacre/odin-space-shooter/blob/master/assets/bullet_red_2.png"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We'll load our .png in the same way we loaded our player image, and we'll resize it to better match our main player spaceship.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    laser_texture := SDL_Image.LoadTexture(game.renderer, "assets/bullet_red_2.png")
    assert(laser_texture != nil, SDL.GetErrorString())
    SDL.QueryTexture(laser_texture, nil, nil, &amp;amp;destination.w, &amp;amp;destination.h)
    destination.w /= 3
    destination.h /= 3

    game.laser = Entity{
        tex = laser_texture,
        dest = destination,
        health = 0,
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the new "health" field added to the Entity struct. &lt;code&gt;health&lt;/code&gt; gives us a simple way to track whether or not our laser should be rendered to the screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Firing our Laser
&lt;/h2&gt;

&lt;p&gt;Each time the player hits the spacebar, we'll fire our laser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
game.fire = state[SDL.Scancode.SPACE] &amp;gt; 0

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To enforce single shots, our laser will only fire if the health is &lt;code&gt;0&lt;/code&gt;. Once fired, the laser health is reset to &lt;code&gt;1&lt;/code&gt; and its position is set to just beyond the current position of the ship, so it appears to be firing directly from the ship.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
if game.fire &amp;amp;&amp;amp; game.laser.health == 0
{
    game.laser.dest.x = game.player.dest.x + 30
    game.laser.dest.y = game.player.dest.y
    game.laser.health = 1
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once our laser disappears offscreen, we reset the health to &lt;code&gt;0&lt;/code&gt; so we can fire it again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
if game.laser.dest.x &amp;gt; WINDOW_WIDTH
{
    game.laser.health = 0
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We only want to render our laser to the screen if it has been fired and hasn't yet disappeared offscreen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
if game.laser.health &amp;gt; 0
{
    game.laser.dest.x += i32(get_delta_motion(LASER_SPEED))
    SDL.RenderCopy(game.renderer, game.laser.tex, nil, &amp;amp;game.laser.dest)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To decide how quickly we should move our laser we use a new constant &lt;code&gt;LASER_SPEED&lt;/code&gt;. As with our player, we want our laser to move at the rate we choose irrespective of the frame rate, so we need to calculate its delta motion. Since this operation is now performed on both the &lt;code&gt;player&lt;/code&gt; and the &lt;code&gt;laser&lt;/code&gt; we can create a new procedure &lt;code&gt;get_delta_motion()&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
get_delta_motion :: proc(speed: f64) -&amp;gt; f64
{
    return speed * (f64(TARGET_DELTA_TIME) / 1000)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;get_delta_motion()&lt;/code&gt; is similar to another procedure we wrote &lt;code&gt;get_time()&lt;/code&gt; -- both procedures return a value. In Odin return values are specified using this arrow syntax &lt;code&gt;-&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Suggested Challenge
&lt;/h2&gt;

&lt;p&gt;Try and find a way to fire more than one laser at a time.&lt;/p&gt;

&lt;p&gt;I came up with a way using one of Odin's array types - a Fixed Array.&lt;/p&gt;

&lt;p&gt;Odin has Fixed Arrays and Dynamic Arrays. Fixed Arrays have a set length that cannot be changed; whereas, Dynamic Arrays can grow dynamically to suit runtime requirements.&lt;/p&gt;

&lt;p&gt;Try to give your ship a fixed number of lasers to fire using a Fixed Array. Once a laser goes offscreen, it should be made available again to fire.&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>odinlang</category>
      <category>odin</category>
      <category>sdl2</category>
    </item>
    <item>
      <title>Space Shooter Game with SDL2 and Odin - Part 3 - Keyboard Input and Delta Time</title>
      <dc:creator>Patrick O'Dacre</dc:creator>
      <pubDate>Mon, 17 Oct 2022 20:17:36 +0000</pubDate>
      <link>https://dev.to/patrickodacre/player-movement-with-sdl2-and-the-odin-programming-language-space-shooter-game-part-3--3l8m</link>
      <guid>https://dev.to/patrickodacre/player-movement-with-sdl2-and-the-odin-programming-language-space-shooter-game-part-3--3l8m</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youtu.be/hY071s3M4N0"&gt;YouTube Video&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/channel/UCKXSHFNc-5D9i3heHkHgeUg"&gt;YouTube Channel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.libsdl.org/SDL_Scancode"&gt;SDL2 Scancodes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.libsdl.org/CategoryAPI"&gt;SDL2 Core Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/odin-lang/Odin/wiki"&gt;Odin Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/hY071s3M4N0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;There are numerous ways to handle keyboard input for player movement.&lt;/p&gt;

&lt;p&gt;The easiest method I have found so far consists of the following parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;SDL.GetKeyboardState() or SDL.PollEvent() for KEYDOWN / KEYUP events&lt;/li&gt;
&lt;li&gt;(Delta Time or Enforced Frame Rate) * target_pixels_per_second&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  SDL.GetKeyboardState()
&lt;/h2&gt;

&lt;p&gt;This function allows us to check which keys on the keyboard are pressed. In our code we set 4 booleans based on the state of the 4 movement keys we're interested in -- WASD.&lt;/p&gt;

&lt;p&gt;The other way to set these boolean flags is to set them to &lt;code&gt;true&lt;/code&gt; on the appropriate &lt;code&gt;KEYDOWN&lt;/code&gt; event and &lt;code&gt;false&lt;/code&gt; on the corresponding &lt;code&gt;KEYUP&lt;/code&gt; event. &lt;code&gt;KEYDOWN&lt;/code&gt; means the key has been pressed. &lt;code&gt;KEYUP&lt;/code&gt; means the key has been released.&lt;/p&gt;

&lt;p&gt;This second method, though, requires us to also check if the &lt;code&gt;KEYDOWN&lt;/code&gt; or &lt;code&gt;KEYUP&lt;/code&gt; event is either a repeated event, or the initial pressing / releasing of that key. If we do not distinguish between the two we could get some strange behavior as we poll the event queue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
state := SDL.GetKeyboardState(nil)

game.left = state[SDL.Scancode.A] &amp;gt; 0
game.right = state[SDL.Scancode.D] &amp;gt; 0
game.up = state[SDL.Scancode.W] &amp;gt; 0
game.down = state[SDL.Scancode.S] &amp;gt; 0

// versus ...

if event.type == SDL.EventType.KEYDOWN
{
    // not repeated
    if event.repeat == 0
    {

        if event.key.keysym.scancode == SDL.Scancode.A
        {
            game.left = true
        }
        /// ...
    }
}

if event.type == SDL.EventType.KEYUP
{
    // not repeated
    if event.repeat == 0
    {

        if event.key.keysym.scancode == SDL.Scancode.A
        {
            game.left = false
        }
        /// ...
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I think you'll agree that checking the keyboard state is much nicer to look at. This second option is too verbose for what we need.&lt;/p&gt;

&lt;h2&gt;
  
  
  delta_time and Delta Motion
&lt;/h2&gt;

&lt;p&gt;Delta Motion is the incremental movement calculated for the present frame based on the time it took to complete the previous frame -- the delta time. In practice, this delta time is multiplied by the desired travel distance measured in pixels per second. This ensures that movement doesn't speed up or slow down when the frame rate changes from machine to machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
delta_motion := PLAYER_SPEED * (f64(TARGET_DELTA_TIME) / 1000)

if game.left
{
    move_player(-delta_motion, 0)
}

if game.right
{
    move_player(delta_motion, 0)
}

if game.up
{
    move_player(0, -delta_motion)
}

if game.down
{
    move_player(0, delta_motion)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I would also like to point out a handy Odin function for ensure the player doesn't move off screen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
move_player :: proc(x, y: f64)
{
    game.player.dest.x = clamp(game.player.dest.x + i32(x), 0, WINDOW_WIDTH - game.player.dest.w)
    game.player.dest.y = clamp(game.player.dest.y + i32(y), 0, WINDOW_HEIGHT - game.player.dest.h)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;clamp()&lt;/code&gt; returns the given value provided it is between the given min and max arguments; otherwise, it will return the min or the max value provided.&lt;/p&gt;

&lt;p&gt;In other games I've used a combination of &lt;code&gt;min()&lt;/code&gt; and &lt;code&gt;max()&lt;/code&gt; that work well for basic collision detection, but for now &lt;code&gt;clamp()&lt;/code&gt; does a good job.&lt;/p&gt;

&lt;h2&gt;
  
  
  SDL.RenderCopy()
&lt;/h2&gt;

&lt;p&gt;Once we're done updating the player position, it is time to render that player to the window. Keep in mind that we're not displaying the updated player position, yet. We're rendering the image in the background, drawing the scene that will be displayed when we next call &lt;code&gt;SDL.RenderPresent()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Odin Highlights
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Variable Declarations
&lt;/h3&gt;

&lt;p&gt;In Odin, the colon &lt;code&gt;:&lt;/code&gt; is used for variables and other type declarations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://odin-lang.org/docs/overview/#variable-declarations"&gt;Variable Declarations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://odin-lang.org/docs/overview/#constant-declarations"&gt;Constant Declarations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When we declare a constant for the player's speed, we specify an &lt;code&gt;f64&lt;/code&gt; type rather than allow the constant to default to an &lt;code&gt;int&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
PLAYER_SPEED : f64 : 500 // pixels per second

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how our struct and procedure declarations follow the same pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Entity :: struct
{
    tex: ^SDL.Texture,
    dest: SDL.Rect,
}

main :: proc()
{
    //
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Package Naming
&lt;/h3&gt;

&lt;p&gt;In the first parts of this series we named our package "main", but this is just an arbitrary name -- we can name our "main" package anything we want, so I renamed it "game".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package game

import "core:fmt"
import SDL "vendor:sdl2"
import SDL_Image "vendor:sdl2/image"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice also that we gave custom names to our imported packages.&lt;/p&gt;

&lt;p&gt;Had we not chosen &lt;code&gt;SDL&lt;/code&gt; and &lt;code&gt;SDL_Image&lt;/code&gt;, we would reference these imported packages with &lt;code&gt;sdl2&lt;/code&gt; and &lt;code&gt;image&lt;/code&gt; prefixes like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
assert(sdl2.Init(sdl2.INIT_VIDEO) == 0, sdl2.GetErrorString())
assert(image.Init(image.INIT_PNG) != nil, sdl2.GetErrorString())
defer sdl2.Quit()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nice and simple!&lt;/p&gt;

&lt;h2&gt;
  
  
  Suggested Exercises
&lt;/h2&gt;

&lt;p&gt;Player movement is an interesting subject, and I have published a few videos documenting my search for a deeper understanding.&lt;/p&gt;

&lt;p&gt;Perhaps you will find it helpful to download my movement tool visualization tool detailed here in this &lt;a href="https://www.youtube.com/watch?v=3xxac2Yip3Y"&gt;video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To practice, you should experiment with the different ways to handle movement. Perhaps you can figure out how to use SDL to handle input from a game controller.&lt;/p&gt;

&lt;p&gt;Be sure to post about your progress in the comments for &lt;a href=""&gt;this video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

</description>
      <category>sdl2</category>
      <category>gamedev</category>
      <category>odin</category>
      <category>odinlang</category>
    </item>
  </channel>
</rss>
