Flint Dev Diary – Intro

It’s been some time since my last blog post (not including tutorials), I figured it’s time to start a small dev blog on the progress of one of my current projects.

About the Game and Lessons Learnt:

A friend who I worked with on Tides of War and I have been working on a 2D game. To sum it up, it will be a 2D platformer with shooting and some RPG progression elements, and a story (I really like character / story-driven games). Development is on a spare-time basis, as we both have other commitments and the project is just for fun.

For the technical side of the game, we are using my own engine ‘Wildfire’, C++ for core game code and eventually Lua for AI scripting. When working on my first platformer (also in C++) back in 2012, myself and a fellow programmer I was working with ‘hacked’ a lot of features together – as we had six weeks to make that game for an assignment. We were loading level files that looked similar to this:

old format

Yes, this mess represented various obstacles, platforms, collectibles, enemies and so on. We had an even more complex mess in C++ which read the text file and created the level using those letters and symbols.

For this new project however, I wanted to give design control to my friend as well but the project wouldn’t go very well if he had to tediously build levels in text files like I had done back then. Imagine the designer(s) on a modern game trying to build levels without some form of visual tool. It was obvious, we needed our own level editor.

Flint v1.2 and naming:

Since the engine is called ‘Wildfire’, we tossed around fire-related words to name the level editor to stick to the ‘theme’. We settled on ‘flint’, which seems fitting as flint is used to start a fire.

I have built Flint using C# and Windows Forms. Being a level editor for a 2D tile-based game, Flint’s key features are:

  • A Tile palette (set of tiles to build the level with)
  • Scene (or ‘level’) view for building the level
  • Placing and deleting tiles in the level
  • Exporting the level data for use in game project

There are of course other important features such as saving/loading tile palette and scene, adding background textures, clicking on a tile to view its data and so on. Last week I finished version 1.2 of the editor, here is a screenshot of how it’s looking:

flint_v1.2

For testing purposes, I did some quick ‘programmer art’ and one tile is even recycled from a past project.

Until next time:

Perhaps this has been interesting or inspired you to make your own level editor. I had been very interested in making a level editor for a while and now it’s a reality. Flint is now ready for when we start making levels and I already have a few ideas for some new features in its next version.

Xbox360 Gamepad Input & Management – Unity Tutorial (Part 5)

Legacy Tutorial – Please note: This tutorial was last tested in Unity 5.3.3f1 (x64 ‘Personal’ version). I am not currently using Unity as I use and develop my own engine technology. The code in this tutorial is all C# and calls to the XInputDotNet plugin, it should port over to more recent versions of the engine just fine.

Welcome to the final part of my Xbox360 gamepad tutorial for the Unity engine!

In Part 4 we designed and set up the GamepadManager system. We’re very close to finishing it and in this part, we’ll be adding its ‘Utility’ functions for features including retrieving a gamepad to use it for input in another script and checking if any connected gamepad has a certain button pressed!

Before we get started, I highly recommend reading the previous parts of this tutorial and following the code listings, if you’re reading this and haven’t already. This part picks up right where Part 4 left off and references certain gamepad features implemented in earlier parts of the tutorial.

Jump to:
Part 1 – Setting up
Part 2 – Button input
Part 3 – Rumble + Thumbstick and Trigger input
Part 4 – Gamepad Management – ‘Core

Return Specific Gamepad:

Since the GamepadManager is designed to support input needs from a single player (1 gamepad) game to a local splitscreen / single-screen multiplayer game (2 to 4 gamepads), the first ‘Utility’ feature we need is a function to retrieve the gamepad we are after.

// Return specified gamepad
// (Pass index of desired gamepad, eg. 1)
public x360_Gamepad GetGamepad(int index)
{
      for (int i = 0; i < gamepads.Count;)
      {
            // Indexes match, return this gamepad
            if (gamepads[i].Index == (index - 1))
                  return gamepads[i];
            else
                  ++i;
      }

      Debug.LogError("[GamepadManager]: " + index + " is not a valid gamepad index!");

      return null;
}

We simply loop through the gamepads list, checking the index of each gamepad against the index parameter (subtracting 1 because of how XInputDotNet works). The function returns the gamepad instance that matches the index, or if there is no match, returns null and sends an error to the console explaining the index you passed is invalid.

Remember, what you set GamepadCount to is how many gamepads you want to support. If you set it at 2 for example, passing 3 or 4 to this function will result in that error because the manager is not storing any gamepad past #2 in this case.

Connected Total:

You may want to show how many gamepads are connected to the PC somewhere in your game, such as a menu, or use this number to change the appearance of the HUD for a multiplayer co-op game. You may have more ideas of what you could use this number for, the list goes on! As the name suggests, this function simply returns the number of gamepads that are connected to the PC.

// Return number of connected gamepads
public int ConnectedTotal()
{
      int total = 0;

      for (int i = 0; i < gamepads.Count; ++i)
      {
            if (gamepads[i].IsConnected)
                  total++;
      }

      return total;
}

Looping through the gamepads list, we check if each one is connected and increase the total variable if so. The total variable is then returned and reset to zero each time this function is called.

Button Input from any Gamepad:

I was making some systems for a co-op game and wanted any player with a connected gamepad to be able to press a certain button to start the level from the lobby screen. Rather than restrict a certain action to only gamepad #1, I wanted any connected gamepad to be able to perform the action. That’s why I made this ‘GetButtonAny‘ function.

// Check across all gamepads for button press.
// Return true if the conditions are met by any gamepad
public bool GetButtonAny(string button)
{
      for (int i = 0; i < gamepads.Count; ++i)
      {
            // Gamepad meets both conditions
            if (gamepads[i].IsConnected && gamepads[i].GetButton(button))
                  return true;
      }

      return false;
}

Looping through the gamepads list, we check that the current gamepad is a) connected and b) its ‘GetButton‘ function returns true, meaning it has the specified button pressed. If both conditions are met, the function immediately returns true without checking any remaining gamepad(s). Regardless of gamepad number, the first gamepad to meet both conditions causes this. The function returns false if no gamepad meets both conditions.

Button ‘Down’ Input from any Gamepad:

This function is nearly identical to ‘GetButtonAny‘, however this time we use the gamepad’s ‘GetButtonDown‘ function instead. The ‘GetButtonDownAny‘ function allows us to check if any connected gamepad has pressed the specified button on the current frame only, by switching ‘GetButton‘ for ‘GetButtonDown‘ in the condition check.

// Check across all gamepads for button press - CURRENT frame.
// Return true if the conditions are met by any gamepad
public bool GetButtonDownAny(string button)
{
      for (int i = 0; i < gamepads.Count; ++i)
      {
            // Gamepad meets both conditions
            if (gamepads[i].IsConnected && gamepads[i].GetButtonDown(button))
                  return true;
      }

      return false;
}

‘GetButtonDownAny’ could also prove very useful for multi-gamepad menus. I used it for menu input on the co-op game project I mentioned.

Part 5 Summary:

We made it! We now have complete input support for an Xbox360 controller in the ‘x360_Gamepad‘ script and GamepadManager, a system to manage up to four gamepads, that even allows us to call a single function to check if any gamepad is pressing a button – without needing to write additional code to do it!

Thank you for reading this tutorial, I hope you’ve found it useful to roll your own custom xbox360 gamepad input solution! At the time of writing, this is my longest tutorial so far and it’s definitely been worth it – since I first got it all working how I designed it, I knew it was a system I wanted to share with others. Below are the links to download the complete C# script files, including a testing script to demonstrate the GamepadManager.

Code from Part 1-3: Download (7.4 KB)
Code from Part 4-5: Download (1.85 KB)
‘TestGamepad’ Script: Download (1.47 KB)

Jump to:
Part 1 – Setting up
Part 2 – Button input
Part 3 – Rumble + Thumbstick and Trigger input
Part 4 – Gamepad Management – ‘Core

Return to Tutorials

Xbox360 Gamepad Input & Management – Unity Tutorial (Part 4)

Legacy Tutorial – Please note: This tutorial was last tested in Unity 5.3.3f1 (x64 ‘Personal’ version). I am not currently using Unity as I use and develop my own engine technology. The code in this tutorial is all C# and calls to the XInputDotNet plugin, it should port over to more recent versions of the engine just fine.

Welcome to Part 4 of my Xbox360 gamepad tutorial for the Unity engine!

At the end of Part 3, we finished the ‘x360_Gamepad‘ script and it’s ready to go! Now it’s finally time to ‘manage’ some gamepads, it’s in the title of this tutorial series after all. Before we get started, I recommend reading and following the code in the previous parts if you’re reading this and haven’t already. Here is the link to download the complete tutorial code so far (you can also find it at the end of Part 3) and quick links to the other parts of this series.

