Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon

30. August 2016

 

OpenFL is the rebrand of NME, a cross platform HaXe media framework designed to implement a Flash like API for the Haxe programming langauge.  Lime is the lower level library OpenFL is built upon.  Both saw new releases this week

 

From the OpenFL release notes:

4.1.0 (08/29/2016)

  • Added new Stage3D code migrated from the (now defunct) PlayScript project
  • Added support for ENTER_FRAME, EXIT_FRAME and RENDER if not on the stage
  • Added openfl.ui.MouseCursor and Mouse.cursor support
  • Made minor changes to read-only getter properties to reduce code
  • Added to/from UInt conversion for standard enum types
  • Added duration to HTML5 NetStream onMetaData object
  • Added vector.insertAt
  • Added dictionary.exists
  • Improved stroking in graphics API
  • Improved openfl.Vector for better accuracy/performance
  • Fixed the order of ADDED and ADDED_TO_STAGE events
  • Fixed the behavior of vector.concat with no arguments
  • Fixed netStream.seek on HTML5
  • Fixed Capabilities.screenResolutionY
  • Fixed an issue with HTML5 shape positioning

 

Now from the Lime release notes:

3.1.0 (08/29/2016)

  • Switched from Ant to Gradle for Android builds
  • Added workarounds for some Haxe 3.3.0-rc1 issues
  • Added support for hidden windows on the desktop
  • Improved HTML5 mouse move by ignoring repeat events
  • Fixed issues in ArrayBuffer when values were null
  • Fixed a cross-origin issue that affected some browsers
  • Fixed support for System directories on Android
  • Fixed null fromBytes/fromImage conversion

GameDev News

12. July 2016

 

OpenFL, a Haxe library previously known as NME, just released version 4.  OpenFL is a media framework often used for creating games that is designed to give Flash developers a transitional path to Haxe development.  A major component of the OpenFL 4 release is to be more consistent with Flash APIs as well as a commitment to support the Stage3D API.  If you are interested in learning more I wrote a multipart tutorial series on using Haxe and NME before it was rebranded OpenFL.

 

From the release notes:

New OpenGL Renderer

We went to the drawing board to make a lightweight, clean, easy-to-understand OpenGL renderer in the core of OpenFL. This has resulted in a number of great benefits, not only for maintenance and development, but also this has enabled support for WebGL by default in our HTML5 builds. We have working ShaderFilter support in Bitmap, TextField,DisplayObject and Tilemap, and plan to add support to Sprite in the future.

WebGL builds will fallback to 2D canvas automatically if WebGL is not supported by a user's browser, but if you would prefer to force the use of 2D canvas when targeting HTML5, use -Dcanvas when compiling.

Greater Consistency with Flash APIs

There are many subtle little differences we are changing in order to better support the behavior you expect when using an open-source Flash library. These will not hurt ordinary projects, but can make all the difference when you port an existing ActionScript project over to use OpenFL. We are on the road to continue to remove the tiny differences that unnecessarily make some porting projects complicated.

Commitment to the Stage3D API

In the past, the Stage3D compatibility layer was developed by our friends on the Away3D project, and maintained by generous contributors through pull requests. As an API, this was not supported by the core OpenFL team, but with our new OpenGL renderer, and continuing commitment to providing the functionality you expect, we have begun the process of improving our Stage3D APIs to conform more closely with the original API. We are partnering with the developers of the Haxe Starling port to continue to make improvements to our core Stage3D implementation so that we can grow to support modern ActionScript projects using Stage3D with as little headache as possible.

Continued Graphics Improvements

OpenFL continues to improve in its support for the shape.graphics APIs, with minor edits to improve accuracy, as well as changes to our renderer to support scaled graphics and full fidelity. For projects that are designed for set pixel dimensions, OpenFL 4 is now able to automatically upscale and letterbox projects, bringing full quality graphics to projects that may have been designed only for a lower-resolution screen.

 

Along with this release there was also an update to Lime, the underlying technology on which OpenFL is built.

GameDev News

27. May 2016

 

