Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon Join the GFS Discord Server!
14. October 2015

 

Tiled is a popular open source map editor for creating 2D maps using tiled graphics.  I have used Tiled in several previous tutorials and no doubt will be using Tiled in several future series, so instead of covering it partially over and over again, I decided to do a Tiled video tutorial series that I will simply link to.  This is that tutorial series.  As I add new tutorials I will link them below.

 

Right now the contents consist of:

 

An earlier text based introduction to Tiled from GameFromScratch is available here.

If you are interested in learning out to make isometric tiles in Blender check this tutorial.

 

Previous tutorials that have used Tiled include:

 

Direct version of the videos embedded below:

Art Programming


12. October 2015

 

In our prior tutorial we created a simple application that showed the basics of event handling in SFML.  In this tutorial we are going to expand upon that concept a bit further and show how to read the keyboard, both using events and direct polling.  Although not strictly SFML related (anymore anyways), we are also going to be covering random number generators as part of our demonstration, a very common task in game development.

 

As always, there is an HD video version of this tutorial.

 

Earlier we used the RenderWindow method pollEvent() to check for and respond to the Closed event.  Now let’s look at the process of responding to keyboard events.

while (renderWindow.pollEvent(event)){
    //Handle events here
    if (event.type == sf::Event::EventType::Closed)
      renderWindow.close();

    //Respond to key pressed events
    if (event.type == sf::Event::EventType::KeyPressed){
      if (event.key.code == sf::Keyboard::Space){
        // Do something here
      }
    }
  }

 

As we can see, responding to a KeyPressed event is nearly identical to a Closed event.  The key difference is, once you have identified that the event is a keyboard event you have additional information available in the event’s key structure.  The value of key.code is a sf::Keyboard::Key enum for each available key.  In addition to the KeyPressed event, there is also a KeyReleased event that is sent when the key is, well, released.  By default KeyPressed will be fired again and again if held down.  If you would prefer to have only a single event fired for a key press you can change this behaviour using the RenderWindow setKeyRepeatEnabled().

 

This is an example of Event driven programming in which your program responds to events as they occurred.  Sometimes however you would rather poll for input then wait for it to occur.  For example you might want to ask “hey computer, what keys are pressed?” or “is the control key down?”.  Fortunately SFML supports this out of the box, like so:

  if (sf::Keyboard::isKeyPressed(sf::Keyboard::R))
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
      // Do something

 

This code snippet first checks if the ‘R’ key is currently pressed.  It then checks to see if the Control key is pressed, as you can see in the example above the left and right control keys are separate events.  You can mix and match event driven and polled input handling however you want, but be careful not to get in a situation where you are accidentally handling the same input multiple times.

 

We are going to create a full example in a second that puts all of these processes together by randomly changing the screen color based on keys being pressed.  First, lets cover that process of creating a random number, a very common process in game development.  In fact, random number generation used to be part of SFML, but as of SFML 2.0 it was removed, partly because it didn’t make sense and partly because it’s now well entrenched in the language in a cross platform manner.

 

There are two ways we can generate random numbers, using the older C style, or the more modern C++ 11 style.  The new way is more appropriate for generating truly random numbers for security reasons and has no global state, but the old C style way should be more than sufficient for game development, so pick the way you like best.  The process is very similar… you generate a sequence of random numbers using some form of seed value, then massage the results into the numeric range you want.  Let’s look first at the C way of generating randoms:

  srand(time(NULL));               //seed random number generator with the current time
  auto randomNumber = rand() % 255;//generate a random number then confine it to a value of 0-255.

The first call sends the random number generator using the current system time.  Then we call rand() to get a random number.  One important thing to be wary off, the seeding process is fairly slow, while the rand() call is slightly lighter weight.  Next we look at the C++ way:

  std::uniform_int_distribution<int> randomColorRange(0, 255);
  std::random_device rd;
  std::mt19937 randomNumbers(rd());
  auto randomVal = randomColorRange(randomNumbers);

