Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon

24. April 2017

 

Cocos2D-x 3.15 was released today.  Cocos2D-x is a cross platform 2D game framework written in C++.  If you want to learn Cocos2D-x we have a complete tutorial series available here.  This new release updates a number of the underlying dependencies as well as adding support for Android Studio, Google’s version of IntelliJ IDEA which recently received C++ support.

Details from the release notes:

Highlights

  • full Android Studio supports: include editing, compiling and debugging c++ codes: doc
  • audio engine uses tremolo and MP3 Decoder Library to decode audio files on Android: high performance and more adaptable to different Android devices
  • WebSockets and SocketIO supports SSL
  • AssetsManagerEx is more stable
  • update Spine runtime to v3.5.35
  • update flatbuffer to v1.5
  • remove support for Windows 8.1 store and phone
  • update OpenSSL to v1.1.0
  • remove linux 32-bit support

 

Cocos2d-x is available for download here.

GameDev News

23. April 2017

 

Ogre3D is a popular C++ based open source 3D renderer and scene graph.  It has been used to make several games including Torchlight 1 and 2, Dungeons, Ankh 2/3 and more.  The 1.10 release adds several new features including the ability to target the browser via Emscripten, a better build system, new documentation, better renderers and more.

Details of the release:

  • Python bindings as a component
  • vastly improved GL3+/ GLES2 renderers with GL3+ now being the recommended choice on *nix systems
  • Bites Component for rapid prototyping of applications
  • Emscripten platform targetsupporting Web Assembly & WebGL2
  • improved build system, automatically fetching all required dependencies.
  • A new HLMS Component implementing physically based shading
  • Unified Documentation: the API docs, the manual and some Wiki pages have been merged and are now managed with Doxygen. As a consequence, the Wiki is outdated when it comes to OGRE 1.10. If you find something particularly missing, feel free to submit an additional tutorial.

Despite the amount of new features OGRE 1.10 provides the smoothest upgrade experience between OGRE releases so far. See the API/ ABI change overview for OGRE 1.7 – 1.10that is kindly provided by ABI-laboratory.
Note that some components are marked as [BETA]. This does not mean that they are likely to crash, but that we can not give any API stability guarantees for them right now. You should expect their API to change without a deprecation period while we we iron the warts out as the Component get more exposure.

In turn for the core components, our deprecation list has grown considerably. You can keep using these APIs for now, as we intend to support them until OGRE 1.11. Speaking of which; to make OGRE releases predictable, we will switch away to a feature based to a time based release model for the 1.x branch. This means that you can expect OGRE 1.11 in April 2018.

 

You can read more about the release here.

GameDev News

21. April 2017

 

Earlier on in the ongoing HaxeFlixel Tutorial series we covered drawing sprites, a fairly critical concept to any 2D game.  Today we are going to take that one step further and look at the process of animating them.  If you look at the FlxSprite class you will notice there is a member animation which is a FlxAnimationController.  This is the class we are going to be focusing on today.  However in order to animate sprites, we need sprites to animate.  2D animation is a lot like those flipbook animations you may have drawn on the corner of books.  Like the following:

 

 

This is exactly what we are going to do here.  Except instead of multiple pages of animations, we are going to put all of our sprites in a single image file.  This one in fact.  (Click to view full size)

walk

 

At it’s full size this image is composed of 16 frames of our sprite, each one 512x384 in size.  When we create our FlxSprite, we use a slightly different setup than we did in the past.

      spritesheet = new FlxSprite();
      spritesheet.loadGraphic(AssetPaths.walk__png,true,512,384);

 

Here when we call loadGraphic we pass in the width and height of the rectangle within the larger image that represents our individual sprite.  Next we need to define our animation. 

      spritesheet.animation.add("walkRight",[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],5,true);

Here we are adding an animation with the name “walkRight”, then we pass in the individual frame indexes that represent this animation.  These represent the index of the sub-rectangle within our source image, starting at the top left, going across to the right and down a row.  Therefore in this case 0 is the animation frame at the top left corner, 1 would be the one to it’s right, 4 would be the first image on the second row, 15 would be the final image in the sequence, etc.  After the array of indices, we pass in the frame rate.  In this case we are saying to play this animation at a rate of 5 frames per second.

