Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon

12. March 2015

 

I’ve long been a fan of the Phaser HTML5 game library, as my ongoing tutorial series might indicate.  Somewhat recently Phaser started adding premium commercial plugins.  The most recently added plugin adds support for Box2D, the popular 2D physics based library.  This is a commercial plugin (aka, you’ve got to pay for it.  $65 for premium $45 for standard – only difference is number of samples ), but don’t fret, Phaser still has a number of physics systems built-in that are completely free.

 

Box2D is a feature-rich 2D physics system used by thousands of hit games.

This plugin opens-up the power of Box2D directly within Phaser. It has the same user-friendly approach to its API that the rest of Phaser does, making integration and game development a beeze.

image

It uses the excellent box2d-html5 JavaScript port by Isaac Burns. We found that this library had the best performance of those tested, even on mobile.

Development of the plugin was lead by Box2D experts iForce2D - the company responsible for the excellent Box2D visual editor R.U.B.E

 

See the Box2D Plugin Page for More Details

 

The Download includes

  • Getting Started Guide - You'll be coding in next to no time.
  • 90 Code Examples - From games to core mechanics.
  • API Documentation and Box2D User Manual
  • Free Upgrades
  • License free - Use it in commercial games
  • Ready built and minified source files + grunt scripts
  • Delivered via download from FastSpring.com

Try it out

We've added 40 of the Box2D examples to this site.

Run them, play with them and edit the code to get a feel for how it all works.

 

The full release details are available here.

 

I actually like to see this form of monetization.  Developers need to eat and we want  them working to make better and better products.  Keeping the core free while adding premium but optional features as a premium plug-in seems like a good middle line to me.  The key is to keep developing the core free product at the same rate that commercial plugins are added.

News , ,

11. March 2015

 

Copperlicht, a somewhat recently open sourced WebGL game engine has just released version 1.9.

 

Release notes are, shall we say…  terse.  Here they are in the entirity from the Copperlicht forums.

 

Hi,
CopperLicht 1.9 is now available for download. Get it here:
http://www.ambiera.com/copperlic...


Added support for realtime reflecting water surfaces, rendering to textures, inverting the depth test, shader callbacks, pointer lock, and more clearly rendered 2D Overlays.



Have fun with it!

 

Although the archive itself has slightly more detailed release notes:

 

---------------------------------------------
CopperLicht 1.9
---------------------------------------------

- Added realtime reflecting water surfaces.
  There is now a special scene node which renders water surfaces, which can be used to create rivers,
  lakes, and oceans. It is highly configurable, so it can be used to create various,
  realistic looking water surfaces.
 
- Added support for rendering to textures.
  See CL3D.Renderer.setRenderTarget() and CL3D.Renderer.addRenderTargetTexture() for this.

- Added support for inverting the depth test.
  See CL3D.Renderer.setInvertedDepthTest() for this.
 
- Introduced the option to use callbacks for shader settings constants when creating your own materials.

- Full screen with pointer lock now works again on Chrome. Previously, this stopped working
  after Google changed their implementation.

- Fixed 3D sound node to play sound looped even if set to 'play once'

 

Copperlicht is from (one of the?) creator of the popular IrrLicht game engine.  They also have a number of other tools available, such as the CopperCube world editor and irrKlang a cross platform audio library.  It’s one of those products I’ve intended to take a closer look at for some time.

News , ,

15. January 2015

 

I’ve been doing a long running Phaser with TypeScript tutorial series that illustrates basically everything you need to know to create a complete game using the Phaser HTML5 game engine.  I decided to put together a video tutorial showing how to put it all together to make a complete game.

 

Now, keep in mind, the game is incredibly simple… I wanted to keep the entire thing to under an hour after all ( I failed, it’s an hour and a half ), so I had to keep the scope reasonable in size.  So as a result I’ve created Extreme Walking Simulator!  Yeah, you walk… and that’s it actually.  You walk forever and ever in front of the same looping background.  However, you are left with a complete but simple game but most importantly, a framework of code that can be expanded upon to build much more complex games.  It also illustrates program flow, drawing sprites, playing music, changing states, handling input and all the other things a “full” game has to do.

 

In addition to the code, all of the assets used are available on GitHub.  This includes my incredible title music, the Blend files used for the main character and the level scene.  Everything you need to create this game is there in the Assets folder.  Feel free to play around and use it however you want.  That said, the textures just came from Google Image Search, so no clue if there is a copyright on any of them, so don’t use them in a commercial project! I believe all of my Github stuff is set to Creative Commons license…  if it’s not, assume you can do anything you want with it and that you have absolutely no warranty.

 

