Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon

24. August 2016

 

Welcome back to the ongoing Defold Game Engine tutorial series looking at all aspects of game development using the Defold game engine.  In this tutorial we are going to look at the process of playing sound and music in Defold.

 

There is an HD video version of this tutorial available here.

 

Playing sound in the Defold engine is simple, which is a double edged sword.  It’s extremely easy to add and play a sound file.  On the other hand the functionality provided is also quite simple.  Many things you may want to accomplish ( callback on sound end, fast forwarding/rewinding a playing audio file, positional audio, etc. ) simply aren’t supported.

Let’s start by adding some audio files to the project.  In my case I added a folder named audio and dragged in an ogg file and a wav file from Windows Explorer to Defold.  These are the two file formats supported.  The ogg file is an Ogg Vorbis file, a compressed streamed format similar to mp3 format but not patent encumbered.  Wav files are almost entirely uncompressed but require less processing power.  In a nutshell for longer form audio files, such as music, use an ogg.  For sound effects, use wav.  The end result should look something like:

image

 

Next we go ahead and create a sound component for our game.  You could parent your sound components to whatever game object you wish.  If it makes sense to create a music player game object and attach all the sounds to it, you could.  Or if you want your game objects (for example, the player) to own their own sound components, that’s alright too.  Select whatever game object you want to add the sound to, right click and select Add Component.

image

 

Next select Sound from the component list.

image

 

Here I am creating one for the music file first:

image

 

Hit the … button beside Sound and select the ogg file you dropped in earlier.  Notice in this case I changed the Group to music.  I repeat the same process for the wav file, instead named sfx. 

 

Now playing the sound effect using code is extremely easy and once again uses messages like so:

msg.post("#music","play_sound")

 

Simply post the play_sound message to the music component of our current game object.  Playing the sound effect file is the exact same process but instead post the message to the #sfx component like so:

msg.post("#sfx","play_sound")

 

We can also control the volume of the sound component, like so:

msg.post("#music","set_gain", { gain = volume })

 

Volume is a value from 0.0 to 1.0, where 0.0 is no volume, while 1.0 represents full volume.  Remember earlier when I changed the group for our music file from “master” to “music”.   Groups enable you to control several sound effects at once, for example muting all the playing songs or sound effects.  For example, we could mute all the sounds in the group music with the following call:

sound.set_group_gain(hash("music"), 0.0)

 

Here is the full source for this example:

-- Local variable for volume. 0 is none, 1 is full
local volume = 1.0

function init(self)
  msg.post(".","acquire_input_focus")
  -- start playing the background music
  msg.post("#music","play_sound")
end

function on_input(self, action_id, action)
  if(action_id == hash("SPACE_PRESSED") and action.pressed == true) then
    -- if user hits the spacebar play the soundfx file. 
    -- multiple presses will play multiple instances.
    msg.post("#sfx","play_sound")
  elseif(action_id == hash("ESC") and action.pressed == true) then
    -- on ESC mute the entire group "music"
    sound.set_group_gain(hash("music"), 0.0)
  elseif(action_id == hash("DOWN_ARROW") and action.pressed == true) then
    if volume >= 0 then
      volume = volume - 0.1
    end
    -- lower the volume of our music
    msg.post("#music","set_gain", { gain = volume })
  elseif(action_id == hash("UP_ARROW") and action.pressed == true) then
    if volume <= 1 then
      volume = volume + 0.1
    end
    -- increase the volume of our music
    msg.post("#music","set_gain", { gain = volume })    
  end
end

 

The Video

Programming

15. August 2016

 

Welcome back to the ongoing Defold Game Engine tutorial series, today we are going to build on the Sprites and Animation tutorial and look at three critical aspects of Defold game programming, scripting and messages.  Defold is programmed using the Lua scripting language which is beyond the scope of what we will be covering in this tutorial.  However we have already completed a Lua programming course for beginners available here.  If you are unfamiliar with Lua, it will teach you everything you need to know to get started with the language.

As with all tutorials in this series, there is an HD video version available here.

 

Setting up Input

 

If you created a default project, you will see a folder named Input, like so:

image

If for some reason you don’t have this input_binding file, you can create one by right clicking, selecting New->Input Binding File

image

The Input Binding File is a special file that maps various input devices to a text string that identifies the action to perform when that input occurs.  Double click the game.input_binding file and it will open in the editor:

image

You will notice there is a category for keys, mouse, gamepad, touch and text.  Right click the category you want to add an input control for and select the Add ___ trigger option.

image

 

This will create a new entry.  In the input value, drop it down and select the key/button/action you want to bind.  In the value name it.  In this example I’ve mapped KEY_SPACE to the event toggle_move.

