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 , , ,

20. March 2017

 

Epic have released a new hotfix for Unreal Engine, 4.15.1.  This update is composed entirely of fixes, including:

Fixed! UE-42385 Crash adding an AnimComposite to itself
Fixed! UE-41929 Crash on reimport animation when there is an additive animation track and fbx frame number is different
Fixed! UE-41921 Crash Re-Importing animation with Additive Layer Tracks after adding a bone to the hierarchy
Fixed! UE-41817 Crash when manipulating Bone Space IK before setting EffectorSpaceBoneName
Fixed! UE-40025 Inconsistant Line Trace behavior
Fixed! UE-42756 UnrealVS not installing correctly for VS2017
Fixed! UE-42321 Unable to launch project from Visual Studio using installed engine build
Fixed! UE-42411 Resource files are not recompiled when Version.h changes
Fixed! UE-42205 Hot reload reported as failed in Visual Studio for projects opened in the Editor after having hot reloads performed successfully previously
Fixed! UE-42507 check(PIEInstanceID != -1) fails when executing SeamlessTravel
Fixed! UE-42480 SetVectorParameterValueOnMaterials In Construction Script Not Working in Packaged Game
Fixed! UE-42459 BP nativization doesn't work with localized text
Fixed! UE-42166 Crash when pressing Ctrl-Z after creating a blueprint function
Fixed! UE-41893 Child blueprints cannot override functions if their parent was nativized
Fixed! UE-41168 Crash opening blueprint when a node class has been removed (e.g., anim blueprint with Ragdoll node with Immediate Mode plugin disabled)
Fixed! UE-42209 Incorrect error message when child actor mobility doesn't match
Fixed! UE-42253 Enum Element Names Reset on Project Upgrade
Fixed! UE-42375 No input received from Raw Input device when packaged for 32bit
Fixed! UE-39884 Foliage LODs do not appear to use the base LODs lightmap any longer
Fixed! UE-42390 Ad banner is displayed incorrectly on Android 7.0 devices
Fixed! UE-42361 Slate UI asset colors washed out on iOS
Fixed! UE-42191 Scene Captures not working on Android
Fixed! UE-42036 Exposure Is More Extreme In High-End Mobile Preview Modes
Fixed! UE-42368 Find Sessions Consistently Returning Results Length of 0
Fixed! UE-42452 No textures listed when selecting material
Fixed! UE-42789 Rebuilding lighting not saving rebuilt light data
Fixed! UE-42196 Static meshes with auto-generated LODs can no longer share lightmaps between LODs
Fixed! UE-42179 Crash in FStreamingTextureLevelContext::GetBuildDataIndexRef
Fixed! UE-42165 [CrashReport] UE4Editor_Renderer!FReflectionEnvironmentSceneData::ResizeCubemapArrayGPU() [reflectionenvironment.cpp:215]
Fixed! UE-42102 Cooked build size increase due to MIC problem
Fixed! UE-41950 GitHub 3252 : Added MobileMaterialInterface to UsedMaterials
Fixed! UE-29491 Eye Adaption is incorrect at any size other than Fullscreen in PIE
Fixed! UE-42554 Regression: Visibility property is not seen in the animation track in UMG
Fixed! UE-42210 Crash when using Ctrl+Z to undo a single digit change in the size of a widget
Fixed! UE-41829 Crash scrubbing through sequencer when playing montage from old assets
Fixed! UE-42665 Update default super search engine to Bing
Fixed! UE-42428 Enabling "Show Only Modified Properties" causes details panel menu to disappear
Fixed! UE-42312 Crash when saving a Data Table that is referencing itself in a Data Table Row Handle
Fixed! UE-35606 Crash when Importing .OBJ using the File > Import into Level Option
Fixed! UE-42669 "Package localization ID mismatch during cook!" log spam
Fixed! UE-41797 Update to Korean localization
Fixed! UE-42106 Edge case where cursor can become hidden in gameplay
Fixed! UE-42631 Stereo off while prox sensor uncovered causes low framerate
Fixed! UE-42576 Oculus crash on "stereo on" when the proximity sensor is not triggered.
Fixed! UE-42101 [daydream] Black screen with FirstPersonTemplate and 4.15P4
Fixed! UE-41604 Integrate fix for improper failure case for allocation of RenderTargets in Oculus
Fixed! UE-41568 Need to enable GearVR on Win64 platforms

 

