Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon
30. December 2015

 

GarageGames have just released Torque2D version 3.2.  Torque2D is 2D game engine built over the Torque 3D engine, which is now open source and MIT licensed.

From the release:

While you were singing carols door to door and sipping eggnog by the fireplace, the T2D Steering Committee was hard at work wrapping up one last present! Presenting Torque2D 3.2! This latest incarnation of everybody's favorite 2D engine sports several shiny new features! But before we get into that, let's take a moment of silence to remember the many bugs that lost their lives to make this release possible.


Now then, our first new feature is the FadeTo function. This works like MoveTo except that it changes the blend color over time instead of the position. If you ever wanted to fade a bad guy out when it died or fade a slightly transparent object in, then this function was written for you! It could be used to make your hero flash red when his life is low or slowly change the color of the sky as the sunsets. FadeTo comes with all the support functions of MoveTo including a cancel function and callback when it's finished.


We also added GrowTo which changes the size of an object over time. With GrowTo you can change the x and y at different rates and create all kinds of neat effects. But, there's a catch! Collision shapes don't grow with the sprite. So if your object has collision shapes attached you'll want to use it sparingly. Slight changes can do a lot. Like FadeTo, GrowTo is supported by functions to test and cancel. When an object reaches its target size it will fire a callback.
We also have support now for one way collisions. This is most commonly seen in platformer games when a character jumps up through the platform and magically lands on top of it, but in theory there's many other uses for it. This only works for edge and chain collision shapes.
And finally, last but not least, we have revived ogg! That's right! The open source, compact audio format is back by popular demand. You can start using ogg files again on Windows and Mac OSX.

GameDev News, Programming , ,

23. November 2015

 

 

In this tutorial we are going to look at audio programming in Cocos2d-x.  We will look at playing music and sound effects using SimpleAudioEngine, one of two engines built into Cocos2d-x.  There is a second, newer, more commplex and experimental audio engine AudioEngine, that we will discuss later.  Let’s start straight away by playing some music.  To make use of SimpleAudioEngine we need to add an additional include call:

#include "SimpleAudioEngine.h"

 

Next we need a song of some sorts to play, simply copy an appropriate file into your resources folder.  Myself I used an mp3 file named creatively enough song.mp3.

Supported Audio File Formats


The audio formats supported by Cocos2D-x depend entirely on what platform you run on.  The primary thing to be aware of is the ogg format is the preferred music format on Android platforms, while it is completely unsupported on iOS, which prefers MP3.

You should be aware that the MP3 format is patent encumbered format and generally should be avoided when possible.  If your app reaches certain sales thresholds, you may be required to pay license fees.  Sadly this generally isn’t an option on iOS devices as MP3 is the primary audio format used.  For sound effects, WAV are commonly used offering quick playback ability at the cost of file size.  Here are the details of supported audio files on iOS

Time now for some coding.  Implement the following init() method:

bool HelloWorld::init()
{
   if (!Layer::init())
      return false;

   auto audio = CocosDenshion::SimpleAudioEngine::getInstance();
   audio->preloadBackgroundMusic("song.mp3");
   audio->playBackgroundMusic("song.mp3");

   return true;
}

That is all that is required to load and play a music file. In fact the preloadBackgroundMusic() call wasn't even required so we could have used even less code. However preloading your music guarantees that you will not suffer a slow down the first time a song plays. You can also pause and resume playback of background music, or switch tracks completely, like so:

   eventListener->onKeyPressed = [audio](EventKeyboard::KeyCode keyCode, Event* event) {

      switch (keyCode) {
         case EventKeyboard::KeyCode::KEY_SPACE:
            if (audio->isBackgroundMusicPlaying())
               audio->pauseBackgroundMusic();
            else
               audio->resumeBackgroundMusic();
            break;

         case EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
            audio->playBackgroundMusic("song2.mp3");
            break;

         case EventKeyboard::KeyCode::KEY_LEFT_ARROW:
            audio->playBackgroundMusic("song.mp3");
            break;
      }
   };

   _eventDispatcher->addEventListenerWithFixedPriority(eventListener, 2);