This example does basically the same thing as the earlier version.  The uniform_int_distribution object is a lightweight object that can be used to massage the data generated by mt19937 algorithm into actual int values within the defined range.  The mt19937 is an implementation of Mersenne Twister algorithm for generating random numbers.  The random_device is a built in object for creating a seed for your random number generator instead of using the current time ( although it’s quite possible that random_device uses the time behind the scenes ).  Using random_device is heavy weight, as is mt19937, so be careful where you generate random numbers.  However using those generated numbers with a uniform_int_distribution is light weight.

 

Ok, so we now know how to respond to keyboard events, poll the keyboard directly and generate random numbers, let’s tie it all together in a single example.

// This example demostrates the main loop

#include "SFML/Graphics.hpp"
#include <iostream>
#include <random>

int main(int argc, char ** argv) {
  sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "SFML Demo");

  sf::Event event;

  // A Clock starts counting as soon as it's created
  sf::Color color(sf::Color::Red);


  // C++ 11 way of generating a random between 0 - 255
  // mt19937 is an implementation of the Mersenne Twister pseudo random number generator
  // random_device() returns a random number to use as a seed for the mt algorithm... slow however so that's why we dont just use it for all randoms if you were wondering
  // mt results arent in a human friendly format, so we use uniform_int_distribution to "shape" the results to our range and type
  // uniform_int_distribution is a fairly "light" object.  random_device and mt19937 aren't.
  std::uniform_int_distribution<int> randomColorRange(0, 255);
  std::random_device rd;
  std::mt19937 randomNumbers(rd());
  
  // Pre-C++ 11 but more common way (*with issues, see:
  //https://www.reddit.com/r/programming/comments/1rnudl/quite_interesting_why_cs_rand_is_considered/
  // Mostly doesn't apply to game devs if not using rand for say... security.
  
  /*
  srand(time(NULL));          //seed random number generator with the current time
  auto randomNumber = rand() % 255;   //generate a random number then confine it to a value of 0 - 255.
  */

  while (renderWindow.isOpen()){
    // Check for all the events that occured since the last frame.
    while (renderWindow.pollEvent(event)){
      //Handle events here
      if (event.type == sf::Event::EventType::Closed)
        renderWindow.close();

      //Respond to key pressed events
      if (event.type == sf::Event::EventType::KeyPressed){
        if (event.key.code == sf::Keyboard::Space){
          color.r = randomColorRange(randomNumbers);
        }
      }
    }

                      
    // Now demonstrate input via polling
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::R))
      if (sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
        color.r = 0;
      else
        color.r = randomColorRange(randomNumbers);

    else if (sf::Keyboard::isKeyPressed(sf::Keyboard::G))
      if (sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
        color.g = 0;
      else
        color.g = randomColorRange(randomNumbers);
    else if (sf::Keyboard::isKeyPressed(sf::Keyboard::B))
      if (sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
        color.b = 0;
      else
        color.b = randomColorRange(randomNumbers);

    

    renderWindow.clear(color);
    renderWindow.display();
  }

}

 

All we are doing in this example is setting the clear color of the RenderWindow based on keyboard input.  On pressing the spacebar we handle this using event driven input and set the Red channel of our clear color to a random value between 0-255.  A value of 0 means no red, while 255 is fully red.  We then directly poll the keyboard for input look to see if the R/G/B keys are pressed.  If they are, we assign that color channel to a random value.  If we also have the control key pressed, we instead set that channel to 0.  Therefore pressing CTRL+R, CTRL+G, CTRL+B will result in a black window.

 

As you can see, SFML makes it simple to handle keyboard input, both using an event driven model or by polling.  One thing it does not provide however is any sense of history.  We can check if a key was pressed or released during a given frame but we can’t really track the history a very common requirement.  That said, rolling your own solution is very simple, as shown below:

// This example demostrates the main loop

#include "SFML/Graphics.hpp"
#include <unordered_map>
#include <iostream>

int main(int argc, char ** argv) {
  sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "SFML Demo");

  sf::Event event;

  // If true, you will continue to receive keyboard events when a key is held down
  // If false, it will only fire one event per press until released
  renderWindow.setKeyRepeatEnabled(false);

  std::unordered_map<int, bool> keys;
  std::list<int> changedKeys;

  while (renderWindow.isOpen()){
    changedKeys.clear();

    while (renderWindow.pollEvent(event)){
      if (event.type == sf::Event::EventType::Closed)
        renderWindow.close();

      if (event.type == sf::Event::EventType::KeyPressed){
        if (keys.count(event.key.code) == 0){
          keys[event.key.code] = true;
          changedKeys.push_back(event.key.code);
        }
      }
      if (event.type == sf::Event::EventType::KeyReleased){
        if (keys.count(event.key.code) == 1){
          keys.erase(event.key.code);
          changedKeys.push_back(event.key.code);
        }
      }
    }

    std::cout << "Currently pressed keys: ";

    // To get the actual value as a string, you need to use Thor or write your own version
    for (auto& keyValue : keys)
      std::cout << keyValue.first << " ";
    std::cout << std::endl;

    if (!changedKeys.empty()){
      std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Keys changed" << std::endl;
    }
    renderWindow.clear();
    renderWindow.display();
  }

}