Ok, enough preamble, let’s jump right in!  The tutorial is available in two parts on YouTube in 1080p ( or embedded below):

 

 

Following are the game itself, then the source listings, finally the two videos in an embedded player.

 

EXTREME WALKING SIMULATOR!

 

EDIT: Removed to prevent music auto playing, to play the game click here instead. Warning, loud

Controls:

  • Click the title screen to get started
  • Tap right arrow to start walking/speed up
  • Tap left arrow to slow down/stop
  • Press ESC to stop the torture!

 

 

The Source Code

 

index.html

<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Hello Phaser</title>
    <link rel="stylesheet" href="app.css" type="text/css" />
    <script src="phaser.js"></script>
    <script src="GameObjects/MyScene.js"></script>
    <script src="GameObjects/Player.js"></script>
    <script src="States/TitleScreenState.js"></script>
    <script src="States/GamePlayState.js"></script>
    <script src="States/GameOverState.js"></script>
    <script src="app.js"></script>
</head>
<body>
    <div id="content"></div>
</body>
</html>

 

app.ts

module Game {
    export class ExtremeWalkingSimulator {
        game: Phaser.Game;


        constructor() {
            this.game = new Phaser.Game(1280, 720, Phaser.AUTO, 'content', {
                create: this.create, preload: this.preload
            });
        }

        preload() {
            // Graphics
            this.game.load.image("title", "Graphics/TitleScreen.png");
            this.game.load.image("scene", "Graphics/scene720p.png");
            this.game.load.image("gameover", "Graphics/GameOver.png");

            //Spritesheets
            this.game.load.atlasXML("HERO_WALKING", "Graphics/Hero_Walking.png", "Graphics/Hero_Walking.xml");
            this.game.load.atlasXML("HERO_IDLE", "Graphics/Hero_Idle.png", "Graphics/Hero_Idle.xml");

            // Audio
            this.game.load.audio("TitleSong", ["Sounds/TitleSong.mp3", "Sounds/TitleSong.ogg",
"Sounds/TitleSong.wav"]); } create() { this.game.state.add("TitleScreenState", GameFromScratch.TitleScreenState, true); this.game.state.add("GamePlayState", GameFromScratch.GamePlayState, false); this.game.state.add("GameOverState", GameFromScratch.GameOverState, false); this.game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; } } } window.onload = () => { var game = new Game.ExtremeWalkingSimulator(); };

 

Player.ts

module GameFromScratch {
    export enum PlayerState { IDLE, WALKING }

    export class Player extends Phaser.Sprite {
        game: Phaser.Game;
        playerState: PlayerState;
        RIGHT_ARROW: Phaser.Key;
        LEFT_ARROW: Phaser.Key;
        ESCAPE: Phaser.Key;
        walkingSpeed: number;

        public static MAX_SPEED: number = 30;

        constructor(game: Phaser.Game, x: number, y: number) {
            this.game = game;

            
            this.walkingSpeed = 0;

            //Wire up input handlers
            this.RIGHT_ARROW = this.game.input.keyboard.addKey(Phaser.Keyboard.RIGHT);
            this.RIGHT_ARROW.onDown.add(Player.prototype.MoveRight, this);

            this.LEFT_ARROW = this.game.input.keyboard.addKey(Phaser.Keyboard.LEFT);
            this.LEFT_ARROW.onDown.add(Player.prototype.MoveLessRight, this);

            this.ESCAPE = this.game.input.keyboard.addKey(Phaser.Keyboard.ESC);
            this.ESCAPE.onDown.add(Player.prototype.GameOver, this);
            super(game, x, y, "HERO_WALKING", 0);

            this.anchor.set(0.0, 1.0);
            this.StartIdle();
        }

        update() {
            if (this.playerState == PlayerState.WALKING) {
                this.x += (this.walkingSpeed / Player.MAX_SPEED) * (60 / this.game.time.elapsedMS);

                // This logic depends on scene being added first.
                var stageWidth = this.game.stage.getChildAt(0).getBounds().width;
                if (this.x > stageWidth * .75)
                    this.x = stageWidth * .25;
            }
            super.update();
        }