Hitting the spacebar will toggle the playback of the currently playing song.  Hitting the right arrow will start playing (or start over if already playing) song2.mp3. Hitting the left arrow will start or re-start playback of song.mp3.  You will notice from this example that only one song can be played at a time.  Generally this isn’t a limitation as it is normal to only have one active sound track at a time. 

setBackgroundMusicVolume() doesn't work!


A bit of a warning, at least on Windows, calling setBackgroundMusicVolume() does nothing, making it impossible to change the volume of a playing music file. This may not be the case on other platforms, I did not test. It was filed as a bug a long time back and does not appear to have been addressed.

 

Now let's look at playing sound effects instead.  Playing music and effects is almost identical.  The biggest difference is that sound effects are expected to support multiple concurrent instances.  That is to say, while you can only play one song at a time, you can play multiple sound effects at once. Consider this sample:

bool HelloWorld::init()
{
   if (!Layer::init())
      return false;

   auto audio = CocosDenshion::SimpleAudioEngine::getInstance();
   
   audio->preloadEffect("gun-cocking-01.wav");
   audio->preloadEffect("gun-shot-01.wav");

   audio->playEffect("gun-cocking-01.wav");

   Director::getInstance()->getScheduler()->schedule([audio](float delta) {
      audio->playEffect("gun-gunshot-01.wav");
      audio->unloadEffect("gun-cocking-01.wav");
   }, this, 1.5f, 0, 0.0f, false, "myCallbackKey");

   return true;
}

 

In this example we preload two WAV sound effects, a gun cocking and a gun shot.  Playing a sound effect is as simple as calling playEffect() passing in the file name.  Of course, be certain to copy the appropriate sound files to your project’s resource folder before running this example.  Next this example queues up a lambda method to be called 1.5 seconds of the gun cocking sound is played to play our gun shot sound.  At this point we are done with our gun cocking effect so we unload it from memory using unloadEffect().  You can still call playEffect with that file in the future, but it will result in the file being loaded again.

 

This example might be somewhat convoluted, but it illustrates and works around a key weakness in the CocosDenshion audio library.  It is a very simple and straight forward library but if you want to do “advanced” things like detecting when a song or audio effect has ended, unfortunately this functionality is not available.  You either have to use the experimental AudioEngine, which we will cover later, or use an external audio library such as FMOD.  SimpleAudioEngine is extremely easy to use, but not very powerful, so it’s certainly a trade off.  If you just need background music and fire and forget sound effects SimpleAudioEngine should be just fine for you.

 

One final topic to cover is handling when your app is minimized or forced into the background, you most certainly want to stop audio playback.  This is thankfully easily accomplished in your AppDelegate there are a pair of methods, applicationDidEnterBackground() and applicationWillEnterForeground().  Simply add the following code:

void AppDelegate::applicationDidEnterBackground() {
   auto audio = CocosDenshion::SimpleAudioEngine::getInstance();
   audio->pauseAllEffects();
   audio->pauseBackgroundMusic();
}

void AppDelegate::applicationWillEnterForeground() {
   auto audio = CocosDenshion::SimpleAudioEngine::getInstance();
   audio->resumeAllEffects();
   audio->resumeBackgroundMusic();
}

 

This will cause all of your currently playing sound effects and music files to be paused when your application enters the background and they will all result when your application regains focus.

Programming , ,

18. November 2015

 

As part of Google’s ongoing developer conference Fun Propulsion Labs, a Google team dedicated to gaming, released the open source game Zooshi to showcase a number of just announced or updated game technologies.  Zooshy is a 3D game that runs on Android, Android TV, Windows, OSX and Linux and is currently available for free on the Google Play Store.  The source code is available on github under the Apache v2 open source license.

The technologies showcased by Zooshi include:

  • Motive – animation system
  • CORGI – an entity/component system
  • FlatUI – immediate mode lightweight GUI
  • Scene Lab – in game level editing
  • Breadboard – node based scripting
  • FPLBase – cross platform API for low level access

 

Now that’s a number of new technologies I currently know nothing about and will have to jump into in more detail shortly.

 

More details about the release are available here.