This approach is pretty typical of SFML.  The basic tools are there for you, but you may have to build a layer on top to fit your game.  That said, there is a library called Thor that covers many of these common scenarios, essentially a utility library built over top of SFML providing additional functionality.  For example, in addition to providing the kind of functionality we just implemented above, there is also a utility for turning SFML Key enum values into a printable format.  We will probably cover using at least parts of Thor at a later point in this series, but for now I want to focus on core SFML.

 

The Video


Programming


9. October 2015

 

In this part of the SFML we will look at creating our first basic SFML application.  At the heart of every SFML application is the RenderWindow which provides both a way to draw things on screen and receive input events from the user.

 

As always, there is an HD video of this tutorial here.

 

At the heart of every non-trivial game is the game loop.  In some game engines it’s hidden away from you inside the engine, but it is always there somewhere.  In SFML it is your responsibility to implement, which is what we will do today.  A game loop is a pretty simple concept… it’s a loop that runs over and over until your game is completed.  Each pass through the loop the screen is cleared and new graphics are drawn (this is referred to as a frame, so when you hear Frames Per Second, this is what is being referred to).  There are several other tasks a game is responsible for handling… input and physics to name just two.

 

Let’s start off with a very simple application:

#include "SFML/Graphics.hpp"

int main(int argc, char ** argv) {
  sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "SFML Demo");

  while (true) {
    renderWindow.clear();
    renderWindow.display();
  }

}

This represents about the simplest meaningful SFML application you can create.  We create a new RenderWindow, passing in both its dimensions and title.  Then we simply loop forever and each pass through the loop we clear the window then draw it again with a call to display().

 

When you run this code you will get a black 640x480 window on screen, however if you attempt to move or close this window you will quickly notice something is wrong.  It doesn’t respond to any of your actions.  In fact, if you lose focus (click on a different window) you can’t even get it to focus again!  This is because we aren’t responding to any events.  Let’s switch things up a bit so that are window is a tad more responsive.  Instead of simply looping forever, we will create a slightly more intelligent game loop.

  sf::Event event;
  while(renderWindow.isOpen()){
    // Check for all the events that occured since the last frame.
    while (renderWindow.pollEvent(event)){
      //Handle events here
      if (event.type == sf::Event::EventType::Closed)
        renderWindow.close();
    }
  
    renderWindow.clear();
    renderWindow.display();
  }

Now your window properly responds to events, it can be moved around and most importantly, it can be closed.  Let’s take a quick look at what we’ve done here.

 

First off, instead of looping forever, we instead loop until our RenderWindow is closed.  Next inside this loop we’ve implemented another while loop that calls pollEvent.  pollEvent checks for all of the events that occurred since the last time pollEvent was called.  It is called inside a while loop because it is possible that multiple events occurred since the last pass through the outer loop.  pollEvent() will return false when no more events exist.  Events exist for things such as mouse and keyboard actions or the window being resized.  In this particular case we are checking to see if the EventType is Closed, which means a close request has occured.  In the event that one does we call renderWindow.close() which will result in the next check of isOpen() to return false, thus ending our game.

 

