Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon

20. March 2017

 

In this tutorial in our ongoing HaxeFlixel tutorial series we are going to look at using Sprites in HaxeFlixel.  Sprites are fundamental to HaxeFlixel development and can be simply thought of as a graphic that can move.  We are going to look at a couple different examples, one procedurally creating the graphic to draw, while the other loads the sprite from an image.  We are also going to quickly take a look at how we can move our sprite around the screen.  If you were curious, the term Sprite was coined by Texas Instruments for one of their early graphics chips.  The reason the term Sprite was chosen according to Wikipedia:

The term was derived from the fact that sprites, rather than being part of the bitmap data in the framebuffer, instead "floated" around on top without affecting the data in the framebuffer below, much like a ghost or "sprite". By this time, sprites had advanced to the point where complete two-dimensional shapes could be moved around the screen horizontally and vertically with minimal software overhead.

It was common in the early days of consoles and graphics cards to have dedicated hardware for drawing sprites (non-stationary images) and the number of supported sprites was a key selling feature for computers and consoles.  In HaxeFlixel, Sprite is actually a very important class, the FlxSprite.  Behind the scenes there is no special hardware for drawing sprites anymore, in fact a sprite is ultimately a 3D object that is parallel with the camera, but the terminology has stuck.  Ok, enough history, let’s actually jump in with some code.

 

In this first example, we are simply going to create a FlxSprite programmatically.

package;

import flixel.FlxSprite;
import flixel.FlxState;

class PlayState extends FlxState
{
   var sprite:FlxSprite;
   override public function create():Void
   {
      super.create();
      sprite = new FlxSprite();
      sprite.makeGraphic(300,300,flixel.util.FlxColor.WHITE);
      for(y in 0...300){
         for(x in 0...300){
            if(x%2 == 1 && y%2 == 1)
               sprite.pixels.setPixel(x,y,0x0000ff);
            if(x < 5 || y < 5 || x > 295 || y > 295 )
               sprite.pixels.setPixel(x,y,0xffffff);
         }
      }
      add(sprite);
   }

   override public function update(elapsed:Float):Void
   {
      super.update(elapsed);
      sprite.x += elapsed * 100;
   }
}

When we run this code we should see:

image

 

As the program runs the sprite will slowly advance to the right until it is off the screen.  Let’s just in and figure out exactly what is happening here. 

First thing to notice is the base class of our sprite is FlxSprite.  We allocate a new one then call it’s makeGraphic() method.  This gives us a 2D image to work with, in this case one that’s 300 pixels wide by 300 pixels high and filled with the colour WHITE.  As you can see HaxeFlixel has a handy utility class containing the numeric value of several of the most common colours available in flixel.util.FlxColor.

Now that we have a 300x300 white canvas to play with we simply loop over all the available pixels in the graphic, looping row by row, then through each pixel in that row.  We can then directly set the color value of a given pixel by accessing the setPixel() method of the pixel member of FlxSprite.  The parameters are the x and y location of the pixel within the graphic, relative to the top left corner, as well as the color to set it.  Notice in this example instead of using a predefined colour (which we could have if we preferred) we instead us a hexadecimal encoded number.  If you’ve ever done any HTML coding, this color scheme should be immeidately familiar.  If not each two digits represents first the red, then green, then blue component of the color from 0 to 255 ( or 0 to ff in hexidecimal).  So in this case we set every other pixel of blue ( no red, no green, full blue == 0x0000ff ).  We also have another check to see if we are within 5 pixels of the image edge and if so, draw the pixels in white.  This causes a 5 pixel wide border to appear around our image.

After creating our simple white bordered checkboard image you will notice a call to add().  This call is EXTREMELY important, as it adds the FlxSprite to the object collection of our FlxState derived class PlayState.  Being in this collection will cause the sprite to automatically be drawn and updated each pass through the game engines main loop.  Speaking of updating, notice we have also overridden the update method.  This is called every pass through the game loop and is where you should update the logic of your game world.  In this case we simply increase the x value of our sprite by elapsed * 100.

So... why did we do this?  What exactly are we saying with the line:

sprite.x += elapsed * 100;

This is actually a really common tactic in game development.  One of the challenge of creating games is getting them to run the same speed on various different computers.  If you are running a fixed game rate loop, say a game running at 60fps, and it never runs below that rate, it’s not a problem, you know how fast things are going to update.  However on faster or slower computers this is trickier to determine.  This is why elapsed is so important.  This is a value passed in to the update() function each pass through the game loop and it tells our game how long has elapsed in seconds since the last pass through the game loop.  You can then multiply this value by the amount you want to move by to get a consistent update regardless to the machine you are running on.