Welcome back to our ongoing tutorial series on using the Heaps framework with the Haxe programming language.  In the first tutorial we covered the configuration and programming a simple game using Heaps.  Then we covered the basics of 2D graphics in the next tutorial.  In this tutorial we are going to look at using 2D animation in Heaps.  We are going to cover three specific ways, first using a sequence of images for each individual frame of animation, second using a single simple spritesheet image and finally we are going to look at using a texture atlas.  All of the images used in this tutorial are available here, while the project files, source, images etc. are all available to Patreon backers.

 

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

 

First copy the animation frames into the resource folder.  Each is named along the lines of walk01, walk02, walk03, etc like so:

image

 

Now let’s jump into the code.  The process is almost identical to the sprite handling process from the previous tutorial:

import h2d.Anim;
import h2d.Bitmap;
import h2d.Sprite;
import h2d.Text;
import h2d.Tile;
import hxd.Res;
import hxd.res.Font;

import js.Lib;

import hxd.App;
class Main extends App {
	
	
	var animation:Anim;
	
	override function init() {
		Res.initEmbed();
		var tiles = new Array<Tile>();
		
		tiles.push(Res.walk01.toTile());
		tiles.push(Res.walk02.toTile());
		tiles.push(Res.walk03.toTile());
		tiles.push(Res.walk04.toTile());
		tiles.push(Res.walk05.toTile());
		tiles.push(Res.walk06.toTile());
		tiles.push(Res.walk07.toTile());
		tiles.push(Res.walk08.toTile());
		tiles.push(Res.walk09.toTile());
		tiles.push(Res.walk10.toTile());
		tiles.push(Res.walk11.toTile());
		tiles.push(Res.walk12.toTile());
		tiles.push(Res.walk13.toTile());
		tiles.push(Res.walk14.toTile());
		tiles.push(Res.walk15.toTile());
		tiles.push(Res.walk16.toTile());
		
		animation = new Anim(tiles, 10, s2d);
	}
	
	override function update(dt:Float) {
	}
	
	static function main() {
		new Main();
	}
	
}

 

Here we populate an array of type Tile with all of the images.  Remember Heaps will automatically make available any resource type with an appropriate loader.  Finally we pass this array to the constructor of Anim.  Anim is a special kind of drawable that contains several tiles that represent individual frames of animation.  Also in the constructor we pass along the frame rate to play the animation at, as well as the parent to play the animation relative to, in this case the default scene, s2d.  When you run this code you should see:

GIF

Pretty simple eh?

 

It’s also quite common to want to group all of your sprites together in a single image.  The following example does exactly that using this evenly spaced spritesheet (click for full sized image).  Just be aware, this code requires the width and height of each tile to be the same size.

animation

 

Now the code:

	override function init() {
		Res.initEmbed();
		
		var tileSrc = Res.animation.toTile();
		var tiles = tileSrc.grid(512);
		
		animation = new Anim(tiles, 10, s2d);
		animation.speed = 5;
	}

 

This code has basically the exact same end result.  Basically we load the entire spritesheet into a single tile, then split it into a number of smaller tiles using the grid() method, passing in the dimension to cut by.  Hopefully in the future this function will be updated to take both a width and a height value, removing the square requirement.  As you can see from this example, you can modify the Anim object after the fact, changing the animation speed, it’s position, rotation, scale etc.

 

One final option is to use an Atlas.  An Atlas is basically another form of spritesheet, but instead of being fixed dimensions, it comes with a text description file that says where each frame of animation within the texture is.  This allows you to more tightly store your images in a single image.  In terms of creating an atlas file, two options are LibGDX’s TexturePacker or CodeAndWeb’s TexturePacker.  Of course you could create the file by hand if you preferred.  Now some more code:

	override function init() {
		Res.initEmbed();

		var frame = Res.animationAtlasv1.get("walk01");
		
		var bmp = new Bitmap(frame, s2d);
		bmp.x = 400;
	}

 

As you can see, there is also a loader for Atlas files, so it’s simply a matter of accessing it via the Res interface.  In this particular example we are retrieving a single frame of animation that we use to populate a Bitmap and display on screen.  The Atlas loader also has the option of return an Anim object if preferred.

 

The Video

Programming

17. May 2016

 

