Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon
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.

image

 

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

image

 

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:

image

 

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:

image

 

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.

image

Select your newly imported 2D Texture.

 

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

image

 

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)

image

 

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

 

Snapping

 

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.

image

 

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

image

 

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)
   self.set_pos(newPos)
   
   #rotate by 90 degrees.  set_rot takes radians so we need to convert using in-built function
   self.set_rot(deg2rad(90))
   
   #scale by 2x
   self.set_scale(Vector2(2,2))
   
func _draw():  
   # each frame draw a bounding rect to show boundaries clearer
   self.draw_rect(self.get_item_rect(),Color(0,0,1,0.2))
 

And when you run that, you should see:

image

 

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:

image

 

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:

image

 

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

image

 

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:

image

 

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)
   self.set_offset(newOffset)

 

With the following result:

image

 

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!

 

image

 

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

image

 

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

 

Programming


22. January 2015

 

Welcome to the first coding tutorial of the GameFromScratch.com 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:

image

 

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:

image

 

A new dialog will open.

image

 

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:

image

 

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.

image

 

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

image

 

 

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.

image

 

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

image

 

A new node will be added to your scene hierarchy:

image

 

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

image

 

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

image

 

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:

image

 

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

image

 

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.

image

 

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

image

 

Finally click “Create”

image

 

Script Editing

 

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

image

 

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:

image

 

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.

image

 

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.

image

 

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:

image

 

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

image

 

Select File…

image

 

Select your scene, then click Open.

image

 

Running your application

 

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

image

 

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

image

 

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:

image

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

image

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:

image

 

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

image

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

image

 

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.

image

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.

image

 

Now when you run the code, you should see:

image

 

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:

image

 

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

image

 

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

image

 

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:

image

 

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

image

 

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:

image

 

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.clear()
   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:

image

 

… 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

 

Programming


20. January 2015

 

In this third part of multiple part video tutorial looking at using Scene2D we look at creating Groups for organizing Actors, as well as hit testing, making it possible to select actors available in your scene.  All of the code is included below.  For an HD version of the video click here.

 

 

Groups

package com.gamefromscratch.group;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.utils.viewport.ScreenViewport;

public class GroupDemo extends ApplicationAdapter implements InputProcessor {
   Stage stage;

   @Override
   public void create () {
      stage = new Stage(new ScreenViewport());
      Group group =  new Group();

      Image tableImg = new Image(new Texture(Gdx.files.internal("table.png")));
      Image aceImg = new Image(new Texture(Gdx.files.internal("ace.png")));
      Image kingImg = new Image(new Texture(Gdx.files.internal("king.png")));

      tableImg.setName("table");
      aceImg.setName("ace");
      kingImg.setName("king");

      group.addActor(tableImg);
      group.addActor(kingImg);
      group.addActor(aceImg);

      stage.addActor(group);

      kingImg.setPosition(300,150);
      aceImg.setPosition(400,150);

      Gdx.input.setInputProcessor(this);
   }

   @Override
   public void render () {
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
      stage.act(Gdx.graphics.getDeltaTime());
      stage.draw();
   }

   @Override
   public boolean keyDown(int keycode) {
      Group group = (Group)stage.getActors().first();
      Image ace = (Image)group.findActor("ace");

      if(keycode == Input.Keys.RIGHT)
         if(Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT))
            ace.setRotation(ace.getRotation() + 1f);
         else
            group.setRotation(group.getRotation() + 1f);

      if(keycode == Input.Keys.LEFT)
         if(Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT))
            ace.setRotation(ace.getRotation() -1f);
         else
            group.setRotation(group.getRotation() - 1f);

      if(keycode == Input.Keys.UP)
         group.setColor(group.getColor().r,group.getColor().g,
               group.getColor().b,group.getColor().a + 0.1f );

      if(keycode == Input.Keys.DOWN)
         group.setColor(group.getColor().r,group.getColor().g,
               group.getColor().b,group.getColor().a - 0.1f );

      if(keycode == Input.Keys.NUM_1)
         ace.setZIndex(ace.getZIndex() -1);
      if(keycode == Input.Keys.NUM_2)
         ace.setZIndex(ace.getZIndex() +1);

      return true;
   }

   @Override
   public boolean keyUp(int keycode) {
      return false;
   }

   @Override
   public boolean keyTyped(char character) {
      return false;
   }

   @Override
   public boolean touchDown(int screenX, int screenY, int pointer, int button) {
      Vector2 coord = stage.screenToStageCoordinates(new Vector2((float)screenX,(float)screenY));
      Actor hitActor = stage.hit(coord.x,coord.y,false);

      if(hitActor != null)
         Gdx.app.log("HIT",hitActor.getName());

      return true;
   }

   @Override
   public boolean touchUp(int screenX, int screenY, int pointer, int button) {
      return false;
   }

   @Override
   public boolean touchDragged(int screenX, int screenY, int pointer) {
      return false;
   }

   @Override
   public boolean mouseMoved(int screenX, int screenY) {
      return false;
   }

   @Override
   public boolean scrolled(int amount) {
      return false;
   }
}