As always, the hotfix is available for download in the Epic Game Launcher.

GameDev News

17. March 2017

 

Unity have released a new patch, this one bringing the Unity game engine to version 5.5.2p3.  The patch is composed entirely of fixes including:

Fixes
  • (868587) - Animation : Fixed a race condition in the legacy animation system which could cause a crash if a GameObject and an Animation assigned to that GameObject were deleted in the same frame.
  • (864273) - Editor: Fixed an issue with deselect of single selected item in hierarchy with ctrl/cmd+click.
  • (864246) - Editor: Fix for time not updating in Editor if play mode is entered and then exited while paused.
  • (861345) - Editor: Fixed an issue with vertex snapping jumping to extreme values in isometric view.
  • (858292) - GI : Fix for lightmaps not being loaded in a standalone player when loading scene through an AssetBundle.
  • (862215) - GI : Fix for lightprobe gizmos being rendered too bright in Linear color space.
  • (none) - Graphics : Fixed D3D12 cubemap mip generation.
  • (868935) - Scripting: Fixed MonoBehaviour array field with initializer getting resized to 0 by serialization.
  • (none) - Tizen: Fixed a crash that occurred when an app tried to exit.
  • (858645) - UI : Fixed the issue of fonts created at runtime not showing up when added to text.
  • (none) - VR: Updated Oculus to version 1.12. This fixed a GearVR timeout issue.
  • (886630) - Windows: Fixed the logging code in the Windows Editor/Standalone player so that messages got printed at once instead of one byte at the time.

 

As always you can download the patch here.  In addition to the patch Unity released an updated post outlining the future of their networking support for the Unity engine.

GameDev News

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 , , ,

16. March 2017

 

Corona Labs, the makers of the Corona SDK Lua powered game engine, have been sold to Appodeal, a mobile advertising firm.  Back in November of 2015 Corona was acquired by Perk then in September of 2016 it was sold back to the CEO, so it’s been a rocky couple of years over at Corona Labs.  Let’s hope this deal provides some stability for the Corona engine.

 

Details from the announcement:

One of the laurels of Corona SDK is how easy it makes it to build games across platforms without compromising on power and flexibility. For those who need to extend beyond what Corona provides “out of the box” with its many APIs and plugins, the Enterprise version of Corona is perfect.

Appodeal is the functional counterpart to Corona — developers can simply sign up for Appodeal, integrate it with a few lines of code, and connect to multiple demand sources (including AdMob and Facebook Audience Network!). Even though Appodeal connects to dozens of ad networks, developers get the convenience of just one easy payment (with the exception of AdMob and Facebook Audience Network). For developers who want even more power and control over their ad network relationships, Appodeal puts you in the driver’s seat so you can tune as you see fit.

An important note is that the acquisition of Corona Labs by Appodeal does not mean that developers must use Appodeal to monetize their games — Corona Labs will continue to offer and support third-party ad networks into the future, although the integration with Appodeal may get deeper over time with the aim to make it even easier to add monetization to your games.

In addition to a natural fit around building easily and monetizing easily, there’s a shared appreciation around the role Corona plays in the indie developer ecosystem. While many ad networks tend to court developers that already have large audiences, Appodeal recognizes that it’s the smaller developers who make up the vast majority of the ecosystem and that nurturing the relationship with these developers will only promote the possibilities of growth and success.

Appodeal is a global company with offices in San Francisco, Barcelona, and Moscow to name a few. Corona has a large developer community in every nook of the world and Appodeal’s international presence and commitment to serving developers worldwide means higher eCPMs no matter where your users are — and where they can’t deliver, their connectivity to AdMob and Facebook Audience Network solves the problem well.

GameDev News

Month List

Popular Comments