We will cover events in more detail later, but for an idea of what EventTypes exist, click here.  There are two very important things to realize in this game loop.  Notice that the sf::Event is declared outside of the loop?  This code is going to be called ALOT.  Never put variable allocations, even stack based ones like this, inside a high frequency loop if it can be helped.  Second, notice how the clear() and display() calls are outside of the inner pollEvent() loop?  This is also important, as otherwise your screen with only update when an event occurs!

 

There is one final important concept to cover before we move on to the next tutorial… time.  It is quite common for a game engine to provide the elapsed time since the last frame.  This value is very useful to your entire game as we will see shortly.  In SFML however you are rolling your own game loop, so you are also rolling your own time tracking system.  Don’t worry though, the process is extremely simple.  That’s see one final complete sample that also keeps track of the elapsed time per frame.

#include "SFML/Graphics.hpp"
#include <iostream>

int main(int argc, char ** argv) {
  sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "SFML Demo");

  sf::Event event;

  // A Clock starts counting as soon as it's created
  sf::Clock clock;
  
  while(renderWindow.isOpen()){
    // Check for all the events that occured since the last frame.
    while (renderWindow.pollEvent(event)){
      //Handle events here
      if (event.type == sf::Event::EventType::Closed)
        renderWindow.close();
    }
  
    // A microsecond is 1/1,000,000th of a second, 1000 microseconds == 1 millisecond
    std::cout << "Elapsed time since previous frame(microseconds): " << clock.getElapsedTime().asMicroseconds() << std::endl;
    // Start the countdown over.  Think of laps on a stop watch.
    clock.restart();


    renderWindow.clear();
    renderWindow.display();
  }

}

You will notice the addition of an sf::Clock to our game.  The Clock provides the most accurate time that the underlying OS is capable of giving (different timers have different resolutions, and this timer needs to be very precise!).  As soon as it is declared, it starts counting.  Think of sf::Clock like a stopwatch that starts automatically.  Each “lap” you can read the elapsed time using getElapsedTime() and you can start a new lap by calling restart().   In this example we get the elapsed time in microseconds.  There are 1000 microseconds in a millisecond, and 1000 milliseconds in a second, so a microsecond is one millionth of a second.  Like I said, we need precision!

 

So that is the process of creating a very simple SFML application, clearing and displaying the window, tracking how much time elapsed and handling events.  In the next tutorial we will look at events a bit closer and see how best to handle keyboard input.

 

The Video

 

Programming


28. July 2015

 

We covered viewports a while back but now we are going to go into a bit more detail, as it’s an important subject.

 

There is a 1080p version of this tutorial available here.   Please note, the full screen portions didn’t display properly in the video.

 

One very important thing to understand is, the very root of your scene, the node that owns all of the nodes in a scene, is ultimately a viewport.  Consider this hierarchy:

image

In that node if you run the code:

func _ready():
   print(get_node("/root"))

 

You will see:

image

 

So, no matter how you create your scene, you will always have at least one viewport.  On the other hand, you can create more viewports within the scene as we will see later.

 

Full Screen Applications

 

It’s possible to set your application to run full screen, both using code or in the application settings.  To do it with code, create a new autoload script as described here.  This is a script, derived from node, that gets run automatically when your game launches.  Use the following code:

extends Node

func _ready():
   var root = get_node("/root")
   root.connect("size_changed",self,"resize")
   OS.set_window_fullscreen(true)
   set_process_input(true)
   
#Event called when viewport size changed  
func resize():
   var root = get_node("/root")
   var resolution = root.get_rect()
   print(resolution)
   
#Input handler, listen for ESC to exit app
func _input(event):
   if(event.is_pressed()):
      if(event.scancode == KEY_ESCAPE):
         get_tree().quit() 

 

