Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon
28. January 2015


This tutorial is available in video form here or embedded below. 


Now might be a good time to pause and look at the life cycle of a typical program, as this can be a bit confusing with Godot yet is something you really need to understand.  Every non-trivial game has a game loop somewhere.  This is the code that runs after a program starts and is basically the heart of your application.  In pseudo code, it might look something like this:


main() {
   scene = createScene()


At it's heart it’s a glorified loop that runs over and over, checking for input, updating the scene and rendering the results until told to stop.


Godot of course is no exception, although by default this behavior is hidden from you as is the norm with game engines.  Instead the object that owns your scene is a SceneTree which itself inherits the MainLoop, which provides the above functionality.  A default one is provided for you, but if you wish you can implement your own, more on that below. 


What you should however realize is that this SceneTree is the beating heart of your application.  Every frame it calls it’s active scene passing in all the input that has occurred, as well as updating nodes that request updating.  We will look at this process now.  One important thing to be aware of… Nodes can access the SceneTree using the method .get_tree().


Updating a Node every frame


Ok, so that’s the basics of how program execution flows, now let’s take a look at a more practical example.  Let’s say for example we have a Sprite that we want to update every frame.  How do we tell our MainLoop that we want or Node to be updated?  Fortunately it’s quite simple. 


Create a Sprite node, add a graphic, position it on the screen then add a new script to it.  All of this was covered in the previous tutorial if you are unsure how to proceed.


Now that we have a Script attached, first we need to tell it we want to receive updates.  That is, every iteration of the main loop, we want our script to be called.  This is a two part process, pun not intended… much.  First, in your _ready function, you tell Godot you want to receive updates by called set_process(true).  Then you override the virtual function _process().


Let’s take a look at a simple sprite that moves right until it hits the edge of the screen, at which point it wraps around.

extends Sprite

func _ready():
func _process(delta):
   var cur_pos = self.get_pos()
   cur_pos.x += 100 * delta
   # wrap around screen
   if(cur_pos.x > self.get_viewport_rect().size.width + self.get_item_rect().size.width/2):
      cur_pos.x = -self.get_item_rect().size.width/2

set_process tells Godot to call this nodes _process() function.  The value passed in, delta, is the elapsed amount of time since the last time _process was called.  As you can see in the above example, this value can be used to animate at a constant rate.  The above example will update the X value by 100 pixels per second.  Your end result should look something like this:




So, in a nutshell, if your want to handle updates in your Node derived object, you simply call set_process(true) and provide a _process(float) override.


Handling Input by Polling


That moves us on to handling input.  You will notice that Input and Process handling are very similar.  There are a couple ways you can handle input in Godot.  Let’s start with the easiest, polling.


You can poll input at any time using the global object Input, like so:

func _process(delta):


This checks  first if the ESCAPE key, then if the SHIFT key (is also!) pressed.  If so we tell the SceneTree to exit the application.  As I said earlier, a node can access it’s SceneTree using get_tree().


In addition to polling for keyboard, there are also methods is_joy_button_pressed(), is_mouse_button_pressed() and is_action_pressed() which will make more sense in the near future.  You can also poll for status.  For example, to check the mouse cursor or touch location you could:


func _process(delta):
      print(str("Mouse at location:",Input.get_mouse_pos(), " moving at speed: ", Input.get_mouse_speed()));

There are other inputs you can poll as well, mostly mobile based, but they all use a very similar interface. I will cover mobile specific controls at a later point in this series.


Handling Input as Event Driven


You can also have Godot hand your application all the Input events as they occur and choose what to process.  Just like handling updates, you have to register to receive input events, like so:

func _ready():


Then you override the function _input, which takes an InputEvent as a parameter.

func _input(event):
   # if user left clicks
   if(event.type == InputEvent.MOUSE_BUTTON):
      if(event.button_index == 1):
   # on keyboard cursor key
   if(event.type == InputEvent.KEY):
      var curPos = self.get_pos()
      if(event.scancode == KEY_RIGHT):
         curPos.x+= 10

      if(event.scancode == KEY_LEFT):
         curPos.x-= 10


The above example handles a couple different scenarios.  First if the user clicks the left button, we set the position to the mouse’s current x and y location, as passed in by the InputEvent class.  Notice in this case I tested for button by index instead of the define BUTTON_LEFT like earlier.  There should be no functional difference, although this would allow you to test for buttons for which a mapping isn’t defined, such as one of those insane 12 button mouse.  Next we check to see if the event is a KEY event and if it is we check which key.  In the event of the right or left arrow, we update our position accordingly.


Sometimes however when you handle an event you want it done and gone.  By default all events will continue to be broadcast to all event receivers.  When you don’t want this behavior, it’s fairly simple to tell Godot that an event is handled.  From the above example, let’s swallow the event in the case of it being an InputEvent.KEY.  This means only this class will have access to keyboard events ( well… and GUI controls, which actually get their crack at the events earlier on ).

   # on keyboard cursor key
   if(event.type == InputEvent.KEY):
      var curPos = self.get_pos()


Calling set_input_handled() will cause the InputEvent to propagate no further.


Finally it’s possible you want to do a catch all.  Perhaps you want to log all of the unhandled input events that occurred.  This can also be done and you also have to register for this behavior, like so:

func _ready():

Then you simply override the corresponding function:

func _unhandled_input(event):
   print(str("An event was unhandled ",event))

In this case we simply log the event out to the console.  Warning though, there will be A LOT of them.  Just no keyboard events, since we are now eating those!


Input Maps


Quite often you want several commands to perform the same action.  For example you want pushing right on the controller d-pad to perform the same action as pushing the right arrow key.  Or perhaps you want to let the user define their own controls?  In both of these cases and input alias system is incredibly useful… and thankfully Godot has one built in… InputMaps.


You may have noticed the InputMap tab when we were in Project Settings earlier… if not open up Project Settings now…



Here you can see a number of mappings have already been defined for UI actions.  Lets go ahead and create a map of our own, MOVE_RIGHT.

At the top in Action enter MOVE_RIGHT


Then click Add


A new entry will be added to the bottom of the page, like so:


Click the + icon and add a new mapping of type Key



You will then be prompted to press a key:



Repeat this process and instead select another device… im going to also map the right mouse button, like so:



Your Input Map should now look something like this:



Now click the Save button and close the dialog. 

Now in code you can easily check activity using the input map, like so:

func _process(delta):
      var cur_pos = self.get_pos()
      cur_pos.x += 1

This code will run if either condition is true… the Right key is pressed or the Right mouse button is.  The above example is polled, but it’s just as easy to use an InputMap with event driven code, like so:

func _input(event):


One warning here however…  Actions are more states ( as in On or Off ) than they are Events, so it probably makes a great deal more sense dealing with them the former ( polling ) than the later ( event driven ).


A Peek Behind the Curtain


If you are like me, you probably aren’t content with not knowing exactly what is going on behind the scenes.  Black boxes just aren’t my thing and this is one of the great things about Godot being open-source, there are no black boxes!  So if you want to understand exactly how program flow works, it helps to jump into the source code.



I figured I would bold that.  The following information is just for people that want to understand a bit more what is happening behind the scenes…  We are going to hunt down the actual main loop in the source code, and essentially it’s right here in the function main/main.cpp.  Specifically the method iteration() is effectively the main loop:

bool Main::iteration() {

   uint64_t ticks=OS::get_singleton()->get_ticks_usec();
   uint64_t ticks_elapsed=ticks-last_ticks;


   double step=(double)ticks_elapsed / 1000000.0;

   float frame_slice=1.0/OS::get_singleton()->get_iterations_per_second();

   if (step>frame_slice*8)


   float time_scale = OS::get_singleton()->get_time_scale();

   bool exit=false;

   int iters = 0;

   while(time_accum>frame_slice) {

      uint64_t fixed_begin = OS::get_singleton()->get_ticks_usec();



      if (OS::get_singleton()->get_main_loop()->iteration( frame_slice*time_scale )) {



      //if (AudioServer::get_singleton())
      // AudioServer::get_singleton()->update();


   uint64_t idle_begin = OS::get_singleton()->get_ticks_usec();

   OS::get_singleton()->get_main_loop()->idle( step*time_scale );

   if (SpatialSoundServer::get_singleton())
      SpatialSoundServer::get_singleton()->update( step*time_scale );
   if (SpatialSound2DServer::get_singleton())
      SpatialSound2DServer::get_singleton()->update( step*time_scale );

   if (OS::get_singleton()->can_draw()) {

      if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) {
         if (VisualServer::get_singleton()->has_changed()) {
            VisualServer::get_singleton()->draw(); // flush visual commands
      } else {
         VisualServer::get_singleton()->draw(); // flush visual commands
         force_redraw_requested = false;
   } else {
      VisualServer::get_singleton()->flush(); // flush visual commands

   if (AudioServer::get_singleton())

   for(int i=0;i<ScriptServer::get_language_count();i++) {


   if (script_debugger)

   // x11_delay_usec(10000);

   if (frame>1000000) {

      if (GLOBAL_DEF("debug/print_fps", OS::get_singleton()->is_stdout_verbose())) {
         print_line("FPS: "+itos(frames));


      if (GLOBAL_DEF("debug/print_metrics", false)) {



   if (OS::get_singleton()->is_in_low_processor_usage_mode() || !OS::get_singleton()->can_draw())
      OS::get_singleton()->delay_usec(25000); //apply some delay to force idle time
   else {
      uint32_t frame_delay = OS::get_singleton()->get_frame_delay();
      if (frame_delay)
         OS::get_singleton()->delay_usec( OS::get_singleton()->get_frame_delay()*1000 );

   int taret_fps = OS::get_singleton()->get_target_fps();
   if (taret_fps>0) {
      uint64_t time_step = 1000000L/taret_fps;
      target_ticks += time_step;
      uint64_t current_ticks = OS::get_singleton()->get_ticks_usec();
      if (current_ticks<target_ticks) OS::get_singleton()->delay_usec(target_ticks-current_ticks);
      current_ticks = OS::get_singleton()->get_ticks_usec();
      target_ticks = MIN(MAX(target_ticks,current_ticks-time_step),current_ticks+time_step);

   return exit;


If you take a good look at that code, you'll notice beyond the complexity it's actually remarkably close to the pseudo code I started this post with. As I said, most game loops start looking pretty same-y over time. Now looking at the code you will notice a number of calls like this:


OS::get_singleton()->get_main_loop()->iteration( frame_slice*time_scale ))

These are callbacks in to the MainLoop we mentioned earlier. By default Godot implements one in C++ you can access here in core/os/main_loop.cpp:


#include "main_loop.h"
#include "script_language.h"

void MainLoop::_bind_methods() {




void MainLoop::set_init_script(const Ref<Script>& p_init_script) {


MainLoop::MainLoop() {


void MainLoop::input_text( const String& p_text ) {


void MainLoop::input_event( const InputEvent& p_event ) {

   if (get_script_instance())


void MainLoop::init() {

   if (init_script.is_valid())

   if (get_script_instance())

bool MainLoop::iteration(float p_time) {

   if (get_script_instance())
      return get_script_instance()->call("iteration",p_time);

   return false;

bool MainLoop::idle(float p_time) {

   if (get_script_instance())
      return get_script_instance()->call("idle",p_time);

   return false;
void MainLoop::finish() {

   if (get_script_instance()) {
      set_script(RefPtr()); //clear script



The default main loop in turn is mostly a set of callbacks into the active script.  You can easily replace this MainLoop implementation with your own, either in GDScript or C++.    Simply pass your class name in the to main_loop_type value in Project Settings:



Granted, very few people are actually going to need to do this…  mostly the people that want to live entirely in C++ land.  I do however think it’s extremely valuable to understand what is going on behind the scenes in a game engine!


The Video



26. January 2015


In this tutorial we are going to be taking a look at what seems to be everyone’s favorite subject, graphics.  We are going to start by creating a Sprite.  A Sprite is basically a 2D image with spatial information such as scale, rotation and position.  We are then going to take a closer look at coordinates and viewports, critical concepts to understand.


The video version of this tutorial is available here.


Creating a Sprite


Start by creating a new node in your scene panel.



Locate and create a “Sprite” node in the resulting dialog:



Now you need an image file to use as a Sprite.  You could simply copy one into the folder structure of your project at the file system level but in this case I am going to use the Import menu.  Select Import->2D Texture:



Locate the file ( it doesn’t have to be in your project directory ), and pick where you want it to be located locally, like so:



Once again, you do not have to import this way, you could have simply copied in the files to your project directory!


Ok, now that we have an image, let’s use it with our Sprite.  With the Sprite selected, in the Inspector panel locate Texture, drop it down and select Load.


Select your newly imported 2D Texture.


Now in your 2D view you will see your sprite positioned centered about the screen origin:



Navigating the 2D View


Now might be a good time to do a quick overview of how the 2D view works.  Let’s start off by looking at the 2D view itself

(Click image to expand)



This is where you position and manipulate the nodes that make up your world.  As you can see, the X-axis is marked in red and the Y axis is marked in green.  Where the two join, that is the world origin.  In this particular example, the viewport ( blue rectangle ) is in the negative Y and positive X quadrant.  However, child nodes positioning is relative to it’s parent, so to our sprite 0,0 appears to be the top left corner of the screen.


The selected object is surrounded by a manipulator cage.  This can be used to easily scale the image, while left clicking and dragging within the cage will move the selected node around.  Remember you can also set positioning information in the Inspector numerically.  You can switch to Rotate mode to rotate an object, objects rotate relative to their center point.  Pan on the other hand allows you to move the camera itself around, enabling you to “pan” through your world.


Mouse Controls:

Button Action
Left Mouse Button Click Select clicked node
Left Mouse Button Click + Drag Translate or Rotate selected
Middle Mouse Button Pan the scene
Scroll Wheel Zoom in/out


Keyboard Controls

Key Action
Q Select Mode
W Translate/Move Mode
E Rotate Mode
Arrow Keys Move selected, very fine
Shift + Arrow Keys Move selected
ESC Unselect
F1 Help Panel
F Center Camera on Selected
Ctrl + F Frame Camera (Zoom to fit) on Selected
Ctrl + P Expand to selected node’s parent
V (hold) Move pivot point




Some times snapping can be incredibly useful when laying out a scene.  Snapping essentially super imposes a grid over your scene and “snaps” the selected to that grid.  To enable Snapping, simply select Use Snap from the Edit Menu.



Using Configure Snap you can set the size of each grid in the snapping overlay.   Now your scene will look like this:



Note, this grid is just there to help you with accurate placement only!  It will not appear when you render your game.  Turn if off again by clicking Use Snap again.  If you are working on a tile based game, snapping can be invaluable.


Rotating, Translating and Scaling a Sprite using Code


So that covers how to add a Sprite to your world and how to navigate the 2D view, let’s take a quick look at the three most commonly performed actions… translating(moving), scaling and rotating.  The following code does all three:

extends Sprite

func _ready():

      #translate to center of the parent, in this case, the viewport
   var newPos = Vector2(self.get_parent().get_rect().size.width/2,self.get_parent().get_rect().size.height/2)
   #rotate by 90 degrees.  set_rot takes radians so we need to convert using in-built function
   #scale by 2x
func _draw():  
   # each frame draw a bounding rect to show boundaries clearer

And when you run that, you should see:



Please note, I quite often use self because I find it adds a bit of clarity and frankly makes code completion easier.  In the above code, “self” is the inherited class “Sprite”.  If you prefer shorter code, you can omit the use of self and it is functionally identical!


One important thing to understand is, all of these transformations happened relative to the Sprite’s pivot point, which by default is at it’s center.  If you zoom in on your Sprite object you should be able to see the pivot point:



It’s the T like cross hair.  This point determines where local transforms occur relative to.  For example, when you say “rotate 90 degrees’ you are rotating 90 degrees around this point.  In the 2D editor, you can move this point ( or more accurately, move the Sprite relative to this point ), by holding the V key down while moving.


Here for example I hit W then left click dragged to move the sprite slightly.  Then I held down V and moved the sprite only and not the pivot point, like so:



Now if I run the same code, you will see that transforms are performed relative to this point instead of the middle:



This value can also be controlled in the Inspector.  It is called the offset and it is a value relative to the Node’s center point:



Or you can change the offset in code.  For example, to make the pivot the bottom left corner of the Sprite, you could do the following:

func _ready():

   var newOffset = Vector2(self.get_item_rect().size.width/2, -self.get_item_rect().size.height/2)


With the following result:



So, quick summary…  child Nodes are positioned relative to their parents and the top level node is the viewport.  All transformations happen relative to an objects offset, that offset is relative to the objects center which by default is the Node’s midpoint.


A Bit about Viewports


We should pause a bit to discuss the viewport, it’s a critical concept in graphics.  As you may notice in the earlier screenshots, the Viewport is drawn as a blue rectangle, with it’s top left corner at 0,0 in 3D space.  By default in Godot 2D, the root node is a viewport, which is why we could access it using get_parent() from our sprite node.  So, where exactly are this viewport’s dimensions set?  Good question!




In the Scene menu select Project Settings.  The following dialog appears ( this is where we set default scene earlier ):



These are your key viewport related settings.  Obviously width and height are what determine the dimensions of your viewport.  There are a few other key settings here too, such as resizable and fullscreen, that determine how the window works on a desktop computer ( these settings are meaningless on mobile devices ).  Orientation on the other hand is important to mobile devices ( landscape vs portrait or lengthwise vs widthwise ) but meaningless on PCs.  stretch_mode and stretch_aspect are useful for dealing with devices of differing resolutions, we will probably cover this in more detail in a separate posting.


Viewports are critical as they allow you to work across a number of different devices in different resolutions using the same basic code.


The Video Version



22. January 2015


Welcome to the first coding tutorial of the Godot tutorial series.  We are going to take a quick look at the Godot IDE then jump in and create our first application.  I want to say right up front, I am no Godot expert, so if I may a mistake or you spot something questionable be sure to point it out!  There certainly may be a better or more efficient way of doing things.  There is also a video version of this tutorial available here.  An embedded version is available down below.  The video covers the same topic but may go into a bit more detail.  This first tutorial goes in to a great deal of detail and all subsequent tutorials will assume you’ve read or watched the ones that come before.  As a result, future tutorials will probably be much shorter, or at least, have less screenshots.


Alright, without further ado, let’s jump in!


First off, you obviously need to have Godot installed before you continue.  If you havent already, go download Godot now.


Creating an initial project


Now when you run Godot you should see the following window appear:



If you have an existing project, you can load it here.  Also, if you have downloaded the demos and samples ( direct zip link ) you can load them using the Import button.  In our case however we want to create a new project.  Click the New Project button:



A new dialog will open.



Click the Browse button and navigate to the folder you wish to create your project in.  Keep in mind, Godot will not create a folder for your project, so use the Create Folder button should you need one.  Here are the settings I am using:



Once you have selected your directory, click Open.  Then in the previous dialog, the project name will be set to that of the directory you choose.  Once happy, click Create.



Now either double click or click select your project and choose Edit




Adding A Node to the World


You should now be in the main editor interface.  Let’s start creating our application.  First thing we need to add a text node to our world.  On the right hand side of the screen, make sure the Scene tab is selected, then click the Add/Create a new node button.



Now in the resulting dialog, locate RichTextLabel then click Create.



A new node will be added to your scene hierarchy:



You can rename the node by double clicking, I’ve renamed mine HelloWorldLabel:



With the Node selected, you can see it’s editable properties in the Inspector window:



Adding a Script


One thing you might notice is there is no property available to set the text!  Time for a bit of scripting.  We need to attach a script to our node.  In the scene panel, select your RichTextLabel node and click the script icon:



If there isn’t a script attached, this icon will bring up the following dialog:



Click the .. next to Path.  Now click “Create Folder”, create one called Scripts then click OK.  I should point out, this is completely optional, you could of course just put all the stuff in the root of your application.  You should note that the file system in Godot is entirely relative to the projects root directory.  If you want an asset included in your game, it needs to be copied into this folder or a subfolder to be usable.



Now name your script.  NOTE!  You have to add the .gd file format, unfortunately Godot wont do it for you.  I called mine “”.  Once done, click “Save”



Finally click “Create”



Script Editing


Once you hit Create, you should automatically be brought to the code editing window, like so:



As you can see, Godot has created a new script that inherits from RichTextLabel.  It implements the _ready() method which is where you do all the creation related logic in your script.  If you come from another language, _ready is not the constructor, it is not the first method to be called.  If you need constructor like behavior, instead use _init().  _ready() is an overrideable function inherited from Node which is the base class of all things that can appear in the Scene.  You will be seeing a lot of Node in the future!


As to GDScript itself, it’s a Python-esque scripting language, so if you’ve got some Python experience, you will feel immediately at home.  If you are used to curly brace ( { } ) languages like C++ or Java, the critical thing to understand is it uses newlines in place of curly braces and semi colons.  Don’t worry, while jarring at first, you will quickly get used to it.


Now if you want to brush up on GDScript, I recommend the following sources:


Additionally, you can access the library reference at any time in the Help tab or by Pressing F1:



You can also get context sensitive help by pressing Shift + F1 when using the Script tab.


Ok… that’s enough language overview, let’s change our code to set the text when our control loads.  Simply replace the code with:

extends RichTextLabel

func _ready():
   self.add_text("Hello World")


self is basically the same as this in other languages, which returns a reference to the local object.  In this case, self is a RichTextLabel.  We are calling the method add_text() that we inherited from RichTextLabel, setting the text for our control.


Next we want to run our code… but we can’t just yet.  First we need to set our default scene…  oh, and while we are on that topic, we need to save our scene!


Setting the Default Scene


First let’s save our scene.  Select the Scene menu button and select Save Scene.



In the resulting dialog, select a location and name.  Be sure to add the scn extension, as Godot requires it and wont do it for you!  Just like scripts, you could save all of your scenes in a scene folder, but in this case I’m just going to save in the root directory using the default name new_scene.scn.  When done click Save.



Ok, now that we have a scene, we need to set it as the default scene that is run when we load our game.  To do so, click Scene->Project Settings:



In the resulting dialog, locate main scene, then hit the folder icon to it’s right:



Select File…



Select your scene, then click Open.



Running your application


Now you can run your scene.  Simply click the play icon across the top of the application:



If everything went according to plan, you should see something like this:



Congratulations, you’ve just created your first Godot game!  Now, let’s make it suck slightly less!


To stop your application from running, simply click the Stop icon to the right of the play icon.


Editing a Scene Node


You may notice our text is across two lines and in the top left corner of the screen.  This is because we didn’t set the size or position.  Both of which can be done in the 2D Scene pane.



First, switch over to 2D Scene:


You can now see our RichTextLabel as a small rectangle at the top left corner:


You can use this window to position your various nodes in your scene.  If your node isn’t selected, you can select it by clicking it in the 2D window, or by selecting it from the Scenes panel to your right. 


Left click and drag within the selection to move it.  Grab one of the circles from the corner to resize it, like so:



If you look at the Inspector panel, you will see the values have been updated as you edit them in the scene:


You can also enter numeric values in the Inspector window if you prefer more precise control.  Just be sure to hit enter or your changes will not be saved.


Loading and changing a Font


One question you may have is, how do I change the size of the text?  The answer is, using a font.  You need to create a font for each size of text you want.  Fortunately creating fonts is incredibly simple.  From the Import menu, select Font



Now you will be able to import an existing font.  If you are running windows, several ttf ( TrueType Font ) files are located in Windows\Fonts.  Please note, these fonts are almost all trademarked and cannot be used without permission in a shipped game!  There are hundreds of open license TTF fonts available for download however.


So, open your font, select the size and properties you want to set, then set the Dest Resource filename, making sure to have the .fnt extension.  Finally click Import.


Now you need to set your RichTextLabel to use your new font.  With your label selected, in the Inspector window, locate Custom Font, click the drop down and select Load.  Select your newly imported font.



Now when you run the code, you should see:



Adding a Timer and wiring events


Now let’s add a bit of functionality to our app.  A lot of the logic in Godot is available in included nodes.  Let’s add a timer as a child to our RichTextLabel, that will be called every second, updating a counter on our message.


First we need to add a child node.  With our RichTextLabel selected in the Scene panel, click the New Node icon and add a Timer:



Select Timer and click Create.  Your timer should now appear as a child of your RichTextNode, like so:



Make sure the Timer is select and in Inspector, set the property AutoStart to on:



This will create a timer that is called every second and starts running as soon as it’s created.  Now lets connect the timer to our RichTextLabel.  In the Scene panel, with Timer selected, click the Edit Node Connections icon:



Next select the timeout() connection, which is the callback that will be called each time the timer “ticks”.  Then hit “Connect…”



In the next dialog, the defaults should be good.  This is wiring a connection between the timer object and the RichTextLabel.  When the connection is fired, it will call the method you are creating, in this case _on_Timer_2_timeout.  When done, click Connect:



This will automatically add a function to your script file and bring you to the Script editor.  Now let’s change our code slightly.  We are going to add a member variable that counts the number of seconds and update our total each time the timer ticks.  Edit your code like so:

extends RichTextLabel

var count = 0

func _ready():
   self.add_text("Hello World")

func _on_Timer_2_timeout():
   count += 1
   self.add_text(str("Hello World!  Elapsed seconds = ",count))   


As you can see, we add a variable named count with the value 0.  GDScript is “duck typed” in that it infers the type from the value it is given.  So “if it looks like a duck, acts like a duck and quacks like a duck… it’s a duck!”, just applied to variables. 


Next you will notice Godot has added the func _on_Timer_2_timeout, which will be called by our timer each time it ticks.  We simply increment our counter, clear the existing value from out label, then add new text.  To concat our string and count variables together we use the built in str() function, which is similar to printf in other languages.


Now when your code runs, you will see:



… and that is the basics of creating an application in Godot.  In the future we will hopefully go in depth on all aspects of using Godot.  If you have any questions or comments, please don’t hesitate to ask!


The Video



GFS On YouTube

See More Tutorials on!

Month List