        // Worse function name ever!
        MoveLessRight() {
            if (this.playerState != PlayerState.IDLE) {
                this.walkingSpeed--;
                if (this.walkingSpeed > 0)
                    this.animations.currentAnim.speed = this.walkingSpeed;
                else
                    this.StartIdle();
            }
        }

        MoveRight() {
            if (this.playerState == PlayerState.IDLE) {
                this.StartWalking();
            }
            else {
            if (this.walkingSpeed < Player.MAX_SPEED)
                this.walkingSpeed++;
                this.animations.currentAnim.speed = this.walkingSpeed;
            }
        }

        StartWalking() {
            this.playerState = PlayerState.WALKING;
            this.walkingSpeed = 5;
            this.loadTexture("HERO_WALKING", 0);
            this.animations.add("walk");
            this.animations.play("walk", this.walkingSpeed, true);
        }

        StartIdle() {
            this.loadTexture("HERO_IDLE", 0);
            this.playerState = PlayerState.IDLE;
            this.animations.add("Idle");
            this.animations.play("Idle",15,true);
        }

        GameOver() {
            this.game.state.start("GameOverState");
        }

    }
}

 

MyScene.ts

module GameFromScratch {

    export class MyScene extends Phaser.Sprite {
        game: Phaser.Game;
        nextFrame: Phaser.Sprite;

        constructor(game: Phaser.Game, x: number, y: number) {
            super(game, x, y, "scene", 0);
            this.nextFrame = new Phaser.Sprite(this.game, this.width, 0, "scene", 0);
            this.game.add.existing(this.nextFrame);
        }
    }
}

 

TitleScreenState.ts

module GameFromScratch {
    export class TitleScreenState extends Phaser.State {
        game: Phaser.Game;
        music: Phaser.Sound;

        constructor() {
            super();
        }

        titleScreenImage: Phaser.Sprite;

        preload() {

        }
        create() {
            this.titleScreenImage = this.add.sprite(0, 0, "title");
            this.titleScreenImage.scale.setTo(this.game.width/this.titleScreenImage.width, this.game.height
/
this.titleScreenImage.height); this.music = this.game.add.audio("TitleSong"); this.music.volume = 100; this.music.loop = true; this.music.play(); this.input.onTap.addOnce(this.titleClicked, this); } titleClicked() { this.music.stop(); this.game.state.start("GamePlayState"); } } }

 

GamePlayState.ts

module GameFromScratch {
    export class GamePlayState extends Phaser.State {
        game: Phaser.Game;
        player: GameFromScratch.Player;
        myScene: GameFromScratch.MyScene;

        constructor() {
            super();
        }

        preload() {
        }
        create() {
            this.myScene = new MyScene(this.game, 0, 0);
            this.player = new Player(this.game, 0, this.game.height - 50);

            this.game.add.existing(this.myScene);
            this.game.add.existing(this.player);

            this.game.world.setBounds(0,0,this.myScene.width * 2, this.myScene.height);
            this.game.camera.follow(this.player);
        }
    }
}

 

GameOverState.ts

module GameFromScratch {
    export class GameOverState extends Phaser.State {
        game: Phaser.Game;
        gameOverSprite: Phaser.Sprite;

        constructor() {
            super();
        }

        preload() {
        }
        create() {
            this.gameOverSprite = this.add.sprite(0, 0, "gameover", 0);
            this.gameOverSprite.scale.setTo(this.game.width / this.gameOverSprite.width, this.game.height /
this.gameOverSprite.height); this.input.onDown.add(() => { this.game.state.start("TitleScreenState", true); }, this);; } } }

 

 

 

The Videos

 

Part One:

 

Part Two:

Programming , , , , ,

29. December 2014

 

Shortly before the holidays began I received a review copy of Core HTML5 2D Game Programming and amid all the holiday insanity, I’ve been slowly making my way through this title.  As with all reviews, I don’t give star ratings, I think the value of a book is determined mostly by the perspective and requirements of the reader.  OfCoreHTML5 course, some books are just simply bad.  Bad grammar, bad topic choice, bad humour.  Fortunately that is not the case here.  From a technical perspective this is a good book (with one glaring flaw).  Now the question is, is it a good book for you?

 