image

 

The cool thing about this approach is you can map multiple input devices to the same action, like so:

image

 

Now the spacebar and left mouse button with both fire off the toggle_move action.  You will see how this works in just a split second.

 

Scripting

 

Now that we have some input firing, lets set up a script to handle it.  Building on the project we made in the last tutorial, add a script file to your game.  In my case it looks like:

image

 

We already covered the basics of creating a script in this earlier tutorial if you need to details on how to proceed creating a script.  In the previous tutorial we created an animation called walk.  Create another one called “Idle” using the same process, but add just a single frame of animation, so it looks like this:

image

 

We are now going to add the code to toggle between the two animation states.  In your freshly created .script file, add the following code:

local currentAnimation = 0

function init(self)
  msg.post(".","acquire_input_focus")
end

function on_input(self, action_id, action)
    if action_id == hash("toggle_move") and action.pressed == true then
      print("ACTION")
      if self.currentAnimation == 1 then
        msg.post("#sprite","play_animation", {id = hash("walk")})
        self.currentAnimation = 0
      else
        msg.post("#sprite","play_animation", {id = hash("idle")})
        self.currentAnimation = 1
      end
      
      return true -- input handled.
    end
end

 

There are a couple key things here… first you notice the local variable currentAnimation.  This is simply going to track which animation is playing so we can switch between them.

 

Next we have the init() callback function.  This function is called ONCE by the Defold game engine, when the game object this script is attached to is created.  This is where you would do your various initialization and setup logic.  In this case we are telling Defold that we want to have input sent to this game object.  That way when you hit the keyboard or press a mouse for example, this scripts on_input() function will be called.  This is done by sending a message, message passing is very important and we will cover it shortly.  For now know that the first parameter in the post() call is where to send the message.  “.” is shortcode for “to the object this script is attached”.  Meanwhile ‘#’ is shorthand for “to this script itself”.  Dont worry, we will cover this in more detail in a moment.  The second parameter is the message we want to send.   In this case we are sending the message “acquire_input”, which is a predefined message type in GameObject.

 

Now that we’ve told Defold we respond to input, we not implement the on_input() callback function.  First we check to see what the action id is, but this value will be encoded, so simply pass it into the hash() function.  Basically we test to see if our toggle_move action that we defined earlier has been fired.  Remember, this is wired to the left mouse button or spacebar being hit.  We also check to make sure it’s a pressed event (as opposed to a release).  Next we toggle our input, if our currentAnimation value is 0 we are currently walking so now we want to change to the idle animation, and vice versa.  Notice that we change the animation once again by using a message.  In this case we are passing the message “play_animation” to the object “#sprite”.  This refers to a fragment, part of an underlying message url… dont worry, it’ll make sense in a moment.  For now just think of #sprite as saying, send this message to the sprite component of this object. 

image

 

If you look at the documentation for any given class… such as Sprite, you will see the various messages it will respond to.

image

 

Sending and receiving messages is the core of how objects in Defold communicate.  It’s a way of having different objects able to communicate and share data or respond to actions or events, while remaining loosely coupled.

 

Now if you run this code, it will start with the player walking.  Hitting space bar or left clicking will fire off the toggle_move event, and the animation should now switch.  Let’s look a bit closer at how you can send messages between objects.

What I did is created a new folder named other, inside of which I created a game object named other and attached a script to it, named inventively enough other.script, like so:

image

 

In your main.collection, add an instance of other, like so:

image

 

Other does absolutely nothing, but is going to illustrate how two game objects can communicate with … um… each other.  Ugh.

In other.script, add the following code:

function update(self, dt)
  msg.post("main:/character", "marco", { msg = "You out there?", meaningOfLife = 42 })
end

 

The update() function is the callback called by the Defold engine every single pass through your game loop.  In this case we are simple sending a message to our character game object in the main folder.  The message is called “marco” (for marco/polo).  You will notice we also pass a table with some pretty useful data in it…  msg and meaningOfLife, the first a string the second a number.  The data you fill in this table is completely optional… in fact you dont need to pass data at all.

 

The important part to understand is the URL we are using to post the message to.  It’s a lot like the URL you use to go to a website.  The first part (in this case) is referring to the collection the target is in, the second part is the name itself.  It doesn’t work exactly like what you might expect though, as here is the structure:

image

The folder name has ZERO importance in this scenario… it’s just there as a handy way for you to organize things.  The root of the url (main:/) refers entirely to the name of the collection, then the remainder of the URL, refer to values within that collection.

So we are sending this message to the character game object inside main.collection:

image

 