In our previous tutorial looking at the Heaps game framework, we looked at creating an initial application.  As part of that tutorial we used s2d to draw some text on the screen.  Today we are going to look a bit closer at using 2D graphics with Heaps.  Let’s start straight off with a simple example:

import h2d.Bitmap;
import h2d.Sprite;
import h2d.Text;
import h2d.Tile;
import hxd.Res;
import hxd.res.Font;

import js.Lib;

import hxd.App;
class Main extends App {
	
	override function init() {
		
		// Example one, create a new Bitmap using a Tile
		Res.initEmbed();
		var logo = Res.logo.toTile();
		var bitmap = new Bitmap(logo, s2d);
		
	}
	
	override function update(dt:Float) {
	}
	
	static function main() {
		new Main();
	}
	
}

 

When we run this example:

image

For this example to work you need to copy an jpg, gif or png file named logo to the resource directory.  Don’t forget you need to tell Haxe where this directory is using the –D resourceDir flag (see previous tutorial for more information ).  In this example we convert the resource to a Tile object, which you can think of as a rectangular region within an image (even if it encompasses the entire image).  Finally we used this tile to create a Bitmap object, which is brings together the thing to draw ( the Tile ) and where to draw it (the Sprite). More on these later.  As before to display it on screen the bitmap is parented to the s2d object, which is a Scene object that is created for us automatically.


Let’s look at another quick source example, the performs a very similar task:

import h2d.Bitmap;
import h2d.Sprite;
import h2d.Text;
import h2d.Tile;
import hxd.Res;
import hxd.res.Font;

import js.Lib;

import hxd.App;
class Main extends App {
	
	override function init() {
		
		// Example two, create a bitmap manually using BitmapData 
		and draw it to screen.
		Res.initEmbed();
		var logoBitmapData = Res.logo.toBitmap();
		var bitmap = Bitmap.create(logoBitmapData);
		s2d.addChild(bitmap);
		
		// Set the pivot point of our bitmap so it is positioned 
		relative to it's center
		bitmap.tile.dx = -Math.round(bitmap.tile.width / 2 );
		bitmap.tile.dy = -Math.round(bitmap.tile.height / 2);
		// Now center the bitmap to the screen
		bitmap.x = s2d.width / 2;
		bitmap.y = s2d.height / 2 ;
	}
	
	override function update(dt:Float) {
	}
	
	static function main() {
		new Main();
	}
	
}

 

And running this one...

image

 

Here we again create a Bitmap to be drawn on screen, but this time using a different process.  In the first example (which is that way you would do things 99% of the time) we loaded the resource as a Tile.  In this example we instead load it using the toBitmap() method.  This is VERY VERY VERY confusing, and is why I decided to show it as an example.  toBitmap() does NOT create a Bitmap object, instead it creates a BitmapData object.  This naming convention was quite poorly chosen in my opinion and leads to a great deal of confusion.  BitmapData can be thought of the raw bytes of information that go together to make all the various pixels in our bitmap.  BitmapData is stored in system memory and is extremely slow to work with.  That said, you can easily manipulate this information, so if for example you wanted to convert all of the individual pixels to grayscale, you could.

Another change here is we didn’t set the Bitmap’s parent (s2d) during construction.  Instead we manually add the newly created bitmap to our scene by calling addChild().  This function will take any Sprite derived class.  We will get back to that in a second, but it’s an important concept to understand.  This second example shows a couple other key concepts.  Notice how we set the position .x and .y?  Well these are simple pixel coordinates to represent where the image should be drawn relative to the origin of it’s parent (s2d in this case).  The origin by default is the top left corner.  In this example we set the pivot point (or origin) by specifying dx and dy.  These are delta values that tell you where drawing calls are made relative to.  In this case we will perform drawing calls on this object relative to it’s mid point.

 

That’s about all I want to cover at this point in time, but there are a few key Heaps classes we should understand before moving on.

 

Sprite

If you come from other game engines, this terminology is very confusing.  Almost universally a Sprite represents and image ( bitmap or texture in memory ) and the position to draw it at.  In heaps however, a Sprite is only about the position of the object. Sprite is the only type of object that can be added to Layer (and thus Scene) ‘s addChild() method call. 

 