First let’s talk about the target audience.  This book is not aimed at complete beginners, prior experience with JavaScript and HTML5 is assumed.  Some JavaScript related topics are covered ( dealing with this, profiling/debugging in Chrome, simple inheritance, etc. ) but if you don’t already understand some JavaScript and haven’t ever touched on HTML5 or CSS work, you will be lost.  No prior game programming experience is assumed, although you may struggle a bit with some of the terminology if completely new.  There is however a fairly solid glossary that while get you through.  For more experienced game developers, this probably isn’t the title for you.

 

Ultimately this is a learn by doing book.  Through the course of the book you are putting together a basic platforming game called Snail Bait, built using the assets of the open source Android title Replica Island.  The game is available to be played online at http://corehtml5games.com… or at least, it’s supposed to be.  When I go to that site I get:

 

image

 

Hmmm, that’s unfortunate.  I am not sure if this is an ongoing problem, or just temporary.  Judging by an earlier review on Amazon about the server being unavailable, this is a recurring problem.  It is however a bit of a big problem, as many of the code listings in this book are actually partial, so having access to the complete project is very important.  The book repeatedly references this site, so with it down, so is a great deal of the appeal of this book.  Unfortunately the publisher doesn’t appear to make the code available anywhere else, at least not the book’s version.

 

Now back to the actual contents of the book.  This book covers pretty much all aspects of what you need to make a complete 2D HTML5 game.  One critical thing to understand with this title is everything is created from scratch.  The book makes use of no existing libraries, so you learn how to do things from scratch.  There is merit to learning how to do everything yourself at least initially.  That said, you will probably make a better game using libraries that have already dealt with all the various cross browser issues and optimizations for you.

 

The book does cover a surprising number of topics, starting with handling the game loop and ending with basic network programming.  For each topic there are a number of callout notes on game development or HTML5 idiosyncrasies.  For the most part, they are topical and rarely feel superfluous.  In between it covers animation, graphics, input, hit detection, dealing with mobile (controls and resolutions), particles, audio, easing and more.  The coverage of each topic is fairly comprehensive and easily understood.  One thing you might want to note, this book is entirely about using canvas for rendering, with absolutely no coverage of WebGL.  Given the increasing support for WebGL ( IE and Safari are both finally on board ), this could be a pretty big negative.

 

As I mentioned earlier, the majority of the book is about creating a single game step by step using what you’ve learned up till this point.  The code snippets are clear but without access to the finished whole, trying to figure out how it all fits together is difficult.  There is however one chapter dedicated to putting all the pieces you’ve learned together to make a simpler but complete  game, Bodega’s Revenge.  Unfortunately, these are also partial code listings, so without access to the source code, readers may struggle filling in the pieces.

 

What’s my verdict on this book then?  The book itself is quite good.  If you have some basic JavaScript knowledge and are looking at learning how to do HTML5 canvas based game development from scratch, it’s a very good resource.  There is an impressive amount of information jammed into this book with no obvious missing pieces.  If you are looking at purchasing this title, be certain to check if the site is available before you do! 

 

I would highly suggest the author or publisher make the code available on a much more reliable source, such as Github.

Programming , ,

6. October 2014

 

 

In today’s tutorial we are going to cover the simple but powerful concept of grouping in Phaser.  As the name suggested, grouping allows you to group like minded Sprites together.  Probably easiest to jump right in with a simple example:

 

/// <reference path="phaser.d.ts"/>
class SimpleGame {
    game: Phaser.Game;
    sprite: Phaser.Sprite;
    group: Phaser.Group;
    
    constructor() {
        this.game = new Phaser.Game(640, 480, Phaser.AUTO, 'content', {
            create: this.create, preload:
            this.preload, render: this.render
        });
    }
    preload() {
        this.game.load.image("decepticon", "decepticon.png");
        
    }
    render() {

    }
    create() {
        this.group = this.game.add.group();
        this.group.create(0, 0, "decepticon");
        this.group.create(100, 100, "decepticon");
        this.group.create(200, 200, "decepticon");

        this.game.add.tween(this.group).to({ x: 250 }, 2000,
            Phaser.Easing.Linear.None, true, 0, 1000, true).start();
    }
}

window.onload = () => {
    var game = new SimpleGame();
};

 

And run it:

 

 

