Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon
27. September 2017


Aseprite, a pixel based drawing and animation app, just released version 1.2.  New features include pixel aspect ratios, gradients, reference layers and more.  There were also several bug fixes and improvements.


From the release blog post:


Aseprite v1.2 is finally the new stable version (*). If you were already using the beta version, you will not notice substantial changes. But if you were using Aseprite v1.1.13, there are a lot of new features for you (like pixel aspect ratio, layer groups, overlapping frame tags, gradients, reference layers, etc.)

This is a list of the changes from v1.2-beta12 to the final v1.2:

  • Added new Addition, Subtract, Divide blending modes
  • Added support to change theme and UI scaling without restarting (#471)
  • Disable transformation handles in the selection when a Shift or Shift+Alt are pressed by default (reported here)
  • Fixed high CPU usage on Timeline when we copy layers/frames/cels (bug report)
  • Fixed snap to grid bug with selection tool
  • Fixed crash closing all files & opening a new one when preview window was playing an animation
  • Windows: New x64 version (included in the installer and on Steam, it’ll install the x64 version on x64 machines)
  • Windows: New --disable-wintab option to avoid loading wintab32.dll
  • Removed Windows XP support (Please contact us in case that you still need a previous version with Windows XP support.)
  • macOS: Use the native macOS menu bar (#135)
  • macOS: Now ⌘M and ⌘H will Minimize and Hide the window respectively. Use Ctrl+M for Color Curves, and Ctrl+H to change View > Show Extras options.
  • macOS: Fixed bug setting broken mouse cursors in some special cases
  • macOS: Retina support (#903)
  • Fixed other bugs (including #1569, and #1423 thanks to @cebolan)

Several new features were delayed just to create a more stable v1.2 version. So sorry for everybody that don’t get what they asked for :’( Soon I’ll release the first v1.3-beta1 with some crazy new stuff, so stay tuned.


We took a look at Aseprite in action in this video should you wish to learn more.

GameDev News Art


26. September 2017


Do you find that 8/16-bit games aren’t retro enough?  Yearning for an even earlier art start?  Well then, do I have the perfect software for you!  RexPaint, an ANSI painting package.  So, how exactly does it work?  Well just like any other paint package frankly, except instead of drawing with pixels or voxels, you using ASCII characters.  RexPaint supports many of the features you would expect from a modern art package, multiple drawing tools, palette tools, layer support etc.  The end result can then be exported as a PNG or in several text formats.


To see RexPaint in action, be sure to watch the video below.  Oh, and it’s completely free.

Art


6. June 2017


There are several game engines out there that present a code free option such as Stencyl and Construct.  Today we are looking at an open source alternative, GDevelop.  It is a cross platform, open source 2D game engine with a visual programming interface that requires no previous experience.  However there is also the ability to extend the engine using the C++ programming language if desired.  If you are new to the Closer Look series, it is a combination of game engine review and getting started tutorial helping you decide if a game engine is right for you.


As always, there is a video version of this tutorial available here and embedded below.


Without further ado, let’s jump into GDevelop.


Meet GDevelop

As mentioned above, GDevelop is an open source 2D game engine.  It is released under the MIT license for the core engine, while the editor is available under the GPL v3 open source license.  The code is available on Github.

Of course you don’t ever have to touch the source code to work with GDevelop.  You can download binaries for Windows, Mac, Linux as well as Browsers, iOS and Android in the form of GDevApp.  I will not be covering GDevApp today however.  GDevelop is able to compile native applications, HTML5 pages as well as Android applications, which is currently an experimental feature.

The vast majority of your time is going to be spent in the GDevelop editor, shown below.

image

The center of the screen is currently showing the Scene editor.  There is where you can compose scenes.  It is a tabbed view that can contain multiple open scenes as well as Events, the programming model of GDevelop, which we will discuss more shortly.

On the right hand side is the Objects Editor, which contain the building blocks of your game.  On the left hand side is the Project Manager containing the assets and scenes that make up your game.


Let’s walk through creating a sprite in a game.  In the Objects editor, right click objects and select Add an object.

image

This will show us a list of possible objects:

image


For every object except the Sprite you need to enable it before you can use it (thus why they are grayed out).  It’s as simple as double clicking a grayed out object to enable it however, like so:

image


In this case however we are going to use the Sprite object, which is already enabled.  Simply double click Sprite.  Double clicking the newly created object in the Object editor will open up the sprite editor screen:

image


At the top right corner of the editor window you will see the Images bank’s editor, click the plus icon and add the images you will use for your sprite.  Next drag the selected images down to the images section, like so:

GIF


You can rename and configure the animation (if any) under the Animations panel.

image


Now you can create an instance of your Sprite object by simply dragging it into the scene.

GIF2


As we saw earlier, there are several built in objects in addition to the Sprite object, including Admob integration, a Text object, a tiled sprite (spritesheet), etc.   Next lets move on to adding some logic to our newly created object.


Scripting in GDevelop

Logic in GDevelop are implemented using Events.  Let’s look at an example of moving the sprite around when the mouse moves.  Click on the Events tab.

image


In the Events ribbon, click Add an Event:

image


In this case we have no conditions, we want this to happen every single frame.  Hover over No actions, then select Add an Action.

image


This is where the building block aspect of GDevelop programming comes into play.  Select All Objects->Position->Position of an object.

image


Now we can set the parameters for positioning our object.  First select the object to modify, then set each parameter.  In this case we set the X and Y values to those of the mouse cursor, like so:

GIF3


Upon completion, you will see we now have an event defined:

image


In this particular case we have no condition, so our event will fire every pass through the event loop.  We could however have set a condition which causes our event to fire or not.  Here for example is a condition that will start playing some music once the scene is loaded.

image


Beyond conditions, there are other control structures you can add to events:

image


Link enables you to break link to another event sheet, enabling you to modularize your code.  It is also possible to define variables, both globally, to the scene and at the object level.  For example, right click the Project and select Modify Global Variables.

image


This now enables us to define new variables:

image


This can also be done at the object level, right click an object and select Other Properties.  Then in the resulting panel select Click to Edit...

image


While we are here, notice the Behaviors option?  This enables us to add new functionality to game objects.  Click the Add... button:

image


You will notice once again, by default all behaviors are disabled.  Double click a behavior to add it in.  Let’s go ahead and add Top-down movement as an example.  You can now edit properties of the new behavior in the same dialog:

image


This will instantly add arrow key navigation abilities to your object.  When you play your game, arrow keys will cause your object to move around screen.  Speaking of playing your game, hit the Preview button in the Scene ribbon to launch your game in your browser.

image


You can control application level settings of your project by right clicking your project and selecting Edit the property of the game.

image


This will bring up the next dialog.

image


Finally, if your project has Native extensions enabled, under the File menu you have the option to build a native version of your application.

image


Then simply click the Compile button.

image



Documentation and Community

GDevelop is reasonably well documented, with a Getting Started tutorial, several other tutorials and a decent number of starter templates to choose from.

image 


There is also a manual available online.  If you are intending to extend GDevelop using C++ however, the documentation is almost non-existent.  However being an open source project, all of the code is available.  All of the behaviors and objects we used in this example are available in source form on Github in the extensions folder:

image


GDevelop has a dedicated forum available here.  It is reasonably active with a decent sized community.  Forums are available in both English and French.


Conclusion

If open source, free and a visual programming interface are important to you, GDevelop is definitely an engine to consider.  The documentation is adequate, the engine is mostly feature complete, although annoyingly some features such as Tiled support are only available for native targets.  The entire thing is designed around extensibility and if you are willing to dive into C++, the sky’s the limit on what you can do.  My biggest complaint is a lack of polish on the UI layer, experiencing a few crashes, some UI glitches that went away on a reload and some buttons that simply do nothing.  Most annoyingly, the engine is basically unusable on a high DPI display.

It is however an easy engine to jump into and use if you are willing to deal with some UI warts.  An MIT license around the core engine is always an excellent feature.


The Video

Programming


8. May 2017

 

Ever needed to loop a background forever in your 2D game and wondered the best way to do it?  That’s exactly what we are going to look at today, with all the code samples done using HaxeFlixel, which I recently covered in this tutorial series if you wish to learn more.  One key aspect is to have a background that is seamless.  That is the ending edge and beginning edge need to blend seamlessly together.  For this example I am using this graphic (click for the full resolution version).

BloodRed

 

There are two approaches we are going to cover today.  The first one is the simplest, essentially we update our camera when we get within half a screens height of the edge and loop it to the bottom, like so:

CameraLoop0001-0060

 

Let’s take a look at the code.

import flixel.FlxG;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.FlxObject;

class PlayState extends FlxState
{
   var bg:FlxSprite;
   var camTarget:FlxObject;
   override public function create():Void
   {
      super.create();
      bg = new FlxSprite(0,0,AssetPaths.BloodRed__png);
   
      add(bg);

      camTarget = new FlxObject();
      camTarget.setPosition(FlxG.width/2, FlxG.height/2);
      FlxG.camera.target = camTarget;

      add(camTarget);
   }

   override public function update(elapsed:Float):Void
   {
      super.update(elapsed);
      camTarget.y+=25;

      // Move the camera to loop forever  
      if(camTarget.y >  bg.height - FlxG.height/2){
         camTarget.setPosition(FlxG.width/2, FlxG.height/2);
      }
   }
}

 

The downside to this approach is you also need to reset the Y coordinate of all the entities in your scene as your camera resets.

Another option is to use two instances of the background and as you approach the edge you raise the lower most version to the top and repeat forever.  Like so:

CameraLoop20001-0060

 

Here is the code for this approach.

import flixel.FlxG;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.FlxObject;

class PlayState extends FlxState
{
   var bg:FlxSprite;
   var bg2:FlxSprite;
   var camTarget:FlxObject;
   override public function create():Void
   {
      super.create();
      bg = new FlxSprite(0,0,AssetPaths.BloodRed__png);
      bg2 = new FlxSprite(0,bg.height,AssetPaths.BloodRed__png);
   
      add(bg);
      add(bg2);

      camTarget = new FlxObject();
      camTarget.setPosition(FlxG.width/2, FlxG.height/2);
      FlxG.camera.target = camTarget;

      add(camTarget);
   }

   override public function update(elapsed:Float):Void
   {
      super.update(elapsed);
      camTarget.y+=25;

      var greater,lesser;
      if(bg.y > bg2.y){
         greater = bg;
         lesser = bg2;
      }
      else{
         greater = bg2;
         lesser = bg;
      }
      if(camTarget.y > greater.y + bg.height - FlxG.height/2){
         trace("Flip");
         lesser.y = greater.y + bg.height;
      }

   }
}

 

This approach has the advantage of enabling you to keep coordinates consistent, but has the downside of requiring a second identical sprite.  Since the second sprite is simply an instance of the same texture though, the memory impact should be almost non-existent.

Programming


26. April 2017

 

Welcome back to our ongoing HaxeFlixel Tutorial Series, today we are going to cover playing sound and music in HaxeFlixel.  This title is a bit misleading, as they are both basically the same thing, they are all ultimately FlxSound objects.  The single biggest challenge you are going to have with HaxeFlixel audio is file formats, so let’s start there. 

The file format of your audio file depends entirely on the platform your code is going to run on.  On the Flash player platform, all of your audio files need to be in mp3 format.  However on other platforms the mp3 file format has a number of licensing issues, so they instead use Ogg Vorbis (ogg) files for long audio files, and WAV for shorter effects.  Why two different formats?  WAV files are much faster to load, but take up more system memory.  They are ideal for frequently used but shorter sound files.  Ogg files on the other hand are much more compressed, taking more CPU power to process but a great deal less space.  This makes them ideal for longer audio files, such as your game’s music.  In addition to the file format limitations, your sounds need to be encoded at 11025, 22050 or 44100kHz frequency.  If you need to switch encoding frequencies, Audacity is a great free program (you can learn more about here) that can also be used to convert between the various file formats.

Using a default project, HaxeFlixel will automatically create sound and music folders in your asset directory.  One thing you will notice in this example is when you start including multiple different audio files for different platforms, the warnings can become extremely irritating.  Hearing that your mp3 file isn't compatible with your platform, or that your WAV file wont work on Flash gets irritating quickly.  Thankfully we have the ability to filter our files based on platform.  In your Project.xml file, locate the Path Settings area and edit it like so:

   <!-- _____________________________ Path Settings ____________________________ -->

   <set name="BUILD_DIR" value="export" />
   <classpath name="source" />
   <!-- <assets path="assets" /> -->
   <assets path="assets/music" include="*.mp3" if="flash" />
   <assets path="assets/music" include="*.ogg|*.wav" unless="flash" />
   <assets path="assets/sounds" include="*.mp3" if="flash" />
   <assets path="assets/sounds" include="*.ogg|*.wav" unless="flash" />

This will cause Flash builds to only see mp3 files from the music and sound directories, while all other platforms will only see the ogg and wav format files.  Ok, now lets move on to some actual code.

Playing music and sound effects is trivial in HaxeFlixel, but once again platform becomes a factor.  In this case we are using conditional compilation to solve this problem, like so:

#if flash
   FlxG.sound.playMusic(AssetPaths.techno__mp3);   
   soundEffect = FlxG.sound.load(AssetPaths.gunshot__mp3);
#else
   FlxG.sound.playMusic(AssetPaths.techno__ogg);
   soundEffect = FlxG.sound.load(AssetPaths.gunshot__wav);  
#end

 

In this case the music file will play automatically, while the soundEffect needs to be triggered manually.  Let’s take a look at how to do that in our update() method.

if(FlxG.keys.justPressed.G)
   soundEffect.play(true);

The true parameter causes the sound effect to replace any running instances.  This will result in the sound starting from the beginning if you press the G key multiple times before a sound effect has finished playing. 

You also have a fair bit of control over sound playback.  The following code shows how to pause/resume sound as well as increasing and decreasing the volume.  Volume is a value that ranges from 0.0 to 1.0, with 0.0 being complete silence while 1.0 is maximum volume.

if(FlxG.keys.justPressed.P)
   if(FlxG.sound.music.active)
      FlxG.sound.music.pause();
   else
      FlxG.sound.music.resume();
if(FlxG.keys.justPressed.PLUS)
   FlxG.sound.changeVolume(0.1);
if(FlxG.keys.justPressed.MINUS)
   FlxG.sound.changeVolume(-0.1);

 

HaxeFlixel also supports positional audio.  Both by changing the X and Y position of a sound effect, or positioning it relative to another object.  The latter is the approach we are going to take here, creating a virtual ear that is centered to the screen.

soundX = FlxG.width/2;  
soundY = FlxG.height/2;
ear = new FlxObject();
ear.setPosition(FlxG.width/2, FlxG.height/2);   

Now we can relocate the sound relative to the ear and it will change accordingly.

 

There is also

if(FlxG.keys.justPressed.LEFT)
   soundX -= 25;
if(FlxG.keys.justPressed.RIGHT)
   soundX += 25;        
if(FlxG.keys.justPressed.UP)
   soundY -= 25;
if(FlxG.keys.justPressed.DOWN)
   soundY += 25;                 
FlxG.sound.music.proximity(soundX,soundY, ear,300,true);

It is also possible to tween audio, fading it in and out over time, like so:

if(FlxG.keys.justPressed.S)
   FlxG.sound.music.fadeOut(3.0);

You can also set up callback functions when a sound stops playing.  This can be used to easily create a music or sound effect management system.

FlxG.sound.music.onComplete = function() {
   // This will only ever fire if you hit L to turn looping off
   trace("Song ended");
}

 

Now let’s show the complete source listing, which also illustrates a couple other features such as looping, muting and pausing audio.

package;

import flixel.FlxG;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.system.FlxSound;
import flixel.FlxObject;

class PlayState extends FlxState
{
   var soundEffect:FlxSound;
   var soundX:Float;
   var soundY:Float;
   var ear:FlxObject;

   override public function create():Void
   {
      super.create();
      #if flash
         FlxG.sound.playMusic(AssetPaths.techno__mp3);   
         soundEffect = FlxG.sound.load(AssetPaths.gunshot__mp3);
      #else
         FlxG.sound.playMusic(AssetPaths.techno__ogg);
         soundEffect = FlxG.sound.load(AssetPaths.gunshot__wav);  
      #end

         soundX = FlxG.width/2;  
         soundY = FlxG.height/2;
         ear = new FlxObject();
         ear.setPosition(FlxG.width/2, FlxG.height/2);   

      FlxG.sound.music.onComplete = function() {
         // This will only ever fire if you hit L to turn looping off
         trace("Song ended");
      }

      FlxG.sound.muted = true;
   }

   override public function update(elapsed:Float):Void
   {
      super.update(elapsed);

if(FlxG.keys.justPressed.G)
   soundEffect.play(true);

      if(FlxG.keys.justPressed.P)
         if(FlxG.sound.music.active)
            FlxG.sound.music.pause();
         else
            FlxG.sound.music.resume();
      if(FlxG.keys.justPressed.PLUS)
         FlxG.sound.changeVolume(0.1);
      if(FlxG.keys.justPressed.MINUS)
         FlxG.sound.changeVolume(-0.1);

      if(FlxG.keys.justPressed.LEFT)
         soundX -= 25;
      if(FlxG.keys.justPressed.RIGHT)
         soundX += 25;        
      if(FlxG.keys.justPressed.UP)
         soundY -= 25;
      if(FlxG.keys.justPressed.DOWN)
         soundY += 25;                 
      FlxG.sound.music.proximity(soundX,soundY, ear,300,true);

      
      if(FlxG.keys.justPressed.L)
         FlxG.sound.music.looped = false;

      if(FlxG.keys.justPressed.S)
         FlxG.sound.music.fadeOut(3.0);

      if(FlxG.keys.justPressed.M)
         FlxG.sound.muted = !FlxG.sound.muted;
   }
}

 

The Video

Programming


GFS On YouTube

See More Tutorials on DevGa.me!

Month List