Drawable

Drawable inherits from Sprite and is the parent class for things that can actually be drawn on screen.  Bitmap inherits from this class, but so to does Text which we used earlier, as does Anim and Graphics.

 

Scene

s2d is an instance of Scene which is ultimately the root of the 2D scene graph.  At it’s core, Scene is actually a Sprite itself ( via Layer ), but it also holds a special object called Stage and is capable of responding to a number of UI events, as we will see in an upcoming tutorial.

 

Tile

This is another one of those things can be a bit confusing.  A Tile is a rectangle within a texture or image, but ultimately represents a source rectangle that is going to be displayed.  For example, the tile of a bitmap could represent only a portion of the source image.  Consider the following change to our original source:

	override function init() {
		Res.initEmbed();
		var logo = Res.logo.toTile();
		var bitmap = new Bitmap(logo, s2d);
		bitmap.tile.setSize(Math.round(bitmap.tile.width / 2),	
		Math.round(bitmap.tile.height / 2));
	}

 

When this code is run we get:

image

 

The underlying image of our Bitmap is unchanged, but we are only using a quarter of it because we shrank the dimensions of the tile.  This Tile approach is handy when dealing with sprite sheets, where you have several different frames of animation in a single source texture.  We will see this process in a later tutorial.

Programming

12. May 2016

 

mínt is a renderer agnostic ui library for the Haxe language that is part of the snõwkit family of libraries.  Put more simply, it’s a Haxe based cross platform UI library.  As the headline above suggests, they just released Alpha 2.0.  The major feature of this release is the addition of a scaling factor, making high DPI monitor support easy to implement.  There is also the beginnings of a UI editor which you can try right here in your browser.

 

This release also included several minor changes including:

  • control added children_at_point for a sorted list
  • window fixed close handle being a label
  • textedit fixed/added alignment options
  • margins added fixed offset to the anchor layout
  • examples added an empty luxe testbed and an AutoCanvas helper
  • lib added focus model, allowing user/platform specified focus handling
  • textedit add/enable IME entry (+ in mint.render.luxe)
  • luxe added color options to most controls
  • slider josuigoa added invert flag
  • textedit added display_char for password type entry
  • lib fixed usage of luxe types in mint core code

 

More information about this release is available here while mint itself is available on Github.

GameDev News

Month List

Popular Comments

All posts tagged 'tutorial'
Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon

6. December 2016

 

A couple years ago I did a detailed text tutorial on how to use a debugger which oddly is a massively important skill that simply isn’t taught.  Given that this article is still popular two years later I’ve decided to follow it up with a video version.  This video, Debugging 101, walks through the basic tasks involved in debugging.  It used Visual Studio 2017 and C++ but should be applicable in most languages and IDEs.  The video shows how breakpoints and conditional break points work, how to step into, over and out of your code, how to use the local and watch window, call stacks, how to do memory debugging and more.  Basically the video shows you how to get started using a debugger.

 

The following is the code used in this example.  There is nothing special to this code, it’s extremely contrived, but it enabled me to show the various features available in most debuggers.

#include <iostream>

// These two functions are used to illustrate how the call stack works
// As well as how step into and step out of behave.
int innerFunction(int input) {
	int meaninglessCounter = 0;
	for (int i = input; i > 0; i--) {
		// First show stepping through the loop
		// Set a conditional breakpoint that breaks when i is a certain value.
		meaninglessCounter++;
	}
	return input;
}

int outerFunction() {
	int i = 42;
	return innerFunction(i);
}


class Demo {
	std::string stringValue;
	int intValue;
	bool booleanValue;

	public: 
		Demo(std::string a, int b, bool c) : stringValue(a), intValue(b), booleanValue(
		c) {};
};

