Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon
17. July 2018


Are you looking for an open source cross platform HTML5 powered game engine, that’s open source, free and comes with a complete editor in addition to the underlying framework?  Perhaps the Wade Game Engine by Clockwork Chilli is what you are looking for.  While open source, WADE is shipped under a custom license you should take note of.  The TL;DR version of the license:

This license allows you to make games and non-games, for any purpose including selling and licensing, without paying anything to Clockwork Chilli. However you must not:

  • Distribute non-compiled (or non-minified) versions of Clockwork Chilli's source code.
  • Create a product that competes with WADE.

You can run WADE directly in the Chrome browser or can download a local installed version for Linux, Mac and Windows platforms.  If you want to learn more, be sure to check out the WADE game engine in action in this video or embedded below.

GameDev News ,

18. June 2018


The PlayCanvas HTML5 game engine just added 2D support in the form of Sprites, texture atlases, animated sprites, sprite components and 9 patch support.

From the PlayCanvas blog:

PlayCanvas is one of the most popular ways to build 3D interactive web content today. But before 3D graphics was a thing, there was 2D graphics!

Today we’re excited to launch the first part of our 2D graphics support. Great for building classic 2D games.

There are 5 great new features which will help you build 2D games using PlayCanvas.

Those new features are:

  • Texture Atlas assets
  • Sprite Asset
  • Sprite Component
  • Sprite Editor
  • 9 Slicing

For more details on the new 2D functionality in the PlayCanvas editor, be sure to check out this hands-on video where we illustrate how to import a texture atlas and use it to create 2D sprite animations:

If you are interested in learning more about PlayCanvas, be sure to check out our two part tutorial on building a simple bowling title in PlayCanvas available here and here.

GameDev News

3. May 2018


Impactjs is a 2D HTML5 game engine with a built in level editor called Weltmeister.  Previously it was commercial software with a $99 price tag.  Earlier today the author made the following tweet:

image


The engine is now available under the MIT open source license.  It’s available on Github right here.  Unfortunately the editor has some PHP dependencies, making it somewhat tricky to get up and running without a full blown PHP install.


It’s been several years since Impact was updated, so unless a community forms around this libraries open sourcing, I see little reason to recommend it.

GameDev News

15. March 2018


Google just open sourced Resonance Audio, their 3D spatial audio rendering SDK.  It supports multiple platforms and game engines including Unreal, Unity, wWise, FMod, iOS, Android and Web.  You can learn more about Resonance Audio here, while the source is hosted on Github under the liberal Apache 2 source license.  Resonance enables you to create and position audio sources in 3D, define audio properties of your world, position the listener and it then calculates the results for you.


The following is a simple HTML5 sample that illustrates creating a 3D audioscape using the Web api.  It creates 3 different sounds, a laughing woman, a waterfall and a bird chirping, all downloaded from freesound.org.  The lady laughing can be moved around using the arrow keys as well as page up/down to move around the Z axis.  You can move the listeners ear left and right using the A and D key.  Finally the bird chirping will appear every 4 seconds in a random location relative to the users ear, + or – 1 meter.