One cool thing we can do is actually flip the animation on the X or Y axis, enabling us to use the same images for a walkLeft animation, like so:

      spritesheet.animation.add("walkLeft",[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],5,true,true);

It’s the exact same parameters, except with a different name and we pass in true to the FlipX parameter.

 

After we have defined our animation(s) and add() it, we need to tell the game engine which one to play, like so:

      spritesheet.animation.play("walkRight");

 

Let’s put some code in the update() callback that flips the direction of animation when the player presses the spacebar.

      if(FlxG.keys.justReleased.SPACE)
         if(spritesheet.animation.name == "walkRight")
            spritesheet.animation.play("walkLeft");
         else
            spritesheet.animation.play("walkRight");

 

You can also easily alter the speed an animation plays after it has been loaded, like so:

      if(FlxG.keys.justReleased.UP)
         spritesheet.animation.curAnim.frameRate++;
      if(FlxG.keys.justReleased.DOWN)
         spritesheet.animation.curAnim.frameRate--;   

We also have the ability to stop a playing animation, like this code that does it when ESC is hit.

      if(FlxG.keys.justReleased.ESCAPE){
         spritesheet.animation.curAnim.curFrame = 0;
         spritesheet.animation.finish();
      }

You do not have to set the frame to the beginning, but it helps if you want to transition to another animation or restart the existing one.

The animation controller also has a pair of callback functions that can be called each frame of an animation, or when an animation ends.  Please note that in this case we created our animation to loop by default, so the callback will only be called if you hit the ESC key to stop the animation manually.  Or you turn looping off when you define the animation sequence.

      spritesheet.animation.callback = function(s:String, frame:Int, index:Int){
         trace("Animation:" + s + " -- frame: " + frame + " index: " + index);
      }

      spritesheet.animation.finishCallback = function(s:String){
         trace ("------------------------ " + s + " anim finished ------------------");
      }

 

Ok, let’s look at that as one complete example now.

package;

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

class PlayState extends FlxState
{

   var spritesheet:FlxSprite;
   var text:FlxText;
   override public function create():Void
   {
      super.create();

      this.bgColor = FlxColor.GRAY;
      text = new FlxText(0,0,300);
      add(text);

      spritesheet = new FlxSprite();
      spritesheet.loadGraphic(AssetPaths.walk__png,true,512,384);
      spritesheet.animation.add("walkRight",[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],5,true);
      spritesheet.animation.add("walkLeft",[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],5,true,true);
      add(spritesheet);

      spritesheet.animation.play("walkRight");
      

      spritesheet.animation.callback = function(s:String, frame:Int, index:Int){
         trace("Animation:" + s + " -- frame: " + frame + " index: " + index);
      }

      spritesheet.animation.finishCallback = function(s:String){
         trace ("------------------------ " + s + " anim finished ------------------");
      }
   }

   override public function update(elapsed:Float):Void
   {
      super.update(elapsed);
      if(FlxG.keys.justReleased.SPACE)
         if(spritesheet.animation.name == "walkRight")
            spritesheet.animation.play("walkLeft");
         else
            spritesheet.animation.play("walkRight");

      if(FlxG.keys.justReleased.UP)
         spritesheet.animation.curAnim.frameRate++;
      if(FlxG.keys.justReleased.DOWN)
         spritesheet.animation.curAnim.frameRate--;   

      if(FlxG.keys.justReleased.ESCAPE){
         spritesheet.animation.curAnim.curFrame = 0;
         spritesheet.animation.finish();
      }
      text.text = "Cur speed: " + spritesheet.animation.curAnim.frameRate;    
   }
}

 

Here is the results.  Press SPACE to flip direction, UP and DOWN to control animation speed and ESC to stop the animation all together.

 

The Video

[Coming Soon]

Programming , , ,

17. April 2017

 