int main(int argc, char ** argv) {
	// Callstack demo, jump into, jump over example
	int someVal = 0;
	someVal = outerFunction();

	// Data example -- simply create a char buffer, fill it with 'a' then null 
	terminate it so 
	// it can be treated like a string.
	char * data = new char[1000];
	for (int i = 0; i < 1000; i++)
		data[i] = 'a';
	data[999] = 0;
	std::cout << data << std::endl;

	//set a watch on d.  Demonstrates watches and drilling into complex object
	Demo d("Hello", 42, true);
	
	std::cout << "End of demo" << std::endl;
	delete[] data;
	// delete[] data;  Calling delete again will trigger an exception
}

Programming , , ,

29. November 2016

 

Welcome to the next part in the ongoing BabylonJS Tutorial Series.  In the previous tutorial we created our first simple scene which contained a simple camera.  In this tutorial we are going to explore the concept of camera’s in more depth.  As always there is an HD video version of this tutorial available here.

 

In the previous example we created a Free Camera.  A Free Camera is a camera that can be moved around using the mouse and keyboard.  Often of course you are going to want to be able to customize which keys are used to move the camera.  Here is an example that configured the camera to respond to the WASD keys.

 

var canvas = document.getElementById('canvas');

        var engine = new BABYLON.Engine(canvas, true);

        var createScene = function(){
            var scene = new BABYLON.Scene(engine);
            scene.clearColor = new BABYLON.Color3.White();
            var camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0,
            0,-10), scene);
            camera.setTarget(BABYLON.Vector3.Zero());
            camera.attachControl(canvas,true);
            camera.keysUp.push(87);    //W
            camera.keysDown.push(83)   //D
            camera.keysLeft.push(65);  //A
            camera.keysRight.push(68); //S


            var box = BABYLON.Mesh.CreateBox("Box",4.0,scene);
            return scene;
        }

        var scene = createScene();
        engine.runRenderLoop(function(){
            scene.render();
        });

 

This code running:

1

When we create the camera, we pass it’s initial location within our scene.  In this case the position is (0,0,-10) or –10 down the Z axis.  Of course we also pass the scene the camera belongs to into the constructor as well.  Next we set the target of the camera, in this case the origin (or a Zero vector).  Finally we need the camera to actually receive input controls from the canvas.  This is simply done by calling attachControl.  This will result in input (such as mouse and keyboard) being passed to the camera for processing.  There is a member of the camera for keys representing up, down, left and right movement.  To each we pass the appropriate key scancode for the each key in the WASD combination.  When you run this code, you can now navigate around the scene using the WASD and free look using the mouse.

 

Another common camera type is a camera that orbits an object.  That is the camera revolves around the target in a circular orbit.  This is accomplished using an ArcRotateCamera.  Keep in mind however, you could also implement this camera in any other camera object available in Babylon, it would however be your responsibility to implement the functionality.  The follow is the code to create an ArcRotateCamera:

        var createScene = function(){
            var scene = new BABYLON.Scene(engine);
            scene.clearColor = new BABYLON.Color3.White();

            var box = BABYLON.Mesh.CreateBox("Box",4.0,scene);
            var camera = new BABYLON.ArcRotateCamera("arcCam",
                    BABYLON.Tools.ToRadians(45),
                    BABYLON.Tools.ToRadians(45),
                    10.0,box.position,scene);
            camera.attachControl(canvas,true);

            return scene;
        }

 

This code running:

2

The three major parameters to the ArcRotateCamera are the alpha, beta and radius.  Radius is straight forward, this is the distance to orbit the target.  Think of the target as the mid point of a circle.  The radius then defines the size of the circle the camera will follow.  Alpha is the rotation angle around the X axis, while beta is the rotation angle around the Y axis.  Note that both take their parameter in radians instead of degrees, so we have to convert using the ToRadians() helper method.

 