Of course this code does a lot more than just set the application full screen.  Due to the app going full screen, it is no longer easy to close the window, so I’ve also wired in some code to handle shutting down if the user hits Esc.  There is also an event handler connected to fire when the resolution changes, we simple print the resolution to the console when it changes.

 

You can accomplish the exact same thing (much easier) using project settings, like so:

image

Please note there are two check boxes to enable!  First you need to enable the fullscreen setting, then you need to turn it on.

 

Viewport Scaling

Now to illustrate how resolution works in Godot, I’ve created a Sprite Node( not centered, at 0,0 ) using this image, which illustrates the various screen resolutions.

image

 

The actual image is 1920x1080 in size, so it should show us the results that various settings have on our game.  Here is a run, using default settings on my laptop which has a 1600x900 display. 

The following display settings are very important.

image

The following screenshots are all scaled down but maintain the aspect ratio of the source image.  The Viewport setting has a profound effect on the results.  The options are:

image

 

Viewport == disabled.  Resolution is 1600x900 ( my native resolution ) and display resolution settings ignored.

image

 

Mode == 2d.  Image size is 1600x900.

image

 

Viewport stretch mode.  Image size is 800x600.

image

 

It’s the ultimate results that make the difference.  When viewport is set to disabled, the width/height are ignored completely and the resolution of the device is used.  In viewport set to 2D, the width and height are used and the results are simply scaled up (or down) to match the resolution of the actual device.  While in Viewport, the results are actually scaled down to the resolution specified.  This means our actual render results are at 800x600 ( or whatever resolution you specified ).   You would generally use this last mode if you were trying to create a pixel perfect game, or if you are trying to render to a lower resolution to improved performance.  Keep in mind on most machines the results will look somewhat horrible.

 

 

 

Handling Aspect Ratios

Now this resizing works great when you are dealing with the same aspect ratios, but once they start changing, it has a much more pronounced effect.  For example, content designed for a 4:3 screen ( iPad ) will look horrible on a 16:9 screen ( Galaxy Note ) for example.  You also need to decide HOW you are going to deal with different aspect ratios.  This isn’t a new problem, people watching single def signals on HD displays have been dealing with this issue for years.

I created a new Sprite, this time using a sprite 379x124 pixels in size, like so:

image

Then automatically position it in the center of the viewport on load:

 

func _ready():
   self.set_pos(Vector2(get_viewport_rect().size.width/2,
                get_viewport_rect().size.height/2))

 

As mentioned earlier, my laptops native resolution is 1600x900, so everything looks fine with an HD resolution.  For example, here is the result rendered at 1280x720 full screen (but scaled down on the blog):

image

 

Looking good!  Now lets try 640x480, a not so HD aspect ratio:

image

 

Ewwww…. ok… obviously not what we want.  The result of the resampling to fit a 640x480 image on a 1600x900 screen as stretched our ship almost to the point of being unrecognizable.

You do however have options here, once again under display settings called stretch_aspect.

image

 

Lets see the result on our 640x480 scene:

 

ignore

image

keep

IMAG0363

keep_width

IMAG0364

keep_height

IMAG0365

 

You may notice the pictures are literally camera shots of my laptop.  This is because the screenshots don’t capture the black bar portions of the image.

Basically you can choose to simply rescale the aspect ratio, which causes the sprites to distort if the source and destination resolutions don’t have a similar aspect ratio.  Choosing Keep will cause it to keep the aspect ratio specified and generate black bars, either horizontally or vertically, whichever is needed.  You can also tell it to keep the height or the width aspect ratio.  The remaining dimension ( height if you chose Keep_width for example ) will then be scaled to fit, causing distortion in that direction.

 

Sub-Viewport

As mentioned earlier, the root node in the scene is always a viewport.  You can however create a viewport node within the scene or embedded within another node.

 

Consider this hierarchy of Nodes for example:

image

 

In the Editor it looks like a complete mess:

image

But when you run it, you can immediately see the results:

image

The nodes added to the child viewport are positioned relative to, and rendered within that viewport.

 

Cameras

 