Up until this point in the HaxeFlixel Tutorial Series all of our examples have been confined to a single screen.  What happens however when your game world is larger than the screen?  Well, that’s where cameras come in.  In this tutorial we are going to look at creating a camera and navigating around the game world.  Cameras in HaxeFlixel are also capable of much more then this, including special effects and even split screen, all of which we will look at in this tutorial. 

There is one important concept to understand before we get too far.  The camera and the screen resolution are two completely different things.  The screen resolution, which we covered in this tutorial, determines the resolution and size of the applications window.  A camera on the other hand is a view into our game world.  They do not have to be the same, nor do they have to even use the same units.

In the example we are going to create I have a single large image to use as a background, an image many times larger than the screen, then another sprite to represent our player within the game world.  Let’s get the setup out of the way.  Don’t worry, I’ll do a full source listing later in the tutorial.

class PlayState extends FlxState
{
   var background:FlxSprite;
   var jet:FlxSprite;
   var blur:Bool = false;
   override public function create():Void
   {
      super.create();
      background = new FlxSprite();
      background.loadGraphic(AssetPaths.aerialcropped__jpg,false);

      jet = new FlxSprite();
      jet.loadGraphic(AssetPaths.jet__png);
      
      camera = new FlxCamera(0,0,640,480);

      camera.bgColor = FlxColor.TRANSPARENT;
      camera.setScrollBoundsRect(0,0,640,background.height);
      
      // Replace default camera with our newly created one
      FlxG.cameras.reset(camera);
      
      jet.angle = 90.0;
      jet.x = 320 - jet.width/2;
      jet.y = 0;

      camera.target = jet;
      add(background);
      add(jet);
   }
}

 

We run this game and get:

image

 

Nothing too exciting so far.  We setup and add our two sprites and most importantly create our FlxCamera object.  We create it with a top left position of 0,0 and size of 640x480.  We then set our camera as active with a call to FlxCamera.reset().  One important thing to be aware of, by default Flixel will create a camera for you in FlxG.camera that matches the size of your application’s resolution.  In this example there is no reason why we couldn’t just use the default created camera.  The other critical line of code to be aware of is

camera.target = jet;

This tells our camera to follow the FlxObject passed in, in this case our jet sprite.  The other key line here is

camera.setScrollBoundsRect(0,0,640,background.height);

This line sets the range that our camera will navigate.  As you will see in a moment when our jet sprite exceeds the bounds the camera will travel no further.  On that topic, let’s get some movement going and see what happens!

Add the following code to your project:

   override public function update(elapsed:Float):Void
   {
      super.update(elapsed);
      jet.y+= 300.0 * elapsed;
   }

 

And now when we run it (focus and press spacebar to begin):

 

As you can see, the camera smoothly follows the jet until the jet sprite exceeds the predefined bounds.  Neat.  So that’s the basics of a camera, but by no means all it can do.  Let’s look at adding zoom functionality next.  Add the following code to your update:

if(FlxG.keys.justReleased.UP)
   camera.zoom += 0.1;
if(FlxG.keys.justReleased.DOWN)
   if(camera.zoom > 1)
      camera.zoom -= 0.1;

Now when you press the update and down arrows:

zoomGifResized

 

You can also perform special effects, such as camera shake:

if(FlxG.keys.justReleased.SPACE)
   camera.shake(0.01,1);   

Resulting in:

Gif4Optimized

 

You can even apply special effect filters, such as blur:

if(FlxG.keys.justReleased.ESCAPE){
   blur = !blur;
   if(blur){
      var filter = new BlurFilter();
      camera.setFilters([filter]);
   }
   else {
      camera.setFilters([]);
   }
}

Resulting in:

GIF5

 

Now let’s look at a complete example.  In addition to all of the code above this one has a couple more features.  You can flash the screen red by pressing the A key.  Also when the jet goes off screen, the screen will fade to black then restart a few seconds later. 

package;

import flixel.FlxG;
import flixel.FlxSprite;
import flixel.FlxCamera;
import flixel.FlxState;
import flixel.util.FlxColor;
import flash.filters.BlurFilter;