Complete ‘x360_Gamepad’ C# script: Download (7.4 KB)

Jump to:
Part 1 – Setting up
Part 2 – Button input
Part 3 – Rumble + Thumbstick and Trigger input

Gamepad Management?

You could easily create an instance of the ‘x360_Gamepad‘ (or your class name) class in say, a character controller script to use the gamepad for player controls. The problem is this instance only exists there, if you wanted to get input from this instance in another script (several in my case, which is why I made this manager), you could find yourself writing more code to find the desired game object, get its desired script component and then get the gamepad instance from there.

To be honest, that’s what we did for a while on Tides of War. It might not be elegant but it does work. Before we get into the code, let’s sum up what we want the Gamepad Manager to do:

  • Store up to four gamepads (handy for co-op / multiplayer on single screen)
  • Exist only ONCE in the Unity project and be easy to access from ANY script
  • Created once, kept in each Unity scene should the project switch between them
  • Handle updating the gamepad(s) and any multi-gamepad functionality

Setting up the ‘GamepadManager’:

Feel free to call it whatever you like, for the rest of the tutorial I will be calling this system ‘GamepadManager’. Let’s start by creating two new C# scripts – ‘RefreshGamepads‘ (I’ll explain that one soon) and ‘GamepadManager‘. Of course, like any new script files they inherit from the MonoBehaviour class, which means we must attach them to a game object in the scene for them to run.

We’ll continue using ‘TestScene‘, our empty scene from Part 1. If you’re adding this system to an existing Unity project, use any scene you like. First, let’s create an empty game object. It won’t need anything fancy such as mesh or sprite renderers, or colliders. Since it won’t be visible, let’s position it to zero (all position values to zero). Next, attach the two new scripts we created. Now your ‘GamepadManager’ game object should look similar to this.

manager_setup

The Singleton Instance

This should sound familiar. Or you may be thinking “What’s a ‘singleton’?!”. For anyone unfamiliar, the Singleton is a design pattern in software development and we will use it for the GamepadManager. I won’t go into a lot of detail on the pattern itself, to put it simply though, it means the class will be created only once, prevent duplicate copies being created (on purpose or by mistake) and be accessible like a public variable…from anywhere in our other scripts!

Note: There are many great articles and tutorials in several programming languages on the net, detailing the Singleton and other design patterns.

The ‘GamepadManager‘ script is just a blank template at the moment, let’s remove the ‘Start‘ function Unity gave us and replace it with ‘Awake‘. We also need a few variables:

  • GamepadCount – Number of gamepads you want to support (1 to 4)
  • gamepads          – List container to store the gamepad instances
  • singleton            – Important! This is the static instance of the script.

Now the ‘GamepadManager’ script should look similar to this:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

// Gamepad Manager class
public class GamepadManager : MonoBehaviour
{
      public int GamepadCount = 2; // Number of gamepads to support

      private List gamepads;     // Holds gamepad instances
      private static GamepadManager singleton; // Singleton instance

      // Initialize on 'Awake'
      void Awake()
      {

      }

      // Normal Unity update
      void Update()
      {

      }
}

Note – ‘Awake’ vs ‘Start’: We’re using ‘Awake‘ because it is called by the engine before ‘Start‘ and is called only once when the script is loaded. The Unity documentation is very useful for looking up such functions! For more information, here are the Scripting API references for Awake and Start.

First, the GamepadManager should check to see if its singleton instance has been assigned AND if the singleton instance is NOT assigned to itself. You could think of it as the GamepadManager saying “My singleton is assigned but not to me!“. This means another instance of the GamepadManager was loaded, creating another copy of the singleton. We know the whole idea of the singleton is for there to be only ONE, not two or several copies.

If found, the duplicate singleton must be destroyed. We can perform this check with a simple if statement.

// Initialize on 'Awake'
void Awake()
{
      // Found a duplicate instance of this class, destroy it!
      if (singleton != null && singleton != this)
      {
            Destroy(this.gameObject);
            return;
      }
}

What if there isn’t a duplicate singleton? We run the remainder of our ‘Awake‘ function – the code to initialize the GamepadManager. We’ll  start by assigning the singleton instance to this – the current instance of the GamepadManager script, as now we immediately destroy any other instance(s) that are found (there should only be one in your scene anyway).

Once again, you could think of it as the GamepadManager saying “My singleton is assigned, to me!“. Now we have ticked off our “exist only once” feature, next we must keep the GamepadManager object between scenes. Should you switch from one scene to another while the game is running, Unity cleans up by destroying all objects in the scene before loading the next one. This is fine until you want to keep a certain object for the next scene and Unity has a function to just that!

// Initialize on 'Awake'
void Awake()
{
      // Duplicate singleton check...
      else
      {
            // Create singleton instance
            singleton = this;
            DontDestroyOnLoad(this.gameObject);
      }
}

Using the DontDestroyOnLoad function, we protect the GamepadManager object from being accidentally destroyed when switching scenes and tick off the “Created once, kept in each Unity scene” feature. Even if your game / project is just a single scene, it’s still handy to have this feature just in case.

Finally, to finish initializing the GamepadManager, we’ll restrict the GamepadCount to the supported 1 to 4 range and create the requested number of gamepad instances.

// Initialize on 'Awake'
void Awake()
{
      // Duplicate singleton check...
      else
      {
            // Create singleton instance...

            // Lock GamepadCount to supported range
            GamepadCount = Mathf.Clamp(GamepadCount, 1, 4);

            gamepads = new List();

            // Create specified number of gamepad instances
            for (int i = 0; i < GamepadCount; ++i)
                  gamepads.Add(new x360_Gamepad(i + 1));
      }
}

Accessing the Singleton Instance….From any Script:

So far we’ve created the GamepadManager singleton and the class will automatically check for and destroy any duplicates. Now let’s address the last, but definitely not least important feature of our singleton…being able to access it from any other script in the project.

Remember how we made the singleton variable static? I won’t detail use of the static keyword here, but simply put, it allows us to access the singleton instance without needing to make an instance of the class. If that sounds confusing, it will make sense very soon! Wait, we made the singleton variable private! Other scripts can’t access it at that protection level. Let’s make a ‘get‘ to publicly access the singleton from other scripts:

// Return instance
public static GamepadManager Instance
{
      get
      {
            if (singleton == null)
            {
                  Debug.LogError("[GamepadManager]: Instance does not exist!");
                  return null;
            }

            return singleton;
      }
}

First of all, you may notice this isn’t a function (eg. something(); ). Because we’re using C#, we made use of the ‘get‘ statement, so you could think of using this like a public variable rather than a normal function. I added the error check so Unity will actually send an error message to its console if the singleton has not been created. You would only get this error if the script was not on a game object in the scene and you tried accessing the GamepadManager in another script. We have already prevented this by setting up the ‘GamepadManager’ object earlier.

Well that wraps up the singleton functionality, we can use GamepadManager.Instance to access the singleton from other scripts. Of course, we don’t have any other functionality in the GamepadManager yet. Next, let’s update and refresh the GamepadManager.

Update and Refresh:

Since we kept the original Update function (that you get in any MonoBehaviour script), we’re going to use it to update the gamepad(s). All we do here is loop through the gamepads list and call the ‘Update’ function of each gamepad.

// Normal unity update
void Update()
{
      for (int i = 0; i < gamepads.Count; ++i)
            gamepads[i].Update();
}

The ‘Refresh‘ function is almost identical, however it must be public since we will need to call it elsewhere.

// Refresh gamepad states for next update
public void Refresh()
{
      for (int i = 0; i < gamepads.Count; ++i)
            gamepads[i].Refresh();
}

For the gamepad’s ‘GetButtonDown‘ (button press on current frame only) functionality to work, ‘Refresh‘ must be called at the end of our update cycle – or in this case, Unity’s update cycle. The solution is our ‘RefreshGamepads‘ script and a little bit of changing the project settings!

First, let’s use the Unity update function in the still blank ‘RefreshGamepads‘ script to tell the GamepadManager to refresh the gamepads. With all the singleton work we’ve done, it’s as simple as this:

// Normal unity update
void Update()
{
      GamepadManager.Instance.Refresh();
}

That’s our first look at the GamepadManager singleton in action, we didn’t need to make an instance, find the script or anything!

For the second and last step, we want the RefreshGamepads‘ Update to be called at the end of the update cycle and GamepadManager’s Update to be called at the start. Unity’s Script Execution Order menu will do this nicely! If you’re unfamiliar with this feature of Unity, it can be found under Edit > Project Settings > Script Execution Order.