For example, if your game was running at 10 frames per second, the value of elapsed will be 0.1.  So to hit our target of 100 pixels per second, this means in updates we will move by 100 * 0.1 or 10 pixels.  However if we were running at 60 fps instead of 10fps, the value of elapsed will instead be 1/60 or 0.016.  So to hit our target of 100pixels per second we update instead by 0.016 * 100 or 1.66 pixels.  Over the course of a second, regardless to framerates, the sprite will be updated by the same total amount.

Before we move on it’s important to know the process of working directly with each pixel in a sprite like we just did is an extremely costly process!  This is the kind of task you want to perform very occasionally, not every frame!

Next, instead of creating an ugly graphic programmatically, lets load a sprite from an image file.  Let’s jump straight into the code.

package;

import flixel.FlxG;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.tweens.FlxTween;

class PlayState extends FlxState
{

   var sprite:FlxSprite;
   override public function create():Void
   {
      super.create();
      sprite = new FlxSprite();
      sprite.loadGraphic(AssetPaths.enemy__png);
      sprite.x = 100;
      sprite.y = 0;
      add(sprite);

      FlxTween.tween(sprite, { x: FlxG.width - sprite.width, 
                         y: FlxG.height - sprite.height, 
                         angle : 360.0 }, 5, { type:FlxTween.PINGPONG });
   }

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

Now when we run the code, we see:

GIF

 

Notice in this case that our sprite is still a FlxSprite, although instead of creating it from scratch using makeGraphic() we load if from file using loadGraphic passing in the value AssetPaths.enemy__png.  In this case enemy.png is the name of the image we are using for our sprite.  If yours has a different filename, this value will change.  A bit of a note on the image, I added it to the directory assets/images that was automatically created when we created our project.

image

 

As we add new assets to these folders, Haxe is smart enough to automatically create a reference to it for us.  This is a handy feature of the Haxe language and is invoked by this code in AssetPaths.hx:

package;

@:build(flixel.system.FlxAssets.buildFileReferences("assets", true))
class AssetPaths {}

Throwing any applicable asset in the assets directory will automatically generate file references that we can then use in code, like so:

image

 

Very cool.  Behind the scenes loadGraphic is actually doing a lot more than you might think.  In addition to loading the file into memory, it’s actually caching it.  This means that if other code loads the same asset it will get the version from cache instead of creating yet another version.  This improves performance and reduces memory usage.

So now that we have our sprite loaded from an image we set it’s initial x position to 100 pixels.  Notice that graphics are drawn relative to their top left corner and the top left corner of the applications window.  So an image with x = 100 and y = 0 is drawn starting at it’s top left corner 100 pixels right of the top left corner of the window and 0 pixels down from the very top of the application window. 

The final detail of this example is the use of a Tween, called via FlxTween.tween().  FlxTween is another cool way of handling updating your game objects, but it takes care of the timing and calculations for us.  Instead of moving our sprite each pass through the game loop via update() like we did earlier, we simply fire off a Tween and it takes care of things for us.  Tween comes from  “In-Between” and basically it’s a function that you give an end goal and a timeline and it figures out all the in-between calculations required.  In this case we are saying “take this sprite, move it to the bottom corner of the screen, rotating 360 degrees over a period of 5 seconds” and HaxeFlixel figures out how much it needs to move each frame and does it for us.  The final parameter we are saying we want to ping pong the tween, which is to say repeat it, but in reverse forever.  There is a ton more we can do with Tweens and we will cover them in more detail later.

 

That’s it for sprites for now, but there is a lot more we will cover later including texture atlases, animations and more, stay tuned!

 

The Video

Programming , , ,

17. March 2017

 

Now that we have covered getting your development environment up and running, we are going to jump into our first HaxeFlixel application.  Let’s start from the very beginning and create a new application.  As mentioned in the Getting Started tutorial, we can create an application using the simple command:

flixel tpl –n “HelloWorld”

This creates a directory with a skeleton application to get us started.  It actually creates a bit more code then we need, we are going to strip it down to just two source files.

image

 

It is pretty much tradition to make your first program a simple Hello World application, so that is what we are going to do.  We will simply print the text “Hello World” on screen, but since this is ultimately a game we are creating here, we will also animate it!  Ok, code time, let’s start with Main.hx, the entry point of our application.  Here is the source code:

import flixel.FlxGame;
import openfl.display.Sprite;

class Main extends Sprite
{
   public function new()
   {
      super();
      addChild(new FlxGame(0, 0, GameState));
   }
}

 

One thing that might immediately seem awkward is that our Main class inherits from Sprite.  This is a throwback to the Flash development world, just think of a Sprite as “something that is visible on screen”.  When our Main object is created it’s constructor is called and really it does just one thing, creates a new FlxGame object passing our GameState class in as a parameter.  The first two parameters to the FlxGame constructor are the width and height of our game window.  In this case we didn’t specify a value, meaning the value from the Project.xml file will be used instead.  If you look at Project.XML (which was generated for you) you will see the lines:

   <!-- ____________________________ Window Settings ___________________________ -->

   <!--These window settings apply to all targets-->
   <window width="640" height="480" fps="60" background="#000000" hardware="true" vsync="true" />

   <!--HTML5-specific-->
   <window if="html5" resizable="false" />

   <!--Desktop-specific-->
   <window if="desktop" orientation="landscape" fullscreen="false" resizable="true" />

   <!--Mobile-specific-->
   <window if="mobile" orientation="landscape" fullscreen="true" width="0" height="0" />

Due to this configuration by default our application will have a resolution of 640x480, while on mobile devices we will instead use the full screen.  As you can see it’s possible to set multiple definitions using the if=”platform” conditional.  If you want to have FlxGame create a larger or smaller window you can either specify the value when creating your FlxGame object, or you can change it’s value in the <window> tag.  Ok, back to our code...

As mentioned earlier, we created a FlxGame object, which is the heart of your application and contains the game loop.  Every single game or game engine has a game loop in some form, it’s essentially a loop that runs over and over until your game is done and is responsible for polling input, updating the world and drawing graphics on screen.  We don’t actually use FlxGame directly however, our game is instead broken into multiple states.  We see this in action in GameState.hx, here is the source:

import flixel.FlxG;
import flixel.FlxState;
import flixel.text.FlxText;
import flixel.util.FlxColor;

class GameState extends FlxState
{
   var text:FlxText; 
   override public function create():Void
   {
      super.create();
      text = new FlxText(0,0,FlxG.width,"Hello World",64);
      text.setFormat(null,64,FlxColor.RED,FlxTextAlign.CENTER);
      add(text);
   }