GameDev News ,

26. October 2015

 

In the previous tutorial we look at the process of using sprites in SFML.  Today we are going to look instead at using a sprite sheet or texture atlas.  The process is very similar to working with a normal sprite, except that you have multiple sprites on a single texture.  Loading and swapping textures in memory is an expensive operation, so holding multiple sprites together can greatly improve the speed of your game.

 

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

 

Many game engines have implicit support for spritesheets and sprite animation, however SFML does not.  There are however libraries built on top of SFML that provide this functionality or you can roll the required functionality yourself with relative ease.  Before we can continue we need a sprite sheet, which is simply one or more images with multiple frames of animation.  This is the one I am using:

dragonFrames

 

This isn’t the full sized image however.  The source file is actually 900x1200 pixels in size.  It should be noted that this size isn’t actually ideal.  Power of two texture dimensions should be preferred ( such as 512x256, 1024x1024, 2048x2048, etc. ).  In earlier version of OpenGL including OpenGL ES 1.x, a power of two texture was actually required.  These days, it is no longer a requirement, but a PoT texture generally will perform better.  As to file dimensions, you can fairly safely go up to 2048x2048 and support even rudimentary GPU’s like the Intel HD3000 series, but sizes of 4096x4096 are generally possible on most modern desktop and mobile GPUs.   You can notice from this image that it contains 12 textures, each 300x400 pixels in size.

 

Now we need code to extract a single frame from the texture and as you will see, it’s actually remarkably easy:

// Demonstrate creating a spritesheet
#include "SFML/Graphics.hpp"

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

  sf::Event event;
  sf::Texture texture;
  texture.loadFromFile("images/dragonFrames.png");

  sf::Sprite sprite(texture,sf::IntRect(0,0,300,400));


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

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

 

This will draw just a small rectangular portion of our source texture, representing the first frame, like so:

image

 

Really that’s all that there is to it.  To add animation, we simply change the rectangular source after the fact, like so:

// Demonstrate creating a spritesheet
#include "SFML/Graphics.hpp"

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

  sf::Event event;
  sf::Texture texture;
  texture.loadFromFile("images/dragonFrames.png");

  sf::IntRect rectSourceSprite(300, 0, 300, 400);
  sf::Sprite sprite(texture,rectSourceSprite);
  sf::Clock clock;

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

    if (clock.getElapsedTime().asSeconds() > 1.0f){
      if (rectSourceSprite.left == 600)
        rectSourceSprite.left = 0;
      else
        rectSourceSprite.left += 300;

      sprite.setTextureRect(rectSourceSprite);
      clock.restart();
    }

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

 

And when run:

GIF

 

You may notice right away that animation doesn’t look right and that’s a keen eye you’ve got there.  In this example we are simply going across the top three frames of animation from left to right.  The proper animation should actually be 0,1,2,1,0 not 0,1,2,0,1,2.  That said, in a proper game you would either roll your own animation class or use an existing one.  When we get to the process of creating a complete game, we will cover this process in detail.

 

In the above example we change frames of animation by changing the sprites source texture rect with a call to setTextureRect().  As I mentioned in the previous tutorial you could actually generate a new sprite per frame if preferred, as the sf::Sprite class is very light weight.

 

The Video

Programming , , ,

20. October 2015

 

In the previous tutorial we covered the basics of using graphics in SFML.  Chances are however your game isn’t going to be composed of simple shapes, but instead made up of many sprites.  That is exactly what we are going to cover today.

 

As always, there is an HD version of this tutorial available here

 

First off, we should start by defining what exactly a Sprite is.  In the early days of computers, sprite had special meaning as there was literally sprite hardware built into early 8bit computers.  A sprite is basically an image on screen that can move.  That’s it.   In SFML this relationship is easily demonstrated by it’s class hierarchy.

 

image

 

There is one very key concept to understand with sprites however.  A sprite in SFML represents and image or texture on screen that can be moved around.  However, it does not own the texture or image!  This makes the Sprite class fairly light weight, which certainly isn’t true about Texture or Image, the classes that actually contain all the data in the image.  Perhaps it’s easiest to start with a simple demonstration.

 