The Camera2D class in Godot is mostly just responsible for manipulating the transform of the viewport.  A Camera automatically applies itself to the closest viewport above it in the node hierarchy, and if there isn’t one, it affects the root node instead.  Only one camera can be active at a time per viewport.

 

Otherwise using a camera is extremely simple.  Consider a scene like this that extends beyond the viewport:

image

 

Simply drop a Camera2D node into the scene:

image

 

Set Current To On

image

 

And your view will automatically update to represent the camera’s position

image

 

 

Taking a Screen Shot

 

When running full screen, capturing a screen shot can become a bit tricky.  I got around it by handling the logic in code.  If you are interested, here is how I captured a screenshot using Godot:

      if(event.scancode == KEY_SPACE):
         print("Screenshot")
         get_viewport().queue_screen_capture()
         yield(get_tree(), "idle_frame")
         yield(get_tree(), "idle_frame")
         var screenshot = get_viewport().get_screen_capture()
         screenshot.save_png("user://screenshot.png")

The location of “user://” is going to change from platform to platform.  On Windows 8.1 the screenshot was located at C:\Users\Mike\AppData\Roaming\Godot\app_userdata\Viewport on my computer.  On Linux, check for a directory named .godot in your home directory.

 

The command queue_screen_capture() doesn’t happen immediately.  This is why we yeild two frames before calling get_screen_capture(), which will have the results of queue_screen_capture() or return an empty image if it hasn’t occurred yet.

 

The Video

Programming


12. July 2015

 

In today’s “A Closer Look At” guide we will be taking a look at the App Game Kit 2 game engine.  The Closer Look at Series is a combination preview, review and imagegetting started tutorial aimed at giving you a solid overview of what working in a particular game engine is like.  App Game Kit is a cross platform game engine capable of making games for Windows, Mac, iOS, Android and Blackberry devices using Mac or Windows development environments.  App Game Kit regularly costs $99, although if you are reading this near the publish date ( 7/12/15 ) it is currently available in the Humble Gamedev Bundle with several other tools.

 

AppGameKit is a cross platform, mobile friendly 2D/3D game engine, although 3D is a work in progress.  AGK is programmed primarily using AGK Script, which is a BASIC dialect with some C++ style features.  If the word BASIC caused you to recoil in terror from your screen, don’t worry, AGK is also available as a C++ library.  If the word C++ just recoiled from your screen, hey… there’s always AGK Script… :)  Over the course of this article we will take a quick look at both.  AppGameKit 2 was the result of a successful Kickstarter campaign and is a product of The Game Creators who previously developed Dark Basic and 3D Gamemaker.

 

There is also an HD video version of this article available here or embedded below.

 

Hello AGK

Let’s jump right in with a pair of Code samples.  First in AGK Script, then in C++.

 

AGK Script Example

// Project: test 
// Created: 2015-07-10

// Setup the main Window
SetWindowTitle( "My Game Is Awesome!" )
SetWindowSize( 640, 480, 0 )

// set display properties
SetVirtualResolution( 640, 480 )
SetOrientationAllowed( 1, 1, 1, 1 )

// Create a Cube 100x100x100 at the Origin
box = CreateObjectBox(100,100,100)
SetObjectPosition(box,0,0,0)

// Add a light to the scene
CreateLightDirectional(1,-1,-1,-0.5,255,255,255)

// Set the position of the camera and aim it back at the origin
SetCameraPosition(1,0,100,-150)
SetCameraLookAt(1,0,0,0,0)

rotationY# = 0