manager_script_order

As the editor says, all scripts we don’t add to this custom order will execute at the default time, which is fine. You can drag the scripts to this inspector pane or click the plus (‘+’) to add them to the custom order. We want GamepadManager to run before Default Time and RefreshGamepads to run after. Those numbers represent the order the scripts will execute and usually default to 100. Feel free to experiment with the numbers if you like, this screenshot shows what I used. Be sure to save your project or these changes won’t be saved!

Part 4 Summary:

I decided to split the final part of this tutorial into two separate parts, this being the first. The GamepadManager is now set up and can manage 1 to 4 gamepads as needed. You can even change the GamepadCount variable in the editor, without needing to change any code! With the core functionality complete, next we will look at the remaining ‘Utility’ functionality for the GamepadManager.

Continue to: Part 5 – Gamepad Management – ‘Utility

Jump to:
Part 1 – Setting up
Part 2 – Button input
Part 3 – Rumble + Thumbstick and Trigger input

Xbox360 Gamepad Input & Management – Unity Tutorial (Part 3)

Legacy Tutorial – Please note: This tutorial was last tested in Unity 5.3.3f1 (x64 ‘Personal’ version). I am not currently using Unity as I use and develop my own engine technology. The code in this tutorial is all C# and calls to the XInputDotNetPlugin, it should port over to more recent versions of the engine just fine.

Welcome to Part 3 of my Xbox360 Gamepad Input tutorial for the Unity engine!

In this part we will finish coding the ‘x360_Gamepad’ class with the remaining input support it needs – rumble (vibration), thumbsticks and triggers. If you’re reading this and have not read Part 1 and Part 2, I suggest you read them first as this part builds on code developed in those stages of the tutorial.

Jump to:
Part 1 – Setting up
Part 2 – Button Input

The ‘xRumble’ class

// Rumble (vibration) event
class xRumble {
     public float timer;    // Rumble timer
     public float fadeTime; // Fade-out time (in seconds)
     public Vector2 power;  // Intensity of rumble
}

xRumble was added to the top of the ‘x360_Gamepad’ script back in Part 1, along with the rumbleEvents list. Now we’re going to use these to represent ‘rumble’ events on the gamepad and store them. Before we get started, the xRumble class needs a function to decrease its timer (you’ll see why soon).

Let’s add the ‘Update‘ function to the xRumble class.

// Rumble (vibration) event
class xRumble {
     public float timer;    // Rumble timer
     public float fadeTime; // Fade-out time (in seconds)
     public Vector2 power;  // Intensity of rumble

     // Decrease timer
     public void Update() {
           this.timer -= Time.deltaTime;
     }
}

With that done, next is the ‘HandleRumble‘ function. You may have guessed from its name, this function will update the rumble events and use XInputDotNet to vibrate the gamepad’s motors accordingly.

Get Ready to Rumble – The ‘HandleRumble’ function

Some uses for rumble include firing weapons (or being hit) in shooter games or crashing into barricades / other objects in racing games. Depending on what you want to use rumble for to provide feedback to the player, you may want to send several rumble events to the gamepad in quick succession or perhaps just a single rumble event.

Let’s add the ‘HandleRumble‘ function to the ‘x360_Gamepad’ script and start by making a loop to update the rumble events.

// Update and apply rumble events
void HandleRumble()
{
      // Ignore if there are no events
      if (rumbleEvents.Count > 0)
      {
            Vector2 power = new Vector2(0,0);

            for (int i = 0; i < rumbleEvents.Count; ++i)
            {
                  // Update current event
                  rumbleEvents[i].Update();
            }
      }
}

Fairly simple so far, we check if there are any rumble events to update and only then cycle through them, updating each one. Although, for now this just counts the event timers down to zero and nothing more. Time to fix that.

While a rumble event is active (its timer hasn’t reached zero), we want to calculate its current ‘power’ (intensity of the motor vibration) based on the following variables.

  • timer – the time left on the rumble event’s timer
  • fadeTime– the time the rumble should begin to fade out (in seconds)
  • power – intensity of the motor vibration (between 0.0f and 1.0f)

Why do this? By giving a ‘current power‘ value to XInputDotNet for vibration, we can start a rumble event at its full intensity and then gently fade it out (the vibration dies down) as its timer ticks down. Sounds neat doesn’t it? Let’s add the ‘current power‘ calculation to the ‘HandleRumble‘ function.

// Update and apply rumble events
void HandleRumble()
{
      // Ignore if there are no events
      if (rumbleEvents.Count > 0)
      {
            Vector2 currentPower = new Vector2(0,0);

            for (int i = 0; i  0)
                  {
                        // Calculate current power
                        float timeLeft = Mathf.Clamp(rumbleEvents[i].timer / rumbleEvents[i].fadeTime, 0f, 1f);
                        currentPower = new Vector2(Mathf.Max(rumbleEvents[i].power.x * timeLeft, currentPower.x),
                                                   Mathf.Max(rumbleEvents[i].power.y * timeLeft, currentPower.y));

                        // Apply vibration to gamepad motors
                        GamePad.SetVibration(playerIndex, currentPower.x, currentPower.y);
                  }
                  else
                  {
                        // Remove expired event
                        rumbleEvents.Remove(rumbleEvents[i]);
                  }
            }
      }
}

Now while the event is still active, we find how much time it has left and use that in calculating the current power value. Then we use XInputDotNet to apply the actual vibration to the gamepad’s motors, using currentPowerX for the left motor and Y for the right. Otherwise once the timer hits zero, the else kicks in and the expired rumble event is removed from the rumbleEvents list.

There’s one last thing we need to do regarding updating / handling rumble….we need to call the ‘HandleRumble‘ function for it to be of any use, of course. Let’s revisit the ‘Update‘ function and call the ‘HandleRumble‘ function at the end of it.