If we had instead wanted to send the message directly to the sprite attached to the character, we could have sent the message to main:/character#sprite

 

Now we can modify our code inside main to listen for this message:

function on_message(self, message_id, message, sender)
  pprint(message)
    if(message_id == hash("marco")) then
      print("Polo")
  end
end

 

The on_message() function is called when the object your script is attached to receives a message.  In this case we check to see if the message was “marco”.  Again we encode it using the hash() function.  If you run this code you will see Polo written over and over in the console.  You will also see the data that was sent in the message, remember that table we encoded earlier.   Note the use of pprint().  This is a handy function that performs a pretty print of a table you pass in.  Basically it prints the table out in a nice easily read form.

 

There are a couple special message targets available as well.  @physics, @render and @system.  These actually send messages to the Defold game engine itself, the physics, rendering and system sub systems respectively.  For example, we can see that the render subsystem responds to the following messages:

image

 

So we could easily change the background color sending a message valued clear_color to @render like so:

msg.post("@render:","clear_color", { color = vmath.vector4(0,0,1,1) })

In this case our data is a Vector4 with the value (0,0,1,1).  This is an RGBA color value, basically saying no red, no green, full blue and full opacity.  AKA… blue.  This will cause our background color to be blue instead of black.

 

This messaging system may at first seem very alien, but it quickly becomes intuitive.  You do have to keep the reference handy to see what messages each object responds to.

 

Properties

 

Finally let’s look quickly at the concept of Properties before moving on.  You’ve already dealt with several built in properties.  For example, when you created a game object, it had several built in properties already defined:

image

 

You can also easily create your own properties.  This is a great way to make code reusable, or set it to so that a coder can code, but expose some data to a designer.  The process is simple, in our script file, simply add:

go.property("MyProperty",42)

To the top of the script file.

f you are wondering just where the heck go.property() came from, it’s simply a member of Game Object which you can think of as your base class.

 

You can define a property anywhere, except inside the various different Defold callbacks (such as Init()).  Now you can use this property anywhere just like any other local variable, like so:

print(self.MyProperty)

 

The cool part however is, now if you check in the Editor for that script, you will see the property is exposed and can easily be overriden:

image

 

The Video

Programming

7. August 2016

 

I’ve been a huge fan of the open source Godot Engine for a very long time, in fact I’ve done an in-depth tutorial series available here.  Godot has seen a number of improvements in the upcoming 2.1 release, but the recently added Visual Scripting interface is probably the biggest new addition.  In this post we are going to look at this new functionality.  A couple of warnings to start.  First, as of writing ( 8/7/2016 ), Visual Scripting is only available in the development branch.  So you will have to build Godot engine from scratch from the Github repository.  Second, this functionality is extremely early and not fully developed.  There is currently no debugger or profiler support and expect bugs.  Heck, I’m having trouble even running scripts at this point, but it’s probably user error on my end.  You have been warned!

 

I also did a video showing hands on with the new Godot Visual Scripting language.  It is available embedded below.

 

Creating a Visual Script

 

Creating a script is a simple process, basically identical to creating a GDScript.  Add a new script as usual.

image

 

Now in the Create Node Script, pull down language and select VisualScript.  VisualScript’s have a .vs extension in Godot.

image

 

Creating Visual Scripts

 

Visual Scripts are basically a flow chart of nodes, like so:

 

image

 

You start by implementing a function.  All of the usual GDScript functions are here:

image

 

This enables you to handle various events within your games lifecycle.  This will create a new node on the graph that acts as an entry point:

image

 

You notice in this example there is a parameter “event” here.  With it selected you can see it’s values in Inspector:

image

 

You will notice on the right side of the Function node there is an arrow and blue dot.  The arrow is for program flow, while the dot represents output.  Other nodes can have various inputs, which are also color coded.  We can now add other nodes to our graph, from the Available Nodes section.

image

There is basically a one to one ratio of nodes and functions available in GDScript.  Add a new Node from the InputEvent section for Is Pressed, simply drag and drop from the Available Nodes to the drawing surface.  Now we connect the two nodes together.

GIF

 

You will notice the newly created is_pressed test has another line out to continue the process as well as a bool output (notice the different color coding).  We could not continue our code by branching to a conditional like so:

image

 

Of course, this is VERY early, but it does give you an idea of how Visual Scripting will work in Godot.

 

The Video

Programming

24. July 2016

 