   override public function update(elapsed:Float):Void
   {
      super.update(elapsed);
      text.y ++;
      if ( text.y > FlxG.height)
         text.y = 0 - 64;
   }
}

This is the meat of our application.  You will notice that GameState inherits from FlxState.  FlxState is a very important concept in HaxeFlixel development.  Essentially you break your game logic up into a number of different states, how exactly you do do this is up to you.  A common division might be  Title Screen State, Game Playing State, High Score State, Game Over State for example.  Another option is to break your game up into screens, so instead have it look something like Splash Screen State, Main Menu State, Game Playing State, Game Credits State, etc.  Or alternatively you could break your game into levels such as Main Menu, Level One, Level Two, etc.  Really it comes down to whatever fits the structure of your application the best.  Just keep in mind that FlxState are the logical units for breaking down gameplay complexity into manageable pieces and if you hate the idea completely, no problems, you can just throw everything together into a single state if you prefer.

At the end of the day though, the FlxState is a pretty simple data structure with two primary tasks.  First, it contains all the “stuff” that makes up that portion of your game.  In this particular example that “stuff” consists of a single FlxText node, but it could contain dozens or thousands of objects.  Just realize when we call the add() method, we are adding to a collection of Objects contained in the FlxState class.  The second important part of FlxState is to provide a number of callback methods that FlxGame can call.  As I said earlier, FlxGame contains our main game loop.  Each pass through this loop however it calls a series of functions on the currently active FlxState, the most important of which are draw() and update().  It is through these two callbacks that your FlxState derived class is modified over time.  Let’s look back at our example and walk through the code.

First in our create() method, we call our parents constructor so we are properly set up and configured.  We then create a new FlxText object, which is a special sprite (aka, something visible on screen) object for displaying text.  In this case we display the string “Hello World” at 32px height in the default font.  Notice we used a call to FlxG to get the width of the screen.  FlxG is a special global helper class containing handy information such as width and height of the screen, the default camera, access to input and more.  You can also get read only access to the FlxGame class we created earlier.  Once we create our FlxText object, we format the text so it’s aligned in the center and drawn in red.  Next we call the add() method, adding the text object to the GameState.  Once added it will automatically be drawn every frame unless disabled.

Next we implement the update() method.  As mentioned earlier, this is a callback function that is going to be called by FlxGame every pass through the game loop.  The one parameter it receives is a Float with the amount of time that elapsed since the last pass through the game loop.  This is extremely handy as it enables us to determine just how fast our game is running.  In this particular case all we do is update the text object’s y coordinate ( we will talk more about coordinates shortly, don’t worry ) scrolling until our text is off screen, at which case we go back to the top and start all over.  Please note that this particular code will run at different speeds depending on how fact the device it runs on is!  We will look at ways to make the code run at the same speed on all machines in a future tutorial.  For now, when you run this code you should see:

Hello

 

In the next tutorial we will dive a bit deeper into drawing graphics on screen.

 

The Video

Programming , , ,

15. March 2017

 

There is no requirement to use Visual Studio Code when developing in Haxe, it is however the editor I will be using for this series.  If you would prefer to use HaxeDevelop, be sure to check this earlier tutorial on how to get up and running.  There are several other editor options available with varying levels of Haxe language support.

 

First things first, we need to install Visual Studio Code, you can download it here.

image

 

The install process is pretty straight forward, run the installer and chose the defaults and you should be fine.  Once installed run Visual Studio Code.

 

Now we need to add Haxe language support.  Click the extensions tab, filter on “haxe” and click the install button for “Haxe -- Haxe language support”.

image

 

Once installed it will prompt you to reload Visual Studio Code.  Do so.

image

 

If you haven’t already, create a project.  Instructions for doing so are available here.  Projects are folder based in Visual Studio Code.  To load your project either switch to the project directory from the commandline and type “code .” or load Visual Studio Code and select File->Open Folder.

image

 

Now you can run your game using Ctrl (Or Cmd) + Shift + P to bring up the command palette.  Now enter run task, like so:

image

 

Next pick the target platform you want to build for:

image

 

And TADA, your running application, assuming everything worked right:

image

 

If an error occurred, it will be show in the Problems panel:

image

 

Granted this process is a bit of a pain in the backside.  Thankfully there is a short cut for building and running the default build.  Simply hit Ctrl + Shift + B and it will compile for the default platform.  So… what is the default platform?  That would be Flash.  This of course means you have to have a Flash player installed.  Thankfully you can download one here.

 

What do you do if you want to change the default platform?  It’s a simple enough task, simply locate the file tasks.json in the .vscode folder.  Next locate the line “isBuildCommand”:true, and make sure this is copied to the entry you want to be the default build.  Like Highlanders, there can be only one, so be sure to erase it from the default “flash debug” task.

image

 

The Video

Programming , ,

13. March 2017

 

Welcome to our tutorial series on creating games using Haxe and HaxeFlixel.  This particular tutorial is going to cover setting up your Haxe development environment, installing and configuring HaxeFlixel and finally creating your first simple game.  Throughout this series I will be using Visual Studio Code as my editor, you can learn more about setting up Visual Studio Code for Haxe development here.

 

First we need to install the Haxe toolchain.  First head on over to the Haxe download page and pick the installer appropriate for your development platform.

image

 

 

 

 

 

 

Run the installer.  The default settings should be fine.

image

 

Now we need to install Haxe Flixel.  With Haxe installed we can now use command line tools to finish the installation process.  Create a new command prompt or terminal as Administrator if possible.  Then run the command

haxelib install flixel

image

This will download all the various required libraries for HaxeFlixel to run including lime ( a low level hardware library ) and OpenFL.  Please note that as of writing, HaxeFlixel is NOT compatible with the most recent version of OpenFL and Lime, hopefully this is fixed soon.  Don’t worry though, the above command will download and configure the correct version.

 

Next run the command

haxelib run lime setup

 

Finally, HaxeFlixel has a set of command line tools and templates available, I will be using these tools for this tutorial series, so lets install those as well.  Run the following two commands:

haxelib install flixel-tools

haxelib run flixel-tools setup

 

image

 

At this point the “flixel” command is now available for you.  Let’s use it to create a new game project.  In the directory you want to create your game, enter:

flixel tpl –n “MyFirstFlixelGame”

 

A new project will be created for you and if you selected an IDE during the install process, it will automatically open:

image

 

As part of the previous process several demos were installed as well.  If you want to jump into some code, instead run the command:

flixel create

This will present you will all of the available templates you can create from:

image

 

That’s it for the setup process, in the next tutorial we jump in to the code of our first application.

 

The Video

Programming , ,

Month List

Popular Comments