Programming


9. January 2015

 

I needed to create a sprite sheet for an upcoming tutorial series and managed to throw one together in an amazingly short amount of time with almost no artistic ability.  Good looking art with no ability is something many indie game developers are screaming for, so I figured I would share the process.

 

During the tutorial we use the following programs:

Mixamo Fuse (Free version available, MSRP $99USD)

Blender (Free and Open Source)

TexturePacker (Free version available, MSRP $50USD)

 

If you want more details on Mixamo, I extensively review it here.

 

The ultimate output from this entire process is the sprite sheet powering this animation:

bigguy

 

And here is the resulting sprite sheet, click it for the full resolution version:

a

 

Now finally, the video.  You can watch it in full 1080p on YouTube.

 

Coincidentally, if you want more information on how I created the above animated gif, I used a program called Cryotek Animated GIf Creator, and document the process here.  It’s a very cool program and completely free.

Programming Art General


4. January 2015

 

Gamefromscratch has a long running series taking an indepth look at various game engines available.  Today we are going to look at the Godot game engine, an open source C++ based game engine with a complete Unity-esque world editor.  Godot runs on Windows, Linux and Mac platforms and can target all of those, plus iOS, Android, PS3 and PS Vita, NaCL with HTML5 and Windows Phone both being in development.

 

In Godot’s own words:

Godot is an advanced, feature packed, multi-platform 2D and 3D game engine. It provides a huge set of common tools, so you can just focus on making your game without reinventing the wheel.

 

That description is incredibly apt as well, you will certainly be surprised by just how many tools are included.  Now let’s jump right in!

 

There is a video on this post available here (and embedded at bottom of the page) which goes in to a bit more detail.

 

The Editor

 

You get started with Godot by downloading the executable from the downloads page.  You probably expect this to be an installer, but you would be wrong.  Instead when you run it you get the Project Manager:

image

 

Here you can either create a new project or load an existing one.  Finally once you’ve selected or created, you are brought to the editor:

image

 

This is where the magic happens.  The above screenshot is of the Platformer demo being edited.  The left hand window is where your scene is composed.  As you can see from the four tabs above, you can work in 2D, 3D, Script editing or browse the built in help in this window.  The top left icons are actually menus and a lot of the functionality and tools are tucked away behind Scene and Import.

 

The top right hand dialog is your scene graph:

image

 

Here you can see ( and create/instance ) the items that make up your world.  Simply click the New Icon to add a new items to the world, or the + Icon to add a new instance instead.  The other icons are for wiring scripts and signals (events) up to the objects in your world.

 

Below the scene graph, you’ve got the Inspector window, which enables you to set properties of objects in your scene.  As you can see from the screen shot, Godot takes a very modular/component approach which is quite popular these days:

image

 

This enables you to visual inspect and edit properties of your game objects.  It also represents one of the first flaws of Godot… some of the controls are just awkward to use.  For example if you don’t hit enter after editing a text property, the values are lost.  Additionally modifying numeric fields can be a pain in the ass at times.  It’s all stuff that can be fixed with time ( Godot was only open sourced about a year ago after all ) but for now its clunky and somewhat annoying.

 

Coding

 

So that’s the visual editor… what about code? 

 

Well the majority of your programming is going to be done in GDScript, using the included editor.  GDScript is a Python-esque proprietary scripting language.  I don’t generally like this approach as it makes all the existing tools and editors worthless, lose the years of bug fixing, performance improvements, etc…  while forcing a learning curve on everyone that wants to use the engine.  That said, the idea behind a scripting language is they should be easy to use and learn.

 

The authors explained their decision in the FAQ:

 

The short answer is, we'd rather a programmer does the small effort to learn GDScript so he or she later has a seamless experience, than attracting him or her with a familiar programming language that results in a worse experience. We are OK if you would rather not give Godot a chance because of this, but we strongly encourage you to try it and see the benefits yourself.

The official languges for Godot are GDScript and C++.

GDScript is designed to integrate from the ground to the way Godot works, more than any other language, and is very simple and easy to learn. Takes at much a day or two to get comfortable and it's very easy to see the benefits once you do. Please do the effort to learn GDScript, you will not regret it.