// Update gamepad state
public void Update()
{
      // Get current state
      state = GamePad.GetState(playerIndex);

      if (state.IsConnected)
      {
            // state code from Part 1 omitted...
            UpdateInputMap(); // Update inputMap dictionary
            HandleRumble();   // Update rumble event(s)
      {
}

Creating Rumble Events

Well, we now have a neat rumble feature but we need to add data to the rumbleEvents list for it to work. The ‘AddRumble‘ function is the last rumble-related feature we will add to complete the rumble support. Let’s add this function to the ‘x360_Gamepad’ script, below the ‘HandleRumble‘ function.

// Add a rumble event to the gamepad
public void AddRumble(float timer, Vector2 power, float fadeTime)
{
      xRumble rumble = new xRumble();

      rumble.timer = timer;
      rumble.power = power;
      rumble.fadeTime = fadeTime;

      rumbleEvents.Add(rumble);
}

The same three variables of the xRumble class are used as parameters, allowing us to specify the timer, intensity (power) and fade duration of the event for a variety of possible rumble effects. These are assigned to the rumble variable, which is then added to the rumbleEvents list – ready to be used by the ‘HandleRumble‘ function!

Thumbsticks

After adding the rumble support, the thumbstick code is quite simple in comparison. Just below the rumble functions, let’s add two new functions to get the axis values from each stick.

// Return axes of left thumbstick
public GamePadThumbSticks.StickValue GetStick_L() {
      return state.Thumbsticks.Left;
}

// Return axes of right thumbstick
public GamePadThumbSticks.StickValue GetStick_R() {
      return state.Thumbsticks.Right;
}

Yes, that’s all there is to it! XInputDotNet stores the thumbstick data in the gamepad state, so we just access the sticks from our state variable. They are stored as the StickValue type, which is why we use that as the return type for the thumbstick functions.

You may be curious how we get the individual X or Y axis out of these? Well similar to the Vector2 math class, StickValue contains its own X and Y values! We can easily access these like so.

// Assuming 'myGamepad' instance was created...
float leftStick_X = myGamepad.GetStick_L().X;
float leftStick_Y = myGamepad.GetStick_L().Y;

Triggers

Last, but not least, we have the triggers. Once again, there is little code we need to write to access the trigger values. Just below the thumbstick functions, let’s add two new functions to get the value of each trigger.

// Return axis of left trigger
public float GetTrigger_L() { return state.Triggers.Left; }

// Return axis of right trigger
public float GetTrigger_R() { return state.Triggers.Right; }

Wow, only one line each this time! Just like the thumbsticks, we access the trigger values through our state variable as they are stored in the gamepad state. This time though, the trigger values are returned directly (thumbstick axes were stored in StickValue, which was the return type), so we use float as the return type.

The trigger values range from 0.0f (not pressed at all)  to 1.0f (held down), giving the option of using these trigger functions to only perform an action for example, when the trigger value is past a certain threshold (such as 0.5f for a half-press). One possibility for this would be to cancel out accidental taps, if the player bumped the trigger but didn’t mean to press it.

Trigger Tap:

Having the trigger support is great, what if you wanted to check for just a tap of a trigger though (same as GetButtonDown on current frame in Part 2)? It could be very useful for doing an action only once per tap such as firing a single projectile, or firing a burst of projectiles for example.

We have already done most of the work for this in Part 1, let’s add the trigger ‘tap’ functions below the trigger functions we just added.

// Check if left trigger was tapped - on CURRENT frame
public bool GetTriggerTap_L() {
      return (LT.prev_value == 0f && LT.current_value >= 0.1f) ? true : false;
}

// Check if right trigger was tapped - on CURRENT frame
public bool GetTriggerTap_R() {
      return (RT.prev_value == 0f && RT.current_value >= 0.1f) ? true : false;
}

Remembering back to Part 1, LT and RT were the trigger states we added to the ‘x360_Gamepad’ class. Their prev_value and current_value are set during the ‘Update‘ and ‘Refresh‘ functions respectively. So all we do here is see if prev_value is zero (not pressed last update) and if current_value is greater than 0.1f (pressed current update), then we have a trigger ‘tap’ and the function returns true. This applies to both the left and right triggers.

Part 3 Summary:

We’re nearly there! The ‘x360_Gamepad’ script is finished and has support for all inputs on the Xbox 360 gamepad – including rumble! Next, we move onto the ‘management’ side of the tutorial (it’s part of the title after all), creating a system that exists throughout multiple scenes in Unity and stores up to four gamepad instances.

Code from Part 1-3: Download (7.4 KB)

Continue to: Part 4 – Gamepad Management – ‘Core

Jump to:
Part 1 – Setting up
Part 2 – Button input

Xbox360 Gamepad Input & Management – Unity Tutorial (Part 2)

Legacy Tutorial – please note: This tutorial was last tested in Unity 5.3.3f1 (x64 ‘Personal version). I am not currently using Unity as I use and develop my own engine technology. The code in this tutorial is all C# and calls to the XInputDotNet plugin, it should port over to more recent versions of the engine just fine.

Welcome to Part 2 of my Xbox360 Gamepad Input tutorial for the Unity engine!

Before we get started, I apologize for any inconveniences caused by the 2 month gap between Parts 1 and 2 of this tutorial. I had been kept busy with study and exams for a course.

If you’re reading this part and have not read Part 1, I suggest reading Part 1 first.

Introducing the Button Map:

A key feature of this custom input is the ‘button map’, which we’ll be using to read button states from the gamepad (such as the ‘A’ button or the directional pad). What is this button map exactly? To start, we’re going to use a Dictionary (similar to a std::map in C++).

In Part 1, we had already added the button map to the gamepad class. Let’s take another look at it now – it’s just before the button state variables at the top of the class.

private Dictionary inputMap;

If you haven’t used dictionaries, maps or similar containers before – don’t worry! Simply put, they store pairs of types (int, char, enum, string, even custom objects). In our case, our inputMap dictionary stores pairs containing a string for an ID and a button state. As of now, we don’t have any buttons mapped to IDs in inputMap. Time to fix that.

Updating the Button Map:

Since our button states are most likely going to change each update as the gamepad is used (eg. some are pressed, held or released), our inputMap dictionary needs to be updated each update too – ensuring each string ID is mapped to its matching state, keeping the mapping ‘current’ if you like.

To make sense of this and save on retyping code later on, we’ll use a function to update the inputMap.

// Update input map
void UpdateInputMap()
{
      inputMap["A"] = A;
      inputMap["B"] = B;
      inputMap["X"] = X;
      inputMap["Y"] = Y;

      inputMap["DPad_Up"]    = DPad_Up;
      inputMap["DPad_Down"]  = DPad_Down;
      inputMap["DPad_Left"]  = DPad_Left;
      inputMap["DPad_Right"] = DPad_Right;

      inputMap["Guide"] = Guide;
      inputMap["Back"]  = Back;
      inputMap["Start"] = Start;

      // Thumbstick buttons
      inputMap["L3"] = L3;
      inputMap["R3"] = R3;

      // Shoulder ('bumper') buttons
      inputMap["LB"] = LB;
      inputMap["RB"] = RB;
}

This function indexes the inputMap dictionary for each button (“A”, “B”, “Start”, etc) using the first type in the pair, the string ID, to return an XButton state – the second type in the pair. Then that inputMap state is assigned to its matching state from the gamepad class.

Update and Refresh functions revisited:

There’s one last thing we need to do to finish updating the inputMap, we need to actually call the UpdateInputMap function. In Part 1, we had written two functions – Update, to update gamepad states on the current frame and Refresh, to save the current states for the next update. The UpdateInputMap function must be called at the end of both, otherwise the inputMap won’t have the most recent button states – causing problems later on for the button input check functions.

// Update gamepad state
public void Update()
{
      // Get current state
      state = GamePad.GetState(playerIndex);

      if (state.IsConnected)
      {
            // state code omitted...
            UpdateInputMap(); // Update inputMap dictionary
      }
}

// Refresh previous gamepad state
public void Refresh()
{
      // Save current state for next update
      prev_state = state;

      if (state.IsConnected)
      {
            // prev_state code omitted...
            UpdateInputMap(); // Update inputMap dictionary
      }
}

Button Input:

Now we can add some functions to the gamepad class to check if a certain button is being pressed or if it’s being pressed only on the current frame. Guess what? So far in this part, we’ve actually done most of the button input code already with the inputMap dictionary. All that we need to do is put it to use!

Let’s add the ‘GetButton‘ function to the gamepad class, just below the ‘Update‘ and ‘Refresh‘ functions.

// Return button state
public bool GetButton(string button)
{
      return inputMap[button].state
            == ButtonState.Pressed ? true : false;
}

GetButton‘ takes a string as a parameter, using it to index, you guessed it, the inputMap dictionary. Should the returned button state be ‘Pressed’, the function returns true indicating the button is pressed. Otherwise the function returns false, the button is not pressed.

Below that, the ‘GetButtonDown‘ function. This is slightly more complex than the ‘GetButton‘ function, as it checks both the PREVIOUS and CURRENT states.

// Return button state - on CURRENT frame
public bool GetButtonDown(string button)
{
      return (inputMap[button].prev_state == ButtonState.Released &&
              inputMap[button].state == ButtonState.Pressed) ? true : false;
}

Unlike the ‘GetButton‘ function, ‘GetButtonDown‘ will ONLY return true once – on the frame (or ‘update’ if you like) the button was pressed. I find this very useful for features such as menus or in-game actions that require a single button press / tap.

Part 2 Summary:

The gamepad class now has a button mapping which is automatically updated as the gamepad is updated or refreshed. Using this, we can now pass button strings (like “A” or “DPad_Left”) to the new button input check functions – neat! Now that we have button input added, it’s time to finish up the gamepad class. Next we will add support for the thumbsticks, triggers and rumble feedback!

Continue to: Part 3 – Rumble + Thumbstick and Trigger input

Return to Tutorials

Xbox360 Gamepad Input & Management – Unity Tutorial (Part 1)

Legacy Tutorial – Please note: This tutorial was last tested in Unity 5.3.3f1 (x64 ‘Personal’ version). I am not currently using Unity as I use and develop my own engine technology. The code in this tutorial is all C# and calls to the XInputDotNet plugin, it should port over to more recent versions of the engine just fine.

At a glance: What we’ll be learning

From my experience using Unity, it’s a great engine and I’ve been enjoying the 2D features and the new UI system added in recent versions (at the time of writing). However, I prefer a more custom solution to the out-of-the-box support for gamepads it provides. Of course, some developers may be satisfied with using the InputManager to set up axes on multiple controllers and that’s totally fine.

You’re here because you want to roll your own, fully custom input system for Xbox 360 controllers in C# that will work in your Unity project, right? I did, which inspired me to write this tutorial. Not only will this tutorial cover gamepad input, we will also write our own ‘Gamepad Manager’ to manage up to four connected controllers.

Introducing the XInputDotNet plugin:

XInputDotNet is a C# wrapper of the DirectX ‘XInput’ API, made by Remi Gellig. It’s designed to work with .NET applications (this includes Unity), so we will be using this plugin to get our gamepad input, rather than Unity’s offerings of “GetAxis” / “GetButtonDown” functions and joystick input via its InputManager.

Setting up – Unity project and XInputDotNet:

First, let’s download the latest version of XInputDotNet. On the Releases page on the github repository, the latest version can be found at the top (github even marks it as ‘Latest release’, for those new to using it).

Note: As of Unity 5, the engine has moved to 64-bit. This means any libraries we want to use with it also need to be in 64-bit, choose the x64 download of XInputDotNet.

Before we get to the zip file (or Unity package, if you went with that), we need a Unity project to use for this tutorial. You may already have a project you’d like to use, otherwise make a new Unity project. For the purpose of this tutorial, I’m calling it ‘XInput_Test’, use a different project name if you like.

unity_xinput_tut_step1

Let’s start by adding some folders and saving the scene. Here (above screenshot), I’ve called my blank scene ‘TestScene‘ and created two folders – ‘Plugins’ for the DLL files and ‘Scripts’ for the C# files. Now unzip the XInputDotNet zip file and extract the ‘XInputDotNetPure’ and ‘XInputDotNetInterface’ DLL files to another location such as your desktop or documents folder. From there, getting them into the Unity project is pretty easy! Simply click and drag the files from the desktop (or the location you extracted them to) over the ‘Plugins’ folder in the Project View (above screenshot). Unity will import the files and the Project View should now look similar to the next screenshot.

unity_xinput_tut_step2

Finally, the XInputDotNetInterface DLL MUST also be in the root folder of the project. Copy this DLL from the ‘Plugins’ folder into the root folder. Without it, the Editor will be unable to load XInputDotNet! See the below screenshot for root folder example.

unity_xinput_tut_step4

And that’s it! The DLL files are in the project and we can now use XInputDotNetPure in our gamepad code. However, before we can start writing gamepad code, we need a new C# script. Right-click the ‘Scripts’ folder and click ‘Create new C# script’. I named the script ‘x360_Gamepad’, but ‘Gamepad’ or ‘Controller’ are also good names for it. With this script added, we’ve finished setting up our Unity project and the Project View should now look similar to the below screenshot.

unity_xinput_tut_step3

‘x360_Gamepad’ script – Basic layout:

In our gamepad class, we’ll be using two structs and another class to represent button, trigger and rumble (vibration) events. Let’s begin by adding these and the ‘using’ command to include the functionality we need from XInputDotNetPure to the script.

using UnityEngine;
using XInputDotNetPure;
using System.Collections.Generic;

// Stores states of a single gamepad button
public struct xButton {
      public ButtonState prev_state;
      public ButtonState state;
}

// Stores state of a single gamepad trigger
public struct TriggerState {
      public float prev_value;
      public float current_value;
}

// Rumble (vibration) event
class xRumble {
     public float timer;    // Rumble timer
     public float duration; // Fade-out (in seconds)
     public Vector2 power;  // Intensity of rumble
}

With these structs and class in place, we can now create the gamepad class and add all the member variables and the constructor to it. Notice how we make use of the structs and class we just added.

// Above code omitted....

public class x360_Gamepad
{
      private GamePadState prev_state; // Previous gamepad state
      private GamePadState state;      // Current gamepad state

      private int gamepadIndex;        // Numeric index (1,2,3 or 4
      private PlayerIndex playerIndex;    // XInput 'Player' index
      private List rumbleEvents; // Stores rumble events

      // Button input map (explained soon!)
      private Dictionary inputMap;

      // States for all buttons/inputs supported
      private xButton A,B,X,Y; // Action (face) buttons
      private xButton DPad_Up, DPad_Down, DPad_Left, DPad_Right;

      private xButton Guide;       // Xbox logo button}
      private xButton Back, Start;
      private xButton L3, R3;      // Thumbstick buttons
      private xButton LB, RB;      // 'Bumper' (shoulder) buttons
      private TriggerState LT, RT; // Triggers

      // Constructor
      public x360_Gamepad(int index)
      {
            // Set gamepad index
            gamepadIndex = index - 1;
            playerIndex = (PlayerIndex)gamepadIndex;

            // Create rumble container and input map
            rumbleEvents = new List();
            inputMap = new Dictionary();
      }
}

We’ll be using prev_state and state to read input from the gamepad, storing it into our xButton and TriggerState variables for use in input checking functions later.

The constructor takes an index as a parameter, allowing us to give the controller an ID if you like, from 1 to 4. I subtract 1 from the given index here because XInput treats its gamepad numbers in the 0-3 range (0 being 1 and 3 being 4, if that’s confusing) and I prefer the 1-4 range in this case. Doing so means you can tell the gamepad to be ‘controller number 1’ that you know is controller 1 and XInput is kept happy by using its 0-3 range.

Gamepad States – Reading Input:

The first of two gamepad states we’ll use, state, is used to read input on the current update. Let’s create the Update function to read this input.

// Constructor...

// Update gamepad state
public void Update()
{
      // Get current state
      state = GamePad.GetState(playerIndex);

      // Check gamepad is connected
      if (state.IsConnected)
      {
            A.state = state.Buttons.A;
            B.state = state.Buttons.B;
            X.state = state.Buttons.X;
            Y.state = state.Buttons.Y;

            DPad_Up.state    = state.DPad.Up;
            DPad_Down.state  = state.DPad.Down;
            DPad_Left.state  = state.DPad.Left;
            DPad_Right.state = state.DPad.Right;

            Guide.state = state.Buttons.Guide;
            Back.state  = state.Buttons.Back;
            Start.state = state.Buttons.Start;
            L3.state    = state.Buttons.LeftStick;
            R3.state    = state.Buttons.RightStick;
            LB.state    = state.Buttons.LeftShoulder;
            RB.state    = state.Buttons.RightShoulder;

            // Read trigger values into trigger states
            LT.current_value = state.Triggers.Left;
            RT.current_value = state.Triggers.Right;
      }
}

I found I didn’t need to be storing all these input states on a disconnected controller, which is why I use the if statement to skip reading the states if the controller is disconnected. Otherwise, reading the input values into our states is straightforward.

prev_state on the other hand, is used to read input values from state…ideally at the end of the current Unity update (covered in a later part of the tutorial). This effectively ‘saves‘ the input values on the current update for use during the next update, hence the name prev_state. Next, we’ll add the Refresh function to update prev_state.

// Above code omitted...
// 'Update' function...

// Refresh previous gamepad state
public void Refresh()
{
      // This 'saves' the current state for next update
      prev_state = state;

      // Check gamepad is connected
      if (state.IsConnected)
      {
            A.prev_state = prev_state.Buttons.A;
            B.prev_state = prev_state.Buttons.B;
            X.prev_state = prev_state.Buttons.X;
            Y.prev_state = prev_state.Buttons.Y;

            DPad_Up.prev_state    = prev_state.DPad.Up;
            DPad_Down.prev_state  = prev_state.DPad.Down;
            DPad_Left.prev_state  = prev_state.DPad.Left;
            DPad_Right.prev_state = prev_state.DPad.Right;

            Guide.prev_state = prev_state.Buttons.Guide;
            Back.prev_state  = prev_state.Buttons.Back;
            Start.prev_state = prev_state.Buttons.Start;
            L3.prev_state    = prev_state.Buttons.LeftStick;
            R3.prev_state    = prev_state.Buttons.RightStick;
            LB.prev_state    = prev_state.Buttons.LeftShoulder;
            RB.prev_state    = prev_state.Buttons.RightShoulder;

            // Read previous trigger values into trigger states
            LT.prev_value = prev_state.Triggers.Left;
            RT.prev_value = prev_state.Triggers.Right;
      }
}

Other than using prev_state, the Refresh function is nearly identical to the Update function. Although not covered in this part, we will later use these two functions to achieve frame-specific input (eg. checking ‘A’ button press on current frame only)!

External access – ‘utility’ functions:

To finish up part one, let’s add some ‘get’ statements to allow other scripts to access some private variables, namely the gamepad’s connection state and index.

// Above code omitted...
// 'Refresh' function...

// Return numeric gamepad index
public int Index { get { return gamepadIndex; } }

// Return gamepad connection state
public bool IsConnected { get { return state.IsConnected; } }

That’s it! Index will return the gamepad’s number (eg. 3), while IsConnected can prove very handy if you want to run specific code should the gamepad disconnect (like a player leaving a match or showing a message to indicate a disconnected controller, for example).

Part 1 Summary:

We’ve reached the end of part 1. So far we have our gamepad class set up and are able to update our gamepad states (that’s state AND prev_state) and read input into our own variables in the class. Next, we’ll look at the input map – what it is, what it does and how it makes writing our button input functions much easier!

Continue to: Part 2 – Button input

Return to Tutorials

Back to School and New tech

Greetings!

Since my last blog update (found here), I have made the best decision I believe I could have made regarding my skill set for employment. I have once again become a full-time student, studying a Certificate IV in Information Technology at a local vocational education provider (or ‘TAFE’).

Why did I return to full-time study? For a few reasons actually. Here’s a brief overview:

  1. New skills, experience and knowledge to better equip me for a broader range of employment opportunities. Specifically, this qualification is in Infrastructure Support – so databases (SQL / Oracle) and networking (installation, admin, servers, etc) are just two examples of the new skills I’ll get out of it.
  2. Since graduating from AIE last December, many friends had suggested I pick up a new course to expand my horizons (and skill set).
  3. Took me a while to admit it, however only having a qualification in video game programming (as cool as that is and I don’t regret it) on my resume’ most likely led to many of my applications being turned down / ignored.

I start this coming week (from date of this update) and the course runs for 2 semesters, so until maybe a bit past halfway through next year. I’m pretty keen to get started and meet new people.

Regarding new tech, in spare time I have been re-developing my 2D engine. Optimization-wise, I have re-designed how systems such as the renderer deal with objects on the C++ side of things. Now with SDL 2 at its core (very fiddly and annoying to get working with only OpenGL for rendering, the fix ended up being simple though), the engine has quite a few new features which weren’t possible using the now out-of-date, SDL 1.2.

I recently decided to teach myself the API of FMOD by Firelight Technologies. For those unfamiliar, FMOD (considered an industry-standard) is an audio engine which has been used in many AAA video games and supports all major platforms and audio formats. Over the last week, I have been implementing it for my engine’s audio system.

GLSL Shader system – Tutorial (Part 2)

Welcome to part 2 of my GLSL Shader system tutorial!

In this part of the tutorial, we will complete the ‘Shader’ class we started in part 1. Because of this, if you are reading this part and have not yet read part 1, I suggest going back to read part 1 first. Click here to return to Part 1.

GLSL Uniforms:

A ‘uniform‘ is a global variable in GLSL and acts as a parameter that we can pass into the shader program from C++. Similar to ‘const‘ in C++, the uniform gets its name because it doesn’t change in a single rendering call from one execution of the shader program to the next.

Use of uniforms comes down to what you want a shader program to do. For example in 3D geometry rendering, a vertex shader may take in a series of matrices (eg. projection, view, model) as uniforms- using them to calculate vertex positions of a mesh. On the other hand, in 2D you may want to do a screen effect like a black and white tone, in which case a fragment shader may take in a texture handle as a uniform or even no uniforms at all.

Binding C++ types to GLSL Uniforms:

Now that we’ve looked at what GLSL uniforms are and what we can do with them, we need some new methods in our ‘Shader‘ class to send C++ types such as int and float into a GLSL program so it can use them.

Let’s add these new ‘Bind’ function prototypes to the ‘Shader’ class:

#ifndef SHADER_H
#define SHADER_H

// GLSL Shader class
class Shader
{
public:

      // Member variables
      //------------------//

      int m_Program;    // Shader program handle
      int m_FragShader; // Fragment shader handle

      // Function prototypes
      //---------------------//

      // Default constructor
      Shader();

      // Overloaded constructor (loads the shader)
      Shader(const char* a_Filepath);

      // Bind an integer value to a GLSL uniform
      void BindUniform_int(const char* a_UniformName, int a_iValue);

      // Bind a float value to a GLSL uniform
      void BindUniform_float(const char* a_UniformName, float a_fValue);
};

#endif // SHADER_H

Each ‘Bind‘ function takes two parameters – the name of the GLSL uniform we want to bind to and the value we want to bind to the uniform. Add these functions below the overloaded constructor in the source (‘Shader.cpp‘) file:

#include "Shader.h"

// Include GLEW header file
#include "YourPath/glew.h"

#include <fstream>
#include <iostream>
#include <vector>

using namespace std;

// Default constructor
Shader::Shader() {}

// Overloaded constructor (loads the shader)
// --- Code from Part 1

// Bind an integer value to a GLSL uniform
void Shader::BindUniform_int(const char* a_UniformName, int a_iValue)
{
      // Get uniform ID
      GLuint UniformID = glGetUniformLocation(m_FragShader, a_UniformName);

      // Bind value to uniform
      glUniform1i(UniformID, a_iValue);
}

// Bind a float value to a GLSL uniform
void Shader::BindUniform_float(const char* a_UniformName, float a_fValue)
{
      // Get uniform ID
      GLuint UniformID = glGetUniformLocation(m_FragShader, a_UniformName);

      // Bind value to uniform
      glUniform1f(UniformID, a_fValue);
}

Both bind functions are a simple two-step process. First, we get the uniform ID (or ‘location’) using the fragment shader handle and the specified uniform name. Then, using the uniform ID, we bind the specified value using the respective ‘glUniform‘ function.

Using the Shader:

So, with our ‘Shader‘ class we can load a GLSL program and even bind int and float variables from C++ into it….but how do we actually use it to make it do something cool?

You may be surprised, but the GLEW library provides functions to make using GLSL shaders very simple. We will need two new functions, one to use (or ‘apply’) our shader to see its effect and the other, to stop the effect and return to normal rendering.

Let’s add these new function prototypes to the ‘Shader‘ class, below the overloaded constructor:

#ifndef SHADER_H
#define SHADER_H

// GLSL Shader class
class Shader
{
public:

      // Member variables
      //------------------//

      int m_Program;    // Shader program handle
      int m_FragShader; // Fragment shader handle

      // Function prototypes
      //---------------------//

      // Default constructor
      Shader();

      // Overloaded constructor (loads the shader)
      Shader(const char* a_Filepath);

      void Begin(); // Activate (use) shader
      void End();   // Return to normal rendering

      // Bind an integer value to a GLSL uniform
      void BindUniform_int(const char* a_UniformName, int a_iValue);

      // Bind a float value to a GLSL uniform
      void BindUniform_float(const char* a_UniformName, float a_fValue);
};

#endif // SHADER_H

As their names suggest, the ‘Begin‘ function will activate the shader program and the ‘End‘ function will simply cancel it, returning to normal rendering. Now, let’s see how simple these tasks are as I mentioned before.

Add these functions between the overloaded constructor and the ‘Bind‘ functions in the source (‘Shader.cpp‘) file:

// Activate (use) the shader
void Shader::Begin()
{
      glUseProgram(m_Program);
}

// Return to normal rendering
void Shader::End()
{
      glUseProgram(0);
}

Yes, that’s all there is to it! Passing zero to the ‘glUseProgram‘ function simply tells GLEW that we don’t want to use any shader.

Unloading the Shader:

As always in C++, we must clean up after ourselves. Fortunately, GLEW has functions to delete shader handles for us, so we’ll make use of these functions.

Let’s add a destructor to our ‘Shader‘ class. Yes, it does mean we will use the class as an object pointer but the plus side is we can use the destructor to automatically delete the shader handles when we delete the pointer.

Add the class destructor below the overloaded constructor, completing our ‘Shader‘ class:

#ifndef SHADER_H
#define SHADER_H

// GLSL Shader class
class Shader
{
public:

      // Member variables
      //------------------//

      int m_Program;    // Shader program handle
      int m_FragShader; // Fragment shader handle

      // Function prototypes
      //---------------------//

      // Default constructor
      Shader();

      // Overloaded constructor (loads the shader)
      Shader(const char* a_Filepath);

      // Destructor (unloads the shader)
      ~Shader();

      void Begin(); // Activate (use) shader
      void End();   // Return to normal rendering

      // Bind an integer value to a GLSL uniform
      void BindUniform_int(const char* a_UniformName, int a_iValue);

      // Bind a float value to a GLSL uniform
      void BindUniform_float(const char* a_UniformName, float a_fValue);
};

#endif // SHADER_H

Finally, add the destructor below the overloaded constructor in the source (‘Shader.cpp‘) file:

#include "Shader.h"

// Include GLEW header file
#include "YourPath/glew.h"

#include <fstream>
#include <iostream>
#include <vector>

using namespace std;

// Default constructor
Shader::Shader() {}

// Overloaded constructor (loads the shader)
// --- Code from Part 1

// Destructor (unloads the shader)
Shader::~Shader()
{
      // Delete shader program
      glDeleteProgram(m_Program);

      // Delete fragment shader
      glDeleteShader(m_FragShader);
}

// Bind an integer value to a GLSL uniform
// --- Code from earlier in this part

// Bind a float value to a GLSL uniform
// --- Code from earlier in this part

An Example – Tying it all together:

Now that we’ve completed our ‘Shader‘ class, let’s look at an example of using it!

#include "Shader.h"

// The shader we'll use
Shader* pMyShader;

// Initialize function (called before game loop)
void Initialize()
{
      // Create (load) the shader
      pMyShader = new Shader("YourPath/YourShader.frag");
}

// Render function (called every frame, in game loop)
void Draw()
{
      // Refresh renderer (eg. clear OpenGL buffers)

      // Apply effect!
      pMyShader->Begin();

      // Draw a texture (or several textures)...

      // Return to normal rendering
      pMyShader->End();

      // eg. Draw HUD...
}

// Unload function (called after game loop breaks)
void Unload()
{
      // Auto deletes the shader handles!
      delete pMyShader;
}

And that’s it! We create the shader before the game loop, during the game loop (rendering) we simply activate the shader with the ‘Begin‘ function, draw anything we want to be affected by its effect and then return to normal rendering with the ‘End‘ function. After the ‘End‘ function is called, you could do additional rendering (eg. HUD) that would appear normally without the effect.

Finally, while unloading after the game loop breaks, we simply delete the pointer we created for the shader earlier – automatically deleting the shader handles!

Part 2 conclusion:

With your own, complete GLSL shader system you can now go wild with writing and playing around with visual effects for your game(s)! You may even want to add this to your own game engine, like what I did. From a quick search in your chosen search engine, you can find many (and free) code examples of various shaders in GLSL if you’re stuck writing your own. A fellow programmer and friend of mine makes some pretty amazing GLSL shaders, you can check out her work at http://castleellen.blogspot.com.au/!

If this tutorial has been helpful, I truly appreciate any thanks or feedback if you think it can be improved. You could share a link to this tutorial on another site, follow this blog or list this blog for thanks/special thanks in the credits of your game – any of these would be greatly appreciated!

Click here to return to Part 1.

GLSL Shader system – Tutorial (Part 1)

Welcome to part 1 of my GLSL Shader system tutorial!

In this tutorial, we will write our own shader class. The main features of this class will be loading a shader file into handles for use in C++, and of course, applying the program to get a visual effect!

Shaders from a 2D perspective:

In 3D graphics (eg. programmable rendering pipline), shaders are used for a variety of things – geometry rendering, materials, particle effects, UI, etc. From a 2D perspective and based on what 2D engine / rendering engine you’re using, a fixed rendering pipeline is likely being used (all rendering done without shaders)….so, what can we use shaders for in this case?

The answer is many pretty cool visual effects! You’ve likely played at least one game where you were able to unlock ‘Render modes’, which you could turn on to turn the entire game world black and white, or perhaps a sepia (old time-y) tone. These two effects are actually what inspired me to make a shader system for my engine!

Tutorial requirements:

We will be using OpenGL and the GLEW (OpenGL Extension Wrangler) library throughout the tutorial. Prior to writing any code in this tutorial, I recommend the following:

  • Use of your own (or 3rd-party) 2D game engine / framework, that uses OpenGL
  • Ensure you have an OpenGL context being created

Should you or your 3rd-party engine / framework be using SDL (or similar API), chances are it will create the GL context in the background for you without you needing to do it yourself.

I will mention terms such as ‘open window’, ‘initialize engine’ and ‘game loop’ in pseudocode during the tutorial. I will NOT be covering actual code on any of this functionality.

‘Shader’ class – Initial layout:

#ifndef SHADER_H
#define SHADER_H

// GLSL Shader class
class Shader
{
public:

      // Member variables
      //------------------//

      int m_Program;    // Shader program handle
      int m_FragShader; // Fragment shader handle

      // Function prototypes
      //---------------------//

      // Default constructor
      Shader();

      // Overloaded constructor (loads the shader)
      Shader(const char* a_Filepath);
};

#endif // SHADER_H

Simple so far, right? We’ve got two handles, one for the program as a whole and the other for the specific fragment (or ‘pixel’) shader we load from file. There is no ‘Load’ function, because we’re going to have the overloaded constructor do the loading and creating of the shader instead. This will make things simpler later on in the tutorial, you’ll see why when we get there.

Initializing GLEW:

Already have GLEW initialized? Skip ahead. Thought I’d cover this just in case. I tend to usually have a source (‘.cpp’) file called ‘main‘ (‘application‘ works too) where I have my engine initialize, game loop and unload code. I used an integer function called ‘main‘ for this example.


// Include GLEW header file
#include "YourPath/glew.h"

// 'Main' function
int main()
{
    // Initialize engine (open window)

    // Initialize GLEW library
    if (glewInit() != GLEW_OK)
    {
          // GLEW failed to initialize
          return 0;
    }

    // Game loop
    do
    {
       // Update
       // Render
    }
    while (EngineUpdate());

    // Unload content
    // Shutdown engine

    return 0;
}

Note that the above example is a rough and crude layout of a possible ‘main game loop’ file. Your / your engine’s implementation may be different. Now that GLEW has been initialized, we can use it in our shader loading code!

‘Shader’ class – Loading and creating a GLSL program from file:


#include "Shader.h"

// Include GLEW header file
#include "YourPath/glew.h"

#include <fstream>
#include <iostream>
#include <vector>

using namespace std;

// Default constructor
Shader::Shader() {}

// Overloaded constructor (loads the shader)
Shader::Shader(const char* a_Filepath)
{
      // Create a handle for the shader
      GLuint ShaderHandle = glCreateShader(GL_FRAGMENT_SHADER);

      vector<string> vFile; // Lines of the file being read
      string sCurrentLine;  // Current line being read

      // Open the program file for reading
      fstream ProgramFile(a_Filepath, ios::in);

      if (!ProgramFile.is_open())
      {
            // The file didn't open
            cout << " Error: Failed to open '" << a_Filepath << "' shader!" << endl;
            return;
      }

      // Iterate through lines of the program file
      // until end is reached
      for (int i = 0; !ProgramFile.eof(); ++i)
      {
            // Obtain the line
            getline(ProgramFile, sCurrentLine);

            // Add it to the 'vFile' container
            vFile.push_back(sCurrentLine);
      }

      // Close program file, we don't need it anymore
      ProgramFile.close();

      // Add the following blocks of code as they are shown in the
      // tutorial here...
}

For now, we have created the handle for our fragment shader and opened the shader file using the specified filepath. After checking if the file didn’t open, we simply loop through the lines of the file – grabbing each one and adding it to our ‘File‘ container, which we will use shortly. Finally, we close the file because we’ve got what we need from it.

Error checking is a wise addition and here we’re using it to print a warning message to the console should the shader file not open. You may not be using a console window or perhaps you don’t want to check for errors. Although I would recommend error checking in this case, adding it or not is entirely up to you.

Add this block of code to the end of the overloaded constructor:


      // --- Above code

      // File source array
      char** FileSource = new char*[vFile.size()];

      // Iterate through 'vFile' container
      for (int i = 0; i < int(vFile.size()); ++i)
      {
            // Copy file line into source array
            FileSource[i] = new char[vFile[i].size()];
            memcpy(FileSource[i], vFile[i].c_str(), vFile[i].size() + 1);
      }

We need an array containing file source, to be used to compile our shader. Once again, we loop through the lines of our ‘File‘ container – copying each one into the ‘FileSource‘ array using the ‘memcpy‘ function. Now with the file source array, we can finally use GLEW to compile the shader!

Add this block of code to the end of the overloaded constructor:

// --- Above code

// Compile the shader (program)
glShaderSource(ShaderHandle, vFile.size(), (const GLchar**)FileSource, NULL);
glCompileShader(ShaderHandle);

// Optional error checking
//-------------------------//

int Compiled; // Compile flag
glGetShaderiv(ShaderHandle, GL_COMPILE_STATUS, &Compiled);

if (!Compiled)
{
      // Shader didn't compile      

      // Get length of GL info log
      int iLength;
      glGetShaderiv(ShaderHandle, GL_INFO_LOG_LENGTH, &iLength);

      // Get log as a string
      string sLog(iLength, ' ');
      glGetShaderInfoLog(ShaderHandle, iLength, &iLength, &sLog[0]);

      // Print log to console window
      cout << sLog.c_str() << endl;

      // Throw logic error and return
      throw logic_error(sLog);
      m_FragShader = 0;

      return;
}

The key step we do here is compiling our shader program. All other code (as the comment suggests) is optional should you wish to add error checking. This time, we check if the shader didn’t compile – if so, we obtain the GL shader log describing the error, print that to the console window and finish up by using the log to throw a logic error. As before, I would recommend the error checking but it’s your call.

Add this block of code to the end of the overloaded constructor:

// --- Above code

// Create the shader program and attach fragment shader
m_Program = glCreateProgram();
glAttachShader(m_Program, ShaderHandle);
glLinkProgram(m_Program);

// Set fragment shader handle
m_FragShader = ShaderHandle;

// Iterate through 'vFile' container
for (int i = 0; i < int(vFile.size()); ++i)
{
      // Delete memory of line from file source array
      delete[] FileSource[i];
}

// Delete file source array memory
delete FileSource;

return;

Finally, we create the handle for our ‘Shader‘ class, attach the ‘ShaderHandle‘ handle (containing our fragment shader) and link it together. The ‘ShaderHandle‘ handle is then assigned to the ‘m_FragmentShader‘ handle of the ‘Shader‘ class (so we may use it elsewhere in the class).

Since we’re using C++, it is very important that we remember to clean up after ourselves by deleting the memory we allocated earlier.

Part 1 conclusion:

We have a ‘Shader‘ class which will represent a single GLSL program in your game (or engine / project). So far, we can pass a filepath of a GLSL shader into the overloaded constructor and it will create / compile the shader source into the handles of the class.

In Part 2, we will add new functionality to the ‘Shader‘ class to allow us to bind C++ types (such as int and float) to the GLSL ‘uniform’ types inside a GLSL shader program.

Click here to continue to Part 2.

2D Frustum Culling – Tutorial (Part 2)

Hello and welcome to part 2 of my tutorial on 2D Frustum Culling.

Before we go any further with the tutorial, if you’re reading this and have not yet read part 1, it is definitely worth your while to go back and read it. It lays the foundations that we need before we can write our 2D Camera class, which will contain the frustum and frustum checking code.

Return to Part 1

If you’ve read part 1 and have either implemented its Vector2 and BoxCollider code or are using your own (or 3rd party equivalent), then you’re all set to continue into part 2!

2D Camera – Background theory:

Yes, theory…hooray! This is important though and good to know before we write code for the camera. First thing’s first, this is NOT an actual camera as you may think! No rendering, no fancy visual effects, nothing. Stripped down, it is simply a Vector2 which represents the “Position” if you like, of the ‘camera’.

This position is then used to offset all sprites (eg. player, enemies, bullets) as they are drawn, giving the illusion of a camera being used. Simply put, you can call this technique ‘side-scrolling’ or even ‘faked-scrolling’, as that’s essentially what this ‘camera’ class does – changes a position, then subtracts that position from the position of everything you want to scroll.

I’ve used this technique in several games and as simple as it is, it does the job quite well. If the explanation of how this camera will work didn’t make sense, the following code should clear things up. Create a new C++ header (‘.h’) file and name it ‘Camera‘.

Simple 2D ‘Camera’ class:

#ifndef CAMERA_H
#define CAMERA_H

#include "Collision.h"

// Simple 2D 'Camera' class
class Camera
{
public:
      // Function prototypes
      //---------------------//

      Camera(); // Default constructor

      // Set up frustum box using specified screen margins
      void InitFrustum(int a_iMargin_X = 20, int a_iMargin_Y = 20);

      // Return true if specified collider is within camera frustum
      bool InFrustum(BoxCollider* a_pCollider, bool a_bOverlap = true);

      // Member variables
      //---------------------//

      Vector2 m_Position; // 'Camera' offset position

private:
     // Frustum box
     struct FrustumBox
     {
            // Edges of the frustum box
            float Left, Right, Top, Bottom;
     }Frustum;
};

#endif // CAMERA_H

// Externally define the 'Camera' class as 'camera'
extern Camera camera;

The structure of the Camera class is done. Our frustum is simply a struct called ‘FrustumBox‘ (defined for use as ‘Frustum‘), which contains four float values. Each value represents a respective on-screen boundary, imagine the four boundaries together as a rectangle. Yes, that is our frustum ‘box’.

Create a new C++ source file (‘.cpp’) and name it ‘Camera‘.

‘InitFrustum’ function:

#include "Camera.h"

// Define the 'Camera' class as 'camera'
Camera camera;

// Set up frustum box using specified screen margins
void Camera::InitFrustum(int a_iMargin_X, int a_iMargin_Y)
{
      Frustum.Left   = SCREEN_W - (SCREEN_W - a_iMargin_X);
      Frustum.Right  = SCREEN_W - a_iMargin_X;
      Frustum.Top    = SCREEN_H - (SCREEN_H - a_iMargin_Y);
      Frustum.Bottom = SCREEN_H - a_iMargin_Y;
}

You may have noticed in the function prototype, both the ‘a_iMargin_X‘ and ‘a_iMargin_Y‘ parameters are set to 20 by default. This will give you a margin of 20 on each side of the frustum box, between it and the respective edge of the screen. By passing other values into this function, you can control how big you want the frustum to be with ease. I found 20 was a decent starting value, which is why I used that.

Note that ‘SCREEN_W‘ and ‘SCREEN_H‘ are just example variables I made up, to represent the width and height of the screen. Replace these with your own variables or if you like, just straight numbers (eg. 1280, 720).

‘InFrustum’ function:

// Return true if specified collider is within camera frustum
bool Camera::InFrustum(BoxCollider* a_pCollider, bool a_bOverlap)
{
      // Set frustum boundaries to use, based on 'a_bOverlap' value
      float fFrustum_Left   = a_bOverlap ? Frustum.Left - a_pCollider->Size.X : Frustum.Left;
      float fFrustum_Right  = a_bOverlap ? Frustum.Right + a_pCollider->Size.X : Frustum.Right;
      float fFrustum_Top    = a_bOverlap ? Frustum.Top - a_pCollider->Size.Y : Frustum.Top;
      float fFrustum_Bottom = a_bOverlap ? Frustum.Bottom + a_pCollider->Size.Y : Frustum.Bottom;

      if (a_pCollider->GetLeft() >= fFrustum_Left         // Within left side of frustum
          && a_pCollider->GetRight() <= fFrustum_Right    // Within right side of frustum
          && a_pCollider->GetTop() >= fFrustum_Top        // Below top side of frustum
          && a_pCollider->GetBottom() <= fFrustum_Bottom) // Above bottom of frustum
      {
          // Collider is inside camera frustum
          return true;
      }

      // Collider is outside camera frustum
      return false;
}

The return value of boolean parameter ‘a_bOverlap‘, determines whether we want to allow the collider to be PARTIALLY (overlapping) inside the frustum, in which case we would pass ‘true‘, or whether we want to make sure the collider is ENTIRELY inside the frustum, in which case we would pass ‘false‘.

The four temporary frustum values, are then either directly assigned to the default frustum values (‘a_bOverlap‘ is ‘false‘) or are assigned to the default frustum values with the collider’s width and height added or subtracted (‘a_bOverlap‘ is ‘true‘).

Note that the ‘a_bOverlap‘ parameter is set to ‘true‘ by default.

Example – putting it all together:

Now that we’ve finished the Camera class, it’s time for an example of putting it to use!


#include "Camera.h"

BoxCollider myCollider; // BoxCollider for this example

// Set up our collider (use your own values if you like)
myCollider.Size     = Vector2(60);
myCollider.Position = Vector2(50);

// INSIDE GAME LOOP (update/draw each frame)
//------------------------------------------//

if (camera.InFrustum(&myCollider))
{
     // The collider is inside the camera frustum!

     // Reset collider velocity
     myCollider.Velocity = Vector2(0);

     // Move collider left
     // If the 'A' key was pressed
     // myCollider.Velocity.X -= 40.0f;

     // Move collider right
     // If the 'D' key was pressed
     // myCollider.Velocity.X += 40.0f;

     // Apply velocity to collider position
     myCollider.Position += myCollider.Velocity;

     // Eg. Check for collision...
     // Eg. Draw object using this collider...
}

Several comments in this example are pseudocode, because this tutorial doesn’t cover using a 3rd-party (or making one) engine for rendering and input. They still get the idea across of how you could go about updating the collider.

Part 2 Conclusion:

And there you have it, a complete simple, yet effective 2D Camera system with frustum culling functionality. This system can quite easily be built upon to allow for more advanced functionality, but as is, it’s all one needs for simple 2D culling (and even side-scrolling, as I mentioned earlier). On a side note, this tutorial has laid all the foundations needed for an upcoming tutorial I have planned!

If this tutorial has been helpful, I truly appreciate any thanks or feedback. You could share a link to this tutorial on another site, follow this blog or list this blog for thanks/special thanks in the credits of your game – any of these would be greatly appreciated!

Return to Part 1                                                                                                                      Return to Tutorials page