Traditionally I don’t recommend beginners start with C++.  There are a number of reasons behind this opinion, most of which are explained in this video.  Most of the reasons however have very little to do with the language itself (which does of course have some downsides) and more to do with the build system, linker and limited included libraries.  I recently discovered a library aimed at beginners that alleviates a great deal of the downsides of learning using C++, raylib.  It’s free, open source (available on Github) and provides most of the functionality you require to make a game.  Most importantly, it’s aimed at beginners meaning the library is easy to use and comes with a turn key installer that enables you to hit the ground running.

If you are interested in learning more about raylib, be sure to watch this video (also embedded below).

 

The key features of raylib are:

- Written in plain C code (C99)
- Uses C# PascalCase/camelCase notation
- Hardware accelerated with OpenGL (1.1, 2.1, 3.3 or ES 2.0)
- Unique OpenGL abstraction layer (usable as standalone module): [rlgl]
- Powerful fonts module with SpriteFonts support (XNA fonts, AngelCode fonts, TTF)
- Outstanding texture formats support, including compressed formats (DXT, ETC, ASTC)
- Basic 3d support for Geometrics, Models, Heightmaps and Billboards
- Materials (diffuse, normal, specular) and Lighting (point, directional, spot)
- Shaders support, including Model shaders and Postprocessing shaders
- Powerful math module for Vector and Matrix operations [raymath]
- Audio loading and playing with streaming support (WAV, OGG, XM, MOD)
- VR stereo rendering support with configurable HMD device parameters
- Multiplatform support: Android, Raspberry Pi, HTML5, Oculus Rift CV1
- Custom color palette for fancy visuals on raywhite background
- Minimal external dependencies (GLFW3, OpenGL, OpenAL)

 

The part I found most impressive though is the installer.  It comes with a pre-configured version of the MingW compiler and Notepad++ set up for development right away.  Basically you run the installer, open notepad++, start writing code and hit F6 to run it.  No dealing with setting up a compiler, learning about linkers and all the various things that make the C++ learning curve so painful.  Well, most of the things...

 

I should point out quickly, while I’ve been calling it a C++ library, it’s actually a C library.  This is a minor distinction as it is perfectly usable in C++ and feels like C++.  It comes with a copious amount of examples, with very easy to understand code.  Here for example is an, um, example that illustrates loading and drawing images:

/********************************************************************************
***********
*
*   raylib [textures] example - Image loading and drawing on it
*
*   NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU 
memory (VRAM)
*
*   This example has been created using raylib 1.4 (www.raylib.com)
*   raylib is licensed under an unmodified zlib/libpng license (View raylib.h 
for details)
*
*   Copyright (c) 2016 Ramon Santamaria (@raysan5)
*
*********************************************************************************
***********/

#include "raylib.h"