// Gameloop
do
   // Display the current FPS
   Print( ScreenFPS() )
   // Rotate our Object
    SetObjectRotation(box,0,rotationY#,0)
    // Display back buffer
    Sync()
    // Update Rotation
    rotationY# = rotationY# + 1
loop

 

Here is this code example running:

g1

 

C++ Example

// Includes
#include "template.h"

// Namespace
using namespace AGK;

app App;

void app::Begin(void)
{
   agk::SetVirtualResolution (640, 480);
   agk::SetClearColor( 0,0,0 ); 
   agk::SetSyncRate(60,0);
   agk::SetScissor(0,0,0,0);


   // Load a Sprite at index 1
   agk::LoadSprite(1,"logo.png");
   // Scale the sprite to 25% of it's size
   agk::SetSpriteScale(1, 0.25, 0.25);

   
}

void app::Loop(void)
{
   agk::Print(agk::ScreenFPS());

   // On gamepad press, spacebar hit, touch or left click enable 
   physics on our sprite
   // And make that sucker bouncy, gravity does the rest
   if (agk::GetButtonPressed(1) || agk::GetPointerPressed()){
      agk::SetSpritePhysicsOn(1, 2);
      agk::SetSpritePhysicsRestitution(1, 0.8);
   }

   agk::Sync();
}


void app::End (void)
{

}

 

Here is this code sample running:

g2

 

There is a bit more to the C++ example than the code shown here.  AGK is provided as a library for C++ use.  To get started there are also a number of templates that you can copy and start from.  Each template has a bootstrap class containing the required code to start AGK.  For example the Visual Studio project provides a WinMain implementation for you.  Here are the currently available templates for a Windows install (MacOS has XCode projects available for iOS and Mac):

image

 

Of course you can of course create your own application and simple use AGK as a C++ library if you prefer.

 

Tools Included

 

AGK IDE

If you are working with AGK Script, the majority of your development will be done in AGK IDE.  AGK IDE is a Code::Blocks derived IDE with full text editing, syntax highlighting, code completion and debugging support for AGK Script.

image

 

I experienced no lag when using the IDE.  Most of the features you would expect in a modern IDE are available, including code folding, find/replace, intellisense and code hints:

image

 

Refactoring tools are all but non-existent and unfortunately there is no local help.  (We will discuss help files shortly).

 

Debugging is supported:

image

But the implementation is barebones, limited to break points, step over/out and displaying the call stack.  You can inspect variable values, but you have to enter them manually in the Variables area.  There is no ability to inspect, add watch or set conditional breakpoints.  I believe this functionality is relatively new, so hopefully it will be extended with time.

 

If you choose to work with C++, you will not use AGK IDE at all, instead working in your C++ IDE of choice.  As mentioned earlier, several templates are provided.

 

Placement Editor

AGK also ships with the Placement Editor, a fairly simplistic tiled level creator:

image

 

It enables you to place varying sized tiles, perform transforms such as rotation and mirroring, layer up and down and supports grid snapping to grid for precise layouts.  The UI however leaves something to be desired, with the scroll bars only supporting movement via the arrows and panning controlled using an onscreen controller.  Additionally you have to exit the application and copy graphics to the media directory to add new tiles.  Unfortunately it’s also lacking some seriously required functionality such as defining collision volumes or physics properties.  It does however enable quick creation of tiled backgrounds.

AGK Player

One other cool feature of AppGameKit is the AGK Player, available on mobile devices:

ss

 

By pressing Broadcast in the IDE, you can easily see your code running on device without having to bundle/sign/deploy like normal.  It is available for download in the app store, except on iOS where you have to build and deploy it yourself using XCode.  This tool enables rapid on device testing during development and can be a huge time saver.

 

Samples and Demos

AppGameKit ships with an impressive number of AGK Script code samples:

image

Including a few complete games:

image

And some user provided examples:

image

 

Here is the SpaceShooter example in action:

g3

 

Documentation and Help

 

I mentioned earlier that there is no local documentation available, which is unfortunate.  There also doesn’t appear to be a generated class library reference, which is also unfortunate.   That said, the documentation available for AGK is actually rather solid and has been complete from my experiences.  It is available entirely online so you can check it out yourself.

 

The scripting language itself is quite simple and documented here in reference form.  While a more broad language introduction and overview is available here.  As mentioned earlier, there are also dozens of examples included to learn from.  There are a series of guides available covering specific topics such as networking , platform publishing and more.  The closest thing to a class reference is the Commands documentation, you can toggle between C++ and BASIC code examples:

image

 

AGK also has a very active developer forum available.

 

The Library

 

Of course we should talk about what functionality is available in AGK.  Over all it’s quite comprehensive, although the 3D functionality is very actively under development and some functionality is obviously missing or under development ( such as animated 3D model support ).

 

The follow feature list is taken directly from the AGK site.

  • Write once, deploy technology
  • Code in BASIC or native (C++)
  • Device independent
  • Cross Platform IDE
    • Develop on Windows or Mac and deploy to Windows / Mac / iOS / Android / Blackberry 10
    • Broadcast test apps to devices over Wifi
    • Auto Complete
    • Function Lists
    • Code Folding
    • Export to exe/app/apk/ipa
  • 2D Games Engine
    • Tweening
    • Blending modes
    • Spine Support
    • Box 2D Physics
    • Particles
    • Drawing commands
    • Text support - fixed and variable width
  • 3D Engine
    • Primitives
    • Positioning
    • Rotation
    • Shaders
    • Collision
    • Cameras
    • Lights
  • Audio/Visual
    • Video Playback
    • Sound
    • Music
  • Input Agnostic
    • Direct Input Control
    • Touch
    • Keyboard
    • Mouse
    • Accelerometer
    • Joystick/Controllers
  • Sensors
    • Camera Access *
    • GPS *
    • Geo-location *
    • Inclinometer *
    • Light Sensor
  • Mobile
    • Rating an app *
    • In-App Purchasing *
    • Adverts *
    • - Chartboost
    • - Admob
  • Networking
    • Messages
    • Shared Variables
  • Misc
    • File IO
    • Facebook *
    • File IO
    • Extensive help & tutorials
    • Time & Date
    • Enhanced image control
    • QR Codes
    • HTTP
    • Edit Boxes
    • Zip file control
  • Coming Soon...
    • Debugger
    • 3D Engine Enhancements
    • File IO
    • 3D Bullet Physics
    • Extension System

    * Selected platforms only.

 

Conclusion

 

I certainly haven’t spent enough time with AGK to consider this a full review by any means.  The following are my initial impressions when working with AGK.  I am personally not a huge fan of the BASIC language, even as a beginner recommendation, but AGK Script is accessible and the included tooling make AGK an appropriate choice for beginners, especially with the included examples and solid documentation.  I was able to use the library very much by intuition and the ability to code entirely in C++ will appeal to several developers.  The mapping between C++ and BASIC is very natural but this also comes at a cost.  The C++ side of the equation is very “flat” in structure, using no OOP and a disconcerting number of “magic number” type variables.  In a simple project, AGK is a solid and approachable choice.  In more complex projects, without writing an organizational layer over top, I could see quickly developing a mess of unmaintainable code.

 

The tools included with AGK are functional but could both use a bit of polish.  The editing experience in AGK script is fine but the debugger is fairly young and needs some work and the some more refactoring support would be nice.  Integrated and context sensitive help would also be a huge boon.  For the most part though there is enough functionality in the IDE that working in AGK Script wouldn’t feel like a chore.  The level editing tool is nice in that it exists, but the functionality is extremely limited and the UI isn’t the best.  For anything but the most trivial game, I would imagine you would find yourself wanting a more mature tool like Tiled, although a loader is available, so this is certainly an option.  Also, the editor is only available on Windows machines.

 

From a developer perspective, for a 2D game, AGK provides pretty much all of the functionality you would expect and some that is a bit unexpected, like cross platform video playback.  3D is coming along but missing some key functionality.  The code experience is incredible consistent, once you’ve figured out how to do one task, you can generally guess how other tasks are going to be performed.  You can accomplish a great deal in AGK in a very short period of time, but I do question how well the design would scale to larger projects.  As a C++ library, AGK could also be considered as a cross platform competitor to libraries such as SFML or SDL.  AGK does appear to be a good solution for new developers, especially if you like the BASIC programming language or wish to work with an approachable C++ library.  For more experienced developers, AGK is a productive and easy to learn library supporting a respectable number of platforms with the option of high and low level development.  I just don’t know how well this product would scale with project complexity.

 

The Video

Programming


See More Tutorials on DevGa.me!

Month List