The final kind of camera we are going to look at is the FollowCamera.  This camera does exactly what you’d expect, it follows a given target.  Let’s look at some code:

        var canvas = document.getElementById('canvas');

        var engine = new BABYLON.Engine(canvas, true);

        var createScene = function(){
            var scene = new BABYLON.Scene(engine);
            scene.clearColor = new BABYLON.Color3.White();

            var box = BABYLON.Mesh.CreateBox("Box",4.0,scene);

            // Create a second object so we can actually witness the movement
            // Make this one wireframe to distiguish the difference.
            var box2 = BABYLON.Mesh.CreateBox("Box2",4.0,scene);
            var material = new BABYLON.StandardMaterial("material1",scene);
            material.wireframe = true;
            box2.material = material;

            box2.position = new BABYLON.Vector3(0,5,0);

            var camera = new BABYLON.FollowCamera("followCam",BABYLON.Vector3.
            Zero(),scene);
            camera.target = box;
            camera.radius = 100;
            camera.heightOffset = 0;
            camera.attachControl(canvas,true);

            scene.activeCamera = camera;
            return scene;
        }

        var scene = createScene();
        engine.runRenderLoop(function(){
            scene.getMeshByName("Box").position.y += 0.1;
            scene.getMeshByName("Box").position.x += 0.1;
            scene.render();
        });

 

This code running:

3

This code contains two rendered cubes, the second a box with a wireframe material attached.  This was done so you could actually detect movement!  We will cover the specifics of materials shortly so don’t sweat the details.  Notice in the creation of the FollowCamera we pass in a target to follow (box), how far away we should follow from (radius) and there is also a control for how height the camera should be relative to the target.

 

It should be noted these are only a few of the possible cameras implemented in BabylonJS.  There are a good dozen other cameras available out of the box with features like touch or gamepad control, VR rendering and more.  The basic principals remain the same regardless to camera type.

The Video

Programming , ,

15. November 2016

 

Welcome to the getting started tutorial in the ongoing BabylonJS Tutorial Series.  Today we are going to look at creating our first simple Babylon application setup and running.  As always there is a HD video version of this tutorial available here or embedded down below. 

 

To get started with BabylonJS, we need a web page containing a <CANVAS> tag to host our application.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <style>
        #canvas {
            width:100%;
            height:100%;
        }
    </style>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>

 

Nothing special here.  We simply create a canvas tag named canvas, style it so it takes up the entire page and that’s about it.  Now we need to link to the BabylonJs library.  You’ve got a few options here, you can download it locally or host it from a content delivery network (CDN).  I’ll take this approach, as it’s generally the fastest option for end users.  You can even create a stripped down version with only the required features here.

 

The options for using BabylonJS include:

 

Babylon.max.js is the most human readable of the versions, making it the easiest to debug but the slowest to load.  During development, this is the version I am going to use.  Simply link to this library somewhere within the <HEAD> tag of our HTML.

<script src="http://cdn.babylonjs.com/2-4/babylon.max.js"></script>

 

We have our host webpage setup and Babylon linked, time to finally get down to some code.  Below our canvas, add the following code:

    <script>
        window.addEventListener('DOMContentLoaded', function(){
            var canvas = document.getElementById('canvas');

            var engine = new BABYLON.Engine(canvas, true);
            var createScene = function(){
                var scene = new BABYLON.Scene(engine);
                
                scene.clearColor = new BABYLON.Color3.White();
                var camera = new BABYLON.FreeCamera('camera1', new BABYLON.
                Vector3(0, 0,-10), scene);
                camera.setTarget(BABYLON.Vector3.Zero());

                var box = BABYLON.Mesh.CreateBox("Box",4.0,scene);
                
                return scene;
            }

            var scene = createScene();
            engine.runRenderLoop(function(){
                scene.render();
            });

        });
    </script>

 

When we run this code we should see:

image

 

Humble beginnings certainly, but our first running app is complete.  So what are we seeing here?  It’s an unlit cube viewed by a camera looking at the origin from –10 units down the z-axis.  Let’s take a quicker look at the code that got us here.  First we create a function that we call on DOMContentLoaded event fired, so basically when our page is loaded, this function is called.  Let’s walk through the function.

var canvas = document.getElementById('canvas');
var engine = new BABYLON.Engine(canvas, true);

This code gets a reference to the canvas tag we created in our HTML file.  We then use this canvas to create an instance of our Babylon game engine.

var createScene = function(){
    var scene = new BABYLON.Scene(engine);
    scene.clearColor = new BABYLON.Color3.White();
    var camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 0,-10),
    scene);
    camera.setTarget(BABYLON.Vector3.Zero());
    var box = BABYLON.Mesh.CreateBox("Box",4.0,scene);
    return scene;
}