You can get more details and hear the demo results in this video, which I will also embed below.  The sound works best when heard through a set of headphones.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>GFS Resonance Audio Test</title>


    <script src="https://cdn.jsdelivr.net/npm/resonance-audio/build/resonance-audio.min.js"></script>

    <script>
        var laughX = 0.0;
        var laughY = 0.0;
        var laughZ = 0.0;


        var x = 0.0;
        var y = 0.0;
        var z = 0.0;

        // Create an AudioContext
        let audioContext = new AudioContext();

        // Create a (first-order Ambisonic) Resonance Audio scene and pass it
        // the AudioContext.
        let resonanceAudioScene = new ResonanceAudio(audioContext);

        // Connect the scene’s binaural output to stereo out.
        resonanceAudioScene.output.connect(audioContext.destination);

        // Define room dimensions.
        // By default, room dimensions are undefined (0m x 0m x 0m).
        let roomDimensions = {
            width: 3.1,
            height: 2.5,
            depth: 3.4,
        };

        // Define materials for each of the room’s six surfaces.
        // Room materials have different acoustic reflectivity.
        let roomMaterials = {
            // Room wall materials
            left: 'metal',
            right: 'curtain-heavy',
            front: 'curtain-heavy',
            back: 'curtain-heavy',
            // Room floor
            down: 'grass',
            // Room ceiling
            up: 'grass',
        };

        // Add the room definition to the scene.
        resonanceAudioScene.setRoomProperties(roomDimensions, roomMaterials);

        /// -----------------  Laugh audio
        // Create an AudioElement.
        let audioElement = document.createElement('audio');

        // Load an audio file into the AudioElement.
        audioElement.src = 'laugh.wav';
        audioElement.loop = true;
        // Generate a MediaElementSource from the AudioElement.
        let audioElementSource = audioContext.createMediaElementSource(audioElement);
        // Add the MediaElementSource to the scene as an audio input source.
        let source = resonanceAudioScene.createSource();
        audioElementSource.connect(source.input);
        // Set the source position relative to the room center (source default position).
        source.setPosition(laughX, laughY, laughZ);
        source.setMaxDistance(3);

        /// -----------------  Waterfall
        // Create an AudioElement.
        let audioElement2 = document.createElement('audio');
        audioElement2.src = 'waterfall.wav';
        audioElement2.loop = true;
        let audioElementSource2 = audioContext.createMediaElementSource(audioElement2);
        let source2 = resonanceAudioScene.createSource();
        audioElementSource2.connect(source2.input);
        source2.setPosition(0,0,0);
        source2.setMaxDistance(3);


        /// -----------------  Bird noises
        let audioElement3 = document.createElement('audio');
        audioElement3.src = 'bird.wav';
        audioElement3.loop = false;
        let audioElementSource3 = audioContext.createMediaElementSource(audioElement3);
        let source3 = resonanceAudioScene.createSource();
        audioElementSource3.connect(source3.input);
        source3.setPosition(0.5,0,1);
        source3.setMaxDistance(3);

        // Play the audio.
        audioElement.play();
        audioElement2.play();

        setInterval(()=>{
            //randomly position bird  -1 to +1 x/y relative to the listeners location every 4 seconds
            source3.setPosition(x + Math.random() * 2 - 1 ,y + Math.random() * 2 - 1,1);
            audioElement3.play();
        },4000);

        resonanceAudioScene.setListenerPosition(x,y,z);
        window.addEventListener("keyup", function(event) {

            // Move laugh audio source around when arrow keys pressed
            if (event.which == 37) // left arrow key
                {
                    source.setPosition(laughX -= 0.10, laughY, laughZ);
                }
            if (event.which == 39) // right arrow key
                {
                    source.setPosition(laughX += 0.10, laughY, laughZ);
                }
            if (event.which == 38) // up arrow key
                {
                    source.setPosition(laughX , laughY += 0.10, laughZ);
                }
            if (event.which == 40) // down arrow key
                {
                    source.setPosition(laughX, laughY -= 0.10, laughZ);
                }
            if (event.which == 33) // page up arrow key
            {
                source.setPosition(laughX , laughY, laughZ += 0.10);
            }
            if (event.which == 34) // page down arrow key
            {
                source.setPosition(laughX, laughY, laughZ -= 0.10);
            }
            if (event.which == 32) // space key
            {
                laughX = 0;
                laughY = 0;
                laughZ = 0;
                source.setPosition(laughX, laughY, laughZ);
            }



            // Move the listener left or right on A/D keys
            if (event.which == 65){ //A
                resonanceAudioScene.setListenerPosition(x-=0.1,y,z);
            }
            if (event.which == 68){ //D
                resonanceAudioScene.setListenerPosition(x+=0.1,y,z);
            }
        }, this);

    </script>
</head>
<body>

</body>
</html>


The video

GameDev News, Programming

30. May 2017


Back in Part One of our look at the PlayCanvas HTML5 3D game engine, we started creating our simple bowling game.  We already created our lane and pins.  Now it is time to continue on and create our bowling ball.  Attached to our bowling ball will also be the script the controls the majority of our game.  Let’s jump back in.


Creating the Bowling Ball

This time, instead of importing a model, we are simply going to use a built in procedurally generated mesh.  Simply right click the Root in the Hierarchy view, select New Entity then Sphere.

image

Scale the newly created ball down and position it accordingly.

image

Under the Entity properties, I renamed it from Sphere to BowlingBall.  Right now our ball doesn’t look all that great.  Let’s go ahead and make it a bit shiny.  Right click in the asset area, select New Asset->Material.

image