First we need an image to work with.  I am using a dragon sprite from the recent Humble Indie Gamedev Bundle.  The image looks like so:

dragonBig

 

Obviously you can use whatever image you want, just be sure to copy it into the working directory of your application.  In Visual Studio, the working directory can be located in the project’s properties panel under Debugging called Working Directory:

image

 

The image can be any of the following formats: bmp, hdr, gif, jpg, png, pic, psd, tga.  Keep in mind, not all formats are created equal.  Bitmap for example does not support transparency encoding and are generally quite large, but lose no image details and are simple to work with.  Gif has some patent issues and should generally be avoided.  Png seems like genuinely a good mix between features, size and quality and is well supported by content creation tools.

 

Ok, enough setup, let’s get to some code.

// Demonstrate sprite drawing in SFML
#include "SFML/Graphics.hpp"

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

  sf::Event event;

  sf::Texture texture;
  texture.loadFromFile("images/dragonBig.png");

  sf::Sprite sprite(texture);

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

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

 

And when you run that:

image

 

As you can see, the experience is remarkably consistent to drawing using graphics primitives.  The big difference here is that we create our Sprite by providing a texture, which in turn we loaded from file with a call to Texture::loadFromFile().  There exist methods to load from stream or memory if preferred.  It is again important to remember that the Sprite does not own the Texture.  This means if the texture goes out of scope before the Sprite, the sprite will draw a blank rectangle.  This also means that several sprites can use the same texture.

 

Now you may have noticed that in addition to sf::Texture, there is a class called sf::Image and you may be wondering why.  There is one very simple difference at play here.  A Texture resides in the memory of your graphics card, while an image resides in system memory.  The act of copying an image from system memory to the GPU is quite expensive, so for performance reasons you almost certainly want to use Texture.  That said, Texture isn’t easily modified, so if you are working on a dynamic texture or say, creating a screen shot, Image is the better choice.  There exist methods to switch between the two types, but they are also fairly heavy in performance, so do not do them on a frame by frame basis.  At the end of the day

 

Let’s take a quick look at creating a dynamic image next.  Not something you are going to do often for most games granted, but it makes sense to mention it now.

// Demonstrate creating an Image
#include "SFML/Graphics.hpp"

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

  sf::Event event;

  sf::Image image;
  image.create(640, 480, sf::Color::Black);
  
  bool isBlackPixel = false;
  sf::Color blackPixel(0,0,0,255);
  sf::Color whitePixel(255, 255, 255, 255);

  //Loop through each vertical row of the image
  for (int y = 0; y < 480; y++){
    //then horizontal, setting pixels to black or white in blocks of 8
    for (int x = 0; x < 640; x++){


      if (isBlackPixel)
        image.setPixel(x, y, blackPixel);
      else
        image.setPixel(x, y, whitePixel);
      // Every 8th flip colour
      if (!(x % 8))
        isBlackPixel = !isBlackPixel;
    }
    // Offset again on vertical lines to create a checkerboard effect
    if(!(y%8))
      isBlackPixel = !isBlackPixel;
  }

  sf::Texture texture;
  texture.loadFromImage(image);
  sf::Sprite sprite(texture);

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

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

 

When you run this example you should see:

image

 

Here you can see we can modify the pixels directly in our sf::Image.  However to display it on screen we still need to move it to texture and populate a sprite.  The difference is direct access to the pixel data.  Another important capability of sf::Image is the method saveToFile which enables you to well, save to file.  Obviously useful for creating screenshots and similar tasks.

 

You may notice depending on the resolution or composition of your source image that you texture may not look exactly like your source image.  This is because there is a smoothing or antialiasing filter built in to SFML to make images look smoother.  If you do not want this, perhaps going for that chunky 8bit look, you can turn it off with a call to setSmooth(false);

 

That is all we are going to cover today.  In the next tutorial part we will take a look at spritesheets, so we can have multiple different sprites in a single source image.

 

The Video

 

Programming , , ,

Month List

DisqusCommentsSummary

Course-specific creative-The Complete iOS 9 Developer Course - Build 18 Apps