int main()
{
    // Initialization
    //---------------------------------------------------------------------------
    -----------
    int screenWidth = 800;
    int screenHeight = 450;

    InitWindow(screenWidth, screenHeight, "raylib [textures] example - image 
    drawing");

    // NOTE: Textures MUST be loaded after Window initialization (OpenGL context 
    is required)

    Image cat = LoadImage("resources/cat.png");             // Load image in CPU 
    memory (RAM)
    ImageCrop(&cat, (Rectangle){ 100, 10, 280, 380 });      // Crop an image 
    piece
    ImageFlipHorizontal(&cat);                              // Flip cropped 
    image horizontally
    ImageResize(&cat, 150, 200);                            // Resize flipped-
    cropped image
    
    Image parrots = LoadImage("resources/parrots.png");     // Load image in CPU 
    memory (RAM)
    
    // Draw one image over the other with a scaling of 1.5f
    ImageDraw(&parrots, cat, (Rectangle){ 0, 0, cat.width, cat.height }, (
    Rectangle){ 30, 40, cat.width*1.5f, cat.height*1.5f });
    ImageCrop(&parrots, (Rectangle){ 0, 50, parrots.width, parrots.height - 100 }
    ); // Crop resulting image
    
    UnloadImage(cat);       // Unload image from RAM

    Texture2D texture = LoadTextureFromImage(parrots);      // Image converted 
    to texture, uploaded to GPU memory (VRAM)
    UnloadImage(parrots);   // Once image has been converted to texture and 
    uploaded to VRAM, it can be unloaded from RAM
    
    SetTargetFPS(60);
    //---------------------------------------------------------------------------
    ------------

    // Main game loop
    while (!WindowShouldClose())    // Detect window close button or ESC key
    {
        // Update
        //-----------------------------------------------------------------------
        -----------
        // TODO: Update your variables here
        //-----------------------------------------------------------------------
        -----------

        // Draw
        //-----------------------------------------------------------------------
        -----------
        BeginDrawing();

            ClearBackground(RAYWHITE);

            DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 
            - texture.height/2 - 40, WHITE);
            DrawRectangleLines(screenWidth/2 - texture.width/2, screenHeight/2 - 
            texture.height/2 - 40, texture.width, texture.height, DARKGRAY);

            DrawText("We are drawing only one texture from various images 
            composed!", 240, 350, 10, DARKGRAY);
            DrawText("Source images have been cropped, scaled, flipped and 
            copied one over the other.", 190, 370, 10, DARKGRAY);

        EndDrawing();
        //-----------------------------------------------------------------------
        -----------
    }

    // De-Initialization
    //---------------------------------------------------------------------------
    -----------
    UnloadTexture(texture);       // Texture unloading

    CloseWindow();                // Close window and OpenGL context
    //---------------------------------------------------------------------------
    -----------

    return 0;
}

 

All examples are a single .c file and there are plenty of them.  All you need to do is open them in Notepad++ and hit F6 to run.

 

At the end of the day, I still don’t personally think C++ is the ideal language to learn game programming, or programming in general.  However if you are going to start using C++, raylib is the single best starting point I have ever seen.  In fact, let me know if you would be interested in a beginner C++ tutorial series built around this library, let me know!

 

The Video

Programming

14. July 2016

 

In the previous tutorial we looked at the basics of creating an application using the Defold engine, part of that included the built in Atlas type for displaying a sprite.  In this tutorial we are going to look further into sprites.  In case you are unaware, a sprite is simply a 2D graphic with position and is pretty fundamental to modern 2D games, even if sprites are actually faked in 3D.

 

There is an HD video version of this tutorial here.

 

In the previous tutorial we started with an Atlas created for us.  This time we are going to create one from scratch.  Don’t worry, it’s easy.  So what exactly is an Atlas?  It’s simply a collection of images in a single source.  The Defold engine itself is resposible for determining the ideal layout for the best performance.

 

Creating and Populating an Atlas

 

Creating an Atlas is simple.  In the Project Explorer, right click the folder you want to create the Atlas in and select New->Atlas File

image

 

Next name your Atlas file.  In this case I’m going with walker.  The extension is predictably enough .atlas.  Then click Finish.

image

 

Now we need some Image files to put in our Atlas.  In this case I am using a selection of images I created earlier but you can use whatever images you want.  If you are a Patreon backer, they are available in the Patreon Dropbox in the folder Art\AnimatedCharacter\Spritesheets\Raw\walk.  Whatever images you go with, simply drag and drop them to the images folder inside the main folder.  If you don’t have such a folder, simply right click and create one.

GIF

 

Now make sure Walker.Atlas is open in the editor, then go over to the Outline view, right click Atlas and select Add Animation Group. 

image

 

In the properties window, name the animation walk and set the default playback mode to Loop Forward.

image

 

Now right click the newly created Walk animation group and select Add Images.  In the popup dialog, select all our newly added images.  You can use CTRL or SHIFT to multiselect:

image

 

You will see that Defold automatically arranges all of our frames of animation together into a single atlas:

image

 

Be sure to save your Atlas before continuing.  You can preview the animation by right clicking “walk” in the Outline then choosing Play/Stop Animation.

GIF2

 

Creating a Sprite

Now that we’ve got our populated Atlas and a walk animation, how do we use it?  We create a Sprite.

To do so open up your main level .collection file.  In Outline right click Collection then choose Add Game Object:

image

 

I personally changed the ID of mine to walker.  Now right click the newly created game object and select Add Component.

image

 

In the Add Component dialog, choose Sprite.

image

 

With the sprite selected in Outline, we now need to define some properties, specifically Image and Default animation.

image

 

For Image, it will bring up a dialog box, select our recently created Atlas.  If the Atlas isnt shown, make sure everything has been saved.

image

 

Next select the Walk animation we defined earlier.

 

Now your game object Sprite will show in Collection.

image

 

In this case our sprite is centered about the atlas.  You can move the sprite using the W key.  ( E and R can be used for rotation and scaling as well ).

image

 

Each arrow represents the axis it will be moved along.  Or you can position your mouse inside the square and move freely in any direction.  Position your character then run your game (Ctrl + B) and you should see:

GIF3

 

Creating a Tile Source

You can also use a tile source instead of an Atlas.  A tile source is simply a grid of sprites already arranged into a single image.  To use a tile source instead of selecting Atlas, you select Tile source.  I wont be covering it in detail here ( I will cover tile sources later when we get to tile maps ), but if you want more details check the video where I did cover it.

 

You can also programmatically program the animation, get callbacks when animations complete, etc... but that requires knowledge of message passing... and that’s in the next tutorial!

 

The Video

Programming ,

Month List

Popular Comments