Select the newly created material from the assets tab.  In the Material panel, I rename it to BowlingBallMaterial.  What I want to do is make the bowling ball a bit shiny.  I am going to leave it white, but if you want to change the color, do so under the Diffuse tab.  Next head on down to the Specular tab.  I used the following settings

image

Finally we need to apply the material to our bowling ball.  In the Hierarchy view, select the BowlingBall entity, under the Model panel, select our newly created Material.

image

Our bowling ball also needs to have a Collision shape and Rigid Body attached to it.

image

image

Be sure to set the Collision object to a Sphere and size the radius to be only slightly larger than our bowling ball model.


Now we have all the pieces needed for our game.  The pins, the lane and the bowling ball.  Now all we need to do is add some logic to the game.  This is done by attaching scripts to entities within our game.  In this case we are going to attach the logic to our bowling ball.


Scripting

With our BowlingBall entity active, add a component and select Script.

image


Scroll down to the Script panel, select Add Script->New Script.

image

Enter a name for the script.

image

Now click Edit Script to launch the script editor.

image

Now enter the following script:

var BallScript = pc.createScript('ballScript');

BallScript.attributes.add('speed', {
    type: 'number',
    default: -8
});

BallScript.prototype.initialize = function() {
    this.entity.collision.on('collisionstart', this.onCollisionStart, this);
    this.app.keyboard.on('keydown', this.onKeyDown, this);
    
    var pins = this.app.root.findByTag("Pin");
    this.startingPositions = [];
    this.startingRotations = [];
    for(var i = 0; i < pins.length; i++){
        this.startingPositions.push(pins[i].getLocalPosition().clone());
        this.startingRotations.push(pins[i].getLocalRotation().clone());
    }
    
    this.ballPosition = this.app.root.findByName("BowlingBall").getLocalPosition().clone();
    this.ballMoving = false;
};

BallScript.prototype.onCollisionStart = function (result) {
    
    if (result.other.rigidbody) {
        if(result.other.name == "BowlingPin")
            this.entity.sound.play("Hit");
    }
};

BallScript.prototype.onKeyDown = function(e) {
    if(e.key == pc.KEY_SPACE || e.key == pc.KEY_W){
        this.entity.rigidbody.applyImpulse(0,0, this.speed);
        this.ballMoving = true;
    }
    if(e.key == pc.KEY_R){
        var pins = this.app.root.findByTag("pin");
        for(var i = 0; i < pins.length; i++){
                pins[i].rigidbody.teleport(this.startingPositions[i],this.startingRotations[i]);
                pins[i].rigidbody.linearVelocity = pc.Vec3.ZERO;
                pins[i].rigidbody.angularVelocity = pc.Vec3.ZERO;
        }
        // now the ball
        this.entity.rigidbody.teleport(this.ballPosition);
        this.entity.rigidbody.linearVelocity = pc.Vec3.ZERO;
        this.entity.rigidbody.angularVelocity = pc.Vec3.ZERO;
        this.ballMoving = false;
    }
    if(e.key == pc.KEY_B){
         // Just the ball
        this.entity.rigidbody.teleport(this.ballPosition);
        this.entity.rigidbody.linearVelocity = pc.Vec3.ZERO;
        this.entity.rigidbody.angularVelocity = pc.Vec3.ZERO;
        this.ballMoving = false;
    }
    if(e.key == pc.KEY_LEFT || e.key == pc.KEY_A){
        this.entity.rigidbody.applyImpulse(-0.2,0,0);
    }
    if(e.key == pc.KEY_RIGHT || e.key == pc.KEY_D){
        this.entity.rigidbody.applyImpulse(0.2,0,0);
    }    
};

// update code called every frame
BallScript.prototype.update = function(dt) {
};


One thing you may notice in the script above is the definition of the speed attribute.  This exposes this variable back to the editor, like so:

image


You may notice the line of code in the script for playing audio when we collide with a pin:

    if (result.other.rigidbody) {
        if(result.other.name == "BowlingPin")
            this.entity.sound.play("Hit");
    }

Now we need to add this audio asset to our bowling ball.  First add the audio file as an asset.  Simply click add asset –> Upload, then upload a WAV file.  Now we need to add a sound component to our BowlingBall entity. 

image


Now scroll down to Slot 1 and add the asset you just uploaded and be sure to set name to Hit.

image


And done.  A complete, rather simple but fully functioning 3D bowling game in just a few minutes.


The Video

Programming , , ,

See More Tutorials on DevGa.me!

Month List

Popular Comments