Here we are creating a function that will setup our scene.  First we create a new Scene using our newly created engine.  We then set the clear color to white.  The clear color is the color that each frame is cleared with between calls, essentially setting the background color to white.  Next we create a FreeCamera named “camera1”, located at –10 along the Z axis in our scene.  Next we set the target to the origin (0,0,0).  We will go into more detail on cameras shortly, so let’s skip over this for now. Then we create a cube at the origin named “Box” that is 4x4x4 in dimensions.  Notice in both when we create the Camera and Box we pass the scene in.  This causes these entities to be created in that particular scene.  Finally we return our newly created scene from our function.

var scene = createScene();
engine.runRenderLoop(function(){
    scene.render();
});

 

Next we create our scene by calling our just defined createScene() function.  We then start our game loop calling engine.runRenderLoop().  The game loop can be thought of as the heart of our game.  This is a loop that will be called over and over as fast as possible.  If for example your game is drawing at 60FPS, this function is called 60 times in a second.  For now all we do is call scene’s render() method, which causes the contents of that scene to be drawn.

 

Here now is the code in it’s entirety.  ( A WebStorm project is available in the GFS Patreon Dropbox directory Tutorial Series –> Babylon for backers )

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="http://cdn.babylonjs.com/2-4/babylon.max.js"></script>

    <style>
        #canvas {
            width: 100%;
            height: 100%;
        }
    </style>
</head>
<body>
    <canvas id="canvas"></canvas>
    <script>
        window.addEventListener('DOMContentLoaded', function () {
            var canvas = document.getElementById('canvas');
            var engine = new BABYLON.Engine(canvas, true);
            var createScene = function () {
                var scene = new BABYLON.Scene(engine);
                scene.clearColor = new BABYLON.Color3.White();
                var camera = new BABYLON.FreeCamera('camera1', new BABYLON.
                Vector3(0, 0, -10), scene);
                camera.setTarget(BABYLON.Vector3.Zero());
                var box = BABYLON.Mesh.CreateBox("Box", 4.0, scene);
                return scene;
            }
    
            var scene = createScene();
            engine.runRenderLoop(function () {
                scene.render();
            });
        });
    </script>
</body>
</html>

 

That’s it for now.  In the next part we will explore cameras in more detail.

 

The Video

GameDev News , , ,

9. November 2016

BabylonBannerSplattered_thumb[3]

Welcome to the GameFromScratch.com tutorial series covering the BabylonJS HTML5 game engine.  The home page of the series is available here.  For each tutorial in the series there is both a text and video version available.  In this post we are simply going to introduce the BabylonJS engine, the scope of this tutorial series and discuss why you might want to use the Babylon engine and also some of the alternatives available should you decide not to.  If you’ve already decided on using the BabylonJS game engine, jump forward to the next tutorial.

 

BabylonJS Overview

I’m not going to go into a great deal of detail on the functionality included in BabylonJS as I have already featured this game engine in the Closer Look game engine series.  Instead we are going to take a quick top level look at the engine features.

 

Why Choose BabylonJS

So, why is the BabylonJS game engine a good choice for you?

  • Open source (Apache 2 license) and free to use
  • Full featured 3D game library (scene graph, physics, particles, models, sprites, etc)
  • Compatible with most modern WebGL browsers
  • Excellent tooling, including level editor, Unity exporter, model converters
  • Good documentation, samples and other learning materials

You can read the full feature set here.

 

Why Not Choose BabylonJS?

So we mentioned a number of Babylon’s strengths, but why would you *not* choose to use BabylonJS?  Well, beyond the fact you may not like how they implement things the biggest reason all comes down to your priorities.  WebGL performance isn’t on par with desktop OpenGL or even OpenGL ES, so there is a bit of a performance penalty at work here.  While HTML5 applications can be wrapped to run as applications on various mobile devices, again there is a price to be paid, in both performance and labor.

At the end of the day, personally, I think a lot of it comes down to your primary target.  If you are creating a browser game first and foremost, I recommend working in a browser native library such as BabylonJS.  This has the most direct workflow, is easiest to debug, etc.  If on the other hand the browser is just another target for you you are probably better off working in a game engine that also targets HTML5, such as Unreal or Unity.

 