Godot C++ API is also efficient and easy to use (the entire Godot editor is made with this API), and an excellent tool to optimize parts of a project, but trying to use it instead of GDScript for an entire game is, in most cases, a waste of time.

Yes, for more than a decade we tried in the past integrating several VMs (and even shipped games using them), such as Python, Squirrel and Lua (in fact we authored tolua++ in the past, one of the most popular C++ binders). None of them worked as well as GDScript does now.

More information about getting comfortable with GDScript or dynamically typed languages can be found here.

 

That covers the why anyways, now let’s look at the language itself.  As I said earlier, it’s a Python like (whitespace based) scripting language.  Let’s look at an example from the included demos:

extends RigidBody2D


const STATE_WALKING = 0
const STATE_DYING = 1

var state = STATE_WALKING
var direction = -1
var anim=""
var rc_left=null
var rc_right=null
var WALK_SPEED = 50

var bullet_class = preload("res://bullet.gd")

func _die():
   queue_free()

func _pre_explode():
   #stay there
   clear_shapes()
   set_mode(MODE_STATIC)
   get_node("sound").play("explode")
   

func _integrate_forces(s):

   var lv = s.get_linear_velocity()
   var new_anim=anim

   if (state==STATE_DYING):
      new_anim="explode"
   elif (state==STATE_WALKING):
      
      new_anim="walk"
      
      var wall_side=0.0
      
      for i in range(s.get_contact_count()):
         var cc = s.get_contact_collider_object(i)
         var dp = s.get_contact_local_normal(i)
         
         if (cc):
         
            
            if (cc extends bullet_class and not cc.disabled):
               set_mode(MODE_RIGID)
               state=STATE_DYING
               s.set_angular_velocity(sign(dp.x)*33.0)
               set_friction(true)
               cc.disable()
               get_node("sound").play("hit")
               
               break
            

         if (dp.x>0.9):
            wall_side=1.0
         elif (dp.x<-0.9):
            wall_side=-1.0
            
      if (wall_side!=0 and wall_side!=direction):
      
         direction=-direction
         get_node("sprite").set_scale( Vector2(-direction,1) )       
      if (direction<0 and not rc_left.is_colliding() and rc_right.is_colliding()):
         direction=-direction
         get_node("sprite").set_scale( Vector2(-direction,1) )
      elif (direction>0 and not rc_right.is_colliding() and rc_left.is_colliding()):
         direction=-direction
         get_node("sprite").set_scale( Vector2(-direction,1) )
         
         
      lv.x = direction * WALK_SPEED
         
   if( anim!=new_anim ):
      anim=new_anim
      get_node("anim").play(anim)
            
   s.set_linear_velocity(lv)


func _ready():
   rc_left=get_node("raycast_left")
   rc_right=get_node("raycast_right")

 

As someone raised on curly braces and semi colons it can take a bit of time to break muscle memory, but for the most part the language is pretty intuitive and easy to use.  You can see a quick language primer here.

Remember earlier I said the code editor was built into the engine, let’s take a look at that now:

image

 

As you can see, the editor does provide most of the common features you would expect from an IDE, a personal favorite being auto-completion.  Features like code intention, find and replace and auto indention are all available, things often missing from built in editors.   Like dealing with the Inspector window though their can be some annoyances, like the autocomplete window appearing as you are trying to cursor around your code, requiring you to hit Escape to dismiss it.  For the most part though the editing experience is solid and hopefully some of the warts disappear with time.

 

Now perhaps the biggest deal of all:

image

Debugging!  This is where so many home made scripting languages really suck, the lack of debugging.  Not Godot:

image

You can set breakpoints, step into/over your running code and most importantly inspect variable values and stack frames.  Once again, it’s the debugging experience that often makes working in scripting languages a pain in the ass, so this is nice to see!

 

Hey, What about C++???

 

Of course, one of the big appeals of Godot is going to be the C++ support, so where exactly does that come in?  Well first and most obviously, Godot is written in C++ and fully open source under the MIT license ( a very very very liberal license ), so you can of course do whatever you want.  I pulled the source from Github and built without issue in Visual Studio 2013 in just a few minutes.  The build process however is based around Scons, which means you have to Python 2.7x and Scons installed and configured, but neither is a big deal.

 

What about extending Godot, that is what the majority of people will want to do.  Well fortunately it’s quite easy to create C++ extensions, although again you need Scons and have to do a bit of configuration, but once you’ve done it once assuming you’ve got a properly configured development environment the process should be quick and mostly painless.  From the wiki page here is a sample C++ module:

 

Sumator.h