As you can see, all objects in the group are updated as the group is updated.  You may notice we created the sprites directly in the group using Group.create, but we didn’t have to.  We could have just as easily done:

 

    create() {
        this.group = this.game.add.group();
        var sprite1 = this.game.add.sprite(0, 0, "decepticon");
        var sprite2 = this.game.add.sprite(100, 100, "decepticon");
        var sprite3 = this.game.add.sprite(200, 200, "decepticon");
        this.group.add(sprite1);
        this.group.add(sprite2);
        this.group.add(sprite3);

        this.game.add.tween(this.group).to({ x: 250 }, 2000,
            Phaser.Easing.Linear.None, true, 0, 1000, true).start();
    }

 

You can also add groups to groups, like so:

 

    create() {
        this.group = this.game.add.group();
        this.group2 = this.game.add.group();

        this.group.create(0, 0, "decepticon");

        this.group2.create(100, 100, "decepticon");
        this.group2.create(200, 200, "decepticon");

        this.group.add(this.group2);

        this.game.add.tween(this.group).to({ x: 250 }, 2000,
            Phaser.Easing.Linear.None, true, 0, 1000, true).start();
    }

 

The above code performs identically to the earlier example.  This can provide a great way to organize your game into logical entities, such as a group for the background, a group for scrolling foreground clouds, a group for bullets, etc.

 

Grouping things together is all nice and good, but if you can’t do anything to the group, it’s mostly just pointless.  Fortunately then, there is quite a bit you can do with a group.  You can loop through them:

 

    create() {
        this.group = this.game.add.group();

        this.group.create(0, 0, "decepticon");
        this.group.create(100, 100, "decepticon");
        this.group.create(200, 200, "decepticon");

        // Set each item in the group's x value to 0
        this.group.forEach((entity) => {
            entity.x = 0;
        }, this, false);

        this.game.add.tween(this.group).to({ x: 250 }, 2000,
            Phaser.Easing.Linear.None, true, 0, 1000, true).start();
    }

 

You can sort them:

 

    create() {
        this.group = this.game.add.group();

        this.group.create(0, 0, "decepticon");
        this.group.create(100, 100, "decepticon");
        this.group.create(200, 200, "decepticon");

        // Sort group by y coordinate descending
        this.group.sort("y", Phaser.Group.SORT_DESCENDING); 
        this.game.add.tween(this.group).to({ x: 250 }, 2000,
            Phaser.Easing.Linear.None, true, 0, 1000, true).start();
    }

 

You can update a property on all group members at once:

 

    create() {
        this.group = this.game.add.group();

        this.group.create(0, 0, "decepticon");
        this.group.create(100, 100, "decepticon");
        this.group.create(200, 200, "decepticon");

        // set the alpha value of all sprites to 50%
        this.group.setAll("alpha", 0.5);

        this.game.add.tween(this.group).to({ x: 250 }, 2000,
            Phaser.Easing.Linear.None, true, 0, 1000, true).start();
    }

 

Running:

 

 

You can get the index of any item within the group:

 

    create() {
        this.group = this.game.add.group();

        var sprite1 = this.group.create(0, 0, "decepticon");
        this.group.create(100, 100, "decepticon");
        this.group.create(200, 200, "decepticon");
        this.group.sort("y", Phaser.Group.SORT_DESCENDING);

        var index = this.group.getIndex(sprite1);
        this.game.add.text(0, 0, "Sprite1's index is:" + index,
            { font: "65px Arial", fill: "#ff0000", align: "center" },
            this.group); // Index should be 2

        this.game.add.tween(this.group).to({ x: 250 }, 2000,
            Phaser.Easing.Linear.None, true, 0, 1000, true).start();
    }

 

Running:

 

 

And as you might be able to see from the above example, you can also add text objects directly to groups!

One other important concept of Groups is being dead or alive.  There are all kinds of methods for checking if an entity is alive or not, like so:

 

    create() {
        this.group = this.game.add.group();

        var sprite1 = this.group.create(0, 0, "decepticon");
        this.group.create(100, 100, "decepticon");
        this.group.create(200, 200, "decepticon");


        sprite1.alive = false;
        this.group.forEachDead((entity) => {
            entity.visible = false;
        }, this);

        this.game.add.tween(this.group).to({ x: 250 }, 2000,
            Phaser.Easing.Linear.None, true, 0, 1000, true).start();
    }

 

This kills off the first of the three sprites, leaving you:

 

 

This tutorial only scratched the surface on what groups can do.  Simply put, they are a convenient data type for logically holding your game objects.  The only thing I didn’t mention is what happens when a group doesn’t have a parent.  In this situation, that parent is the games’ World, which… is a group.

 

Programming , , ,

Month List

Popular Comments