Alternatives to BabylonJS

Shockingly there aren’t actually a ton of HTML5 3D game engines or frameworks like BabylonJS.  The most direct alternatives are:

 

By no means is that an exclusive list, but it does represent some of the most common 3D engines with WebGL as their primary target.

In addition to these engines several 3D engines offer HTML5 as a target including Unreal, Unity, Godot and many more.  The primary challenge with these options is the generated code is often illegible, acting almost identically to a compiled binary.  So if things don’t work right you are dependent on the engine developer to fix things.  Or if you wish to use a native browser feature, you are again dependent on the engine developers to support it in some form.

 

Enough overview, lets jump into the technical details.  I am aiming to keep each tutorial somewhat short and concise, both text and video versions.  Stay tuned for the first tutorial covering getting BabylonJS up and running.

 

The Video

Programming , , , ,

23. September 2016

 

Welcome back to our ongoing Godot tutorial series.  You may notice a pretty major change in the way Godot looks from previous tutorials.  This is because this tutorial jumps forward to Godot 2.1 which has an updated look and feel.  Don’t worry, the process is virtually identical regardless to which version of Godot you were running.  Today we are going to look at implementing 2D lights in your Godot game.  This will involve creating Godot light nodes, as well as occluders to prevent light.  We will also look at light masking, which is useful for implementing fog of war type effects. 

 

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

 

First let’s set up a simple scene we can test our lighting on.  I simple create the following hierarchy using the default Godot icon sprite.

image

 

Then scale it up like so:

image

 

Now let’s add a Light2D as a Child to our Root node:

image

 

Notice the exclamation mark?

image

 

This is because we need to specify a texture to use as the light source.  I created the following image in Paint.net (process is shown in the video if you want to see how it was made):

LightMask

 

Notice that this image is a grayscale PNG file with an alpha channel.  Where there are no pixels at all, there will be no light shown.  Where it is whitest, the light will be most intense, while the darker it gets the less intense the light.  Save this image or create your own and add it to your project.  Now we set it as the texture source for our light.

image

 

Now if you move your Light2D node around the scene, you will see how it interacts with other objects in the scene:

GIF

 

There are a number of properties you can set for the light, such as the Energy (intensity) Color (tint) and Scale (size):

image

 

Notice also Mode.  We will come back to that in a minute.  Now sometimes you aren’t going to want all lights affecting all objects in the scene.  Thankfully there is a setting for that.  Notice in the range category there is a setting called Item Mask:

image

 

This controls what layer of items this light will interact with (there is also a setting for shadows as well).  Now if you switch over to your Sprite, under canvas item you will notice a Light Mask setting:

image

 

So long as the light and CanvasItem use the same masking channel, the light will apply to that node.  If they don’t use the same channel, the light will have no effect.  This can lower processing costs and enables you to exempt parts of your seen from being lit if so desired.

 

Now sometimes you want to have light actively blocked in your scene.  For example you might have a wall that should cast a shadow.  This is easy to implement in Godot using Occuluders.  This is simply a polygon area where the proverbial light don’t shine.  Let’s set one up around the nose of our Godot sprite.  Add a LightOccluder2D to your Sprite.

image

 

Your scene hierarchy should now look like:

image

 

With the LightOcculder2D node selected in the Scene the following icon should be available in the 2D view:

image

 

Click the pencil.  Now we want to draw our occlusion polygon, like so:

Gif2

 

Now notice the way the light interacts with the scene...

gif4

 

Now remember earlier on the Mode value of our Light2D node?

image

 

Now we are going to switch it over to “Mask” and show a powerful capability.  This can be used to create localized lights or to implement fog of war effects.  Just like before we need a texture to represent our light source, but this time we want the pixel values reversed, so I created the following image:

LightMask2

 

In this case the black area will receive no light, while the whitest area will contain the most light.  Here is the end result:

gif5

 

By scaling the light out to the full size of the screen, you can easily attach such a light to the character sprite to easily implement a fog of war type approach.

 

The Video

Programming ,

Month List

Popular Comments