/* sumator.h */
#ifndef SUMATOR_H
#define SUMATOR_H

#include "reference.h"

class Sumator : public Reference {
    OBJ_TYPE(Sumator,Reference);

    int count;

protected:
    static void _bind_methods();
public:

    void add(int value);
    void reset();
    int get_total() const;

    Sumator();
};

#endif

Sumator.cpp

/* sumator.cpp */

#include "sumator.h"

void Sumator::add(int value) {

    count+=value;
}

void Sumator::reset() {

    count=0;
}

int Sumator::get_total() const {

    return count;
}

void Sumator::_bind_methods() const {

    ObjectTypeDB::bind_method("add",&Sumator::add);
    ObjectTypeDB::bind_method("reset",&Sumator::reset);
    ObjectTypeDB::bind_method("get_total",&Sumator::get_total);
}

Sumator::Sumator() {
    count=0;
}

 

Then in your script you can use it like:

var s = Sumator.new()
s.add(10)
s.add(20)
s.add(30)
print( s.get_total() )
s.reset()

 

If you inherit from Node2D or a derived class, it will be available in the editor.  You can expose properties to the inspector and otherwise treat your module like any other Node available.  Remember though, for productivity sake, you should really only be dropping to C++ as a last resource.  It is however quite simple to do.

 

Nodes, Nodes and more Nodes

At the heart of Godot, the world is essentially a tree of Nodes, so I suppose it’s worthwhile looking at some of the nodes available and how they work.  From the scene graph window, you add a new node to the world using this icon:

image

 

Next it’s a matter of picking which type, which could of course include modules you created yourself in C++.

image

 

As you can see from the small portion I’ve shown above, there are a LOT of built in nodes already available.  From UI controls, to physics controllers, path finding and AI tools, bounding containers, video players and more.  Essentially you create your game by composing scenes, which then are composed of nodes.  Once you’ve created a node you can then script it.  Simply select your node in the scene graph and then click the script icon:

image

 

Then a New Script dialog will be displayed:

image

 

And your script will be created:

image

 

As you can see, the script itself inherets from the node type you selected.  You can now script any and all logic attached to this particular Node.  Essentaily your game logic is implemented here.

 

In addition to wiring up scripts to game nodes, you can also wire up Signals.

image

 

Signals can be thought of as incoming events:

image

 

HELP!

 

So, what about Help then?  Well this is both a strength and weakness of Godot.  As you saw earlier, there is actually an integrated help tab.  You can look it up any time, or use press SHIFT + F1 while coding to get context sensitive help:

image

It’s invaluable, but unfortunately the resulting help file is often just a listing of methods/parameters and nothing more.  I often instead just keep the class reference from the Wiki open in a browser window.  For an open source project, the reference is pretty good, but it could still certainly use a lot more love.

 

Next are the tutorials, there’s a fairly good selection available on the Wiki but I think a good in-depth beginner series is really needed.  To someone that just downloaded Godot and is thinking “now what”… that presents a challenge. That said, I will probably be creating one, so this shouldn’t be an issue in time!

 

Finally, and perhaps most valuably, there are several demos included:

image

 

Publishing

 

So, once you’ve finished your game, how do you publish it to the various available platforms?  Well for starters you click the Export button:

image

 

You also need an export template, which is available from the Godot downloads site.  Additionally you need to  configure the tool chain for each platform, such as the Android SDK for Android, XCode for iOS ( and a Mac!  You can’t end run around the needing a Mac for iOS development requirement unfortunately), etc.  But the process is spelled out for you and they make it pretty easy.

 

Summary

 

I haven’t even really touched upon the plethora of tools tucked away in the editor…  need to import a font, there’s a tool for that.  There’s an improved Blender COLLADA plugin which just worked when I tried it.  There’s a tool for mapping controls to commands, there are tools for compressing and modifying textures on import, for modifying incoming 3D animations, etc…  Basically if you need to do it, there is probably a tool for it shoved in there somewhere.

 

On the other hand, the process itself can be pretty daunting.  Figuring out how to get input, a script’s life cycle etc isn’t immediately obvious.  It really is an engine you have to sit down with and just play around.  Sometimes you will hit a wall and it can be pretty damned frustrating.  However, it’s also a hell of a lot of fun and once it starts to click it is a great engine to work in.

 

I definitely recommend you check out Godot, especially if you are looking for an open source Unity like experience.  That said, calling this a Unity clone would certainly be doing it a disservice, Godot is a great little game engine on it’s own accord that deserves much more exposure.

 

The Video Version

 

Click here for the full resolution 1080p version.

Programming


GFS On YouTube

See More Tutorials on DevGa.me!

Month List