class PlayState extends FlxState
{
   var background:FlxSprite;
   var jet:FlxSprite;
   var blur:Bool = false;
   var start:Bool = false;
   override public function create():Void
   {
      super.create();
      background = new FlxSprite();
      background.loadGraphic(AssetPaths.aerialcropped__jpg,false);

      jet = new FlxSprite();
      jet.loadGraphic(AssetPaths.jet__png);
      
      camera = new FlxCamera(0,0,640,480);

      camera.bgColor = FlxColor.TRANSPARENT;
      camera.setScrollBoundsRect(0,0,640,background.height);
      
      // Replace default camera with our newly created one
      FlxG.cameras.reset(camera);
      
      jet.angle = 90.0;
      jet.x = 320 - jet.width/2;
      jet.y = 0;

      camera.target = jet;
      add(background);
      add(jet);
   }



   override public function update(elapsed:Float):Void
   {
      super.update(elapsed);
      if(FlxG.keys.justReleased.SPACE)
         start = true;
         
      if(FlxG.keys.justReleased.UP)
         camera.zoom += 0.1;
      if(FlxG.keys.justReleased.DOWN)
         if(camera.zoom > 1)
            camera.zoom -= 0.1;

      if(FlxG.keys.justReleased.S)
         camera.shake(0.01,1);
      
      if(FlxG.keys.justReleased.ESCAPE){
         blur = !blur;
         if(blur){
            var filter = new BlurFilter();
            camera.setFilters([filter]);
         }
         else {
            camera.setFilters([]);
         }
      }              

      if(FlxG.keys.justReleased.A)
         camera.flash(flixel.util.FlxColor.RED,0.5);

      if(start){
         if(jet.y > background.height)
            camera.fade(FlxColor.BLACK,2.0,false, function(){
               FlxG.resetGame();
               });
         jet.y+= 300.0 * elapsed;
      }
   }
}

Click the window below and press Space to begin. S to shake, Up and Down arrows to zoom.  Unfortunately the Blur filter depends on the Flash target so does not work in the browser.

 

 

One final thing we are going to cover is supporting multiple cameras.  Let’s just jump in with a code example.

   override public function create():Void
   {
      super.create();
      background = new FlxSprite();
      background.loadGraphic(AssetPaths.aerialcropped__jpg,false);

      jet = new FlxSprite();
      jet.loadGraphic(AssetPaths.jet__png);
      
      var camera = new FlxCamera(0,0,320,480);

      camera.bgColor = FlxColor.TRANSPARENT;
      camera.setScrollBoundsRect(0,0,640,background.height);
      
      var camera2 = new FlxCamera(320,0,320,480);
      camera2.focusOn(new FlxPoint(320/2,480/2));

      // Replace default camera with our newly created one
      FlxG.cameras.reset(camera);
      FlxG.cameras.add(camera2);

      
      
      jet.angle = 90.0;
      jet.x = 320/2 - jet.width/2;
      jet.y = 0;

      camera.target = jet;
      add(background);
      add(jet);
   }

Now when run you see the screen is now split:

 

The second camera stays stationary while the camera on the left behaves exactly as the original did.

fin

 

The Video

Programming , , ,

11. April 2017

 

Articy:draft is a unique tool aimed at game designers for visually creating and organizing game content.  In many ways it is like a version of Visio created specifically for game developers handling such tasks as conversation trees, game flow, inventory, characters and more.  Additionally with the most recent release you can directly consume your data in the Unity game engine.  As the title suggests, articy:draft 2 SE is currently on sale for 95% off on the Bundle Stars website.  Available for less than $5 USD instead of the usual $200 price tag, this represents a pretty massive discount.  Act fast though, the sale ends on April 14th.

-------------------

EDIT – Be aware of the following limitation!

This version is for non-commercial use only. You can acquire an upgrade for commercial usage via Steam.

I am unable to determine the upgrade price for the commercial edition!

 

If you’ve never heard of articy:draft, be sure to watch the video below for more information!

GameDev News

Month List

Popular Comments