Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon

13. February 2016

 

Welcome back to the ongoing Superpowers game engine tutorial series.  In the first part we got Superpowers installed and created our first project, in the second tutorial we look at Actors and Components, the “stuff that makes up your game world”.  Then we did a tutorial on Sprites and Animations give our “stuff” a little bit more visible panache.  In this tutorial we are going to add a Behavior to our component, which is the way you give your “stuff” a bit of logic.  Basically this is how you program your Superpowers game.

 

Just like adding a sprite was a two step process, first we added the image to the scene as an asset, then we created a new component on our actor, scripts work the same way.  Let’s start by creating a new script.  In the left hand window, click the + icon and select Script:

image

This will create a new script and automatically open it in Superpower’s integrated code editor.  Oh, by the way, Superpowers has an integrated code editor!  And it’s actually pretty good, with auto completion, code formatting and more.

image

Now double click your Scene or switch to the Scene tab in the editor and select your Sprite.  In my case I have an animated sprite with a single animation called “Walk” defined, but the Animation set to (None).  See the previous tutorial for more details on this process.  Now let’s add another component to our action, a Behavior.  Following the same process as adding the Sprite Renderer, simply click New Component and select Behavior:

image

There is only one setting in Behavior, the name of the class to add.  Drop down the Class dropdown and choose ScriptBehavior.

image

 

Now we can actually do a bit of coding for this Actor.  I will present the code upfront, and we will go through it after.  Coding in Superpowers by default is using the TypeScript programming language, which is an open source language created by Microsoft to solve some of JavaScripts, shall we say... rough spots.  I’m actually rather a fan of TypeScript myself.  Anyways... here is the code I created:

class ScriptBehavior extends Sup.Behavior {
  awake() {
   
  }

  update() {
    
    if(Sup.Input.isKeyDown("UP")){
      this.actor.move(0,0.1,0);
      if(this.actor.spriteRenderer.getAnimation() !== "Walk"){
        this.actor.spriteRenderer.setAnimation("Walk");
        Sup.log("Set animation to walk");
      }
    }
    if(Sup.Input.isKeyDown("DOWN")){
      this.actor.move(0,-0.1,0);
      if(this.actor.spriteRenderer.getAnimation() !== "Walk"){
        this.actor.spriteRenderer.setAnimation("Walk");
        Sup.log("Set animation to walk");
      }
      
    }
  }
}
Sup.registerBehavior(ScriptBehavior);

 

Our class ScriptBehavior (perhaps we should have named it something a bit less lazy, like CodeThatMovesMySpriteOnKeypress ...) inherits from Sup.Behavior.  You will notice all Superpowers code is in the Sup namespace to prevent name collisions.  The Sup.Behavior class can be thought of as a scriptable component.  It has a number of methods that can be called as part of the program’s lifecycle, in this example we implement awake() and update(), although there are a few more available, such as start() and onDestroy().  awake is called when the behavior is attached to an actor and can basicially be thought of like a constructor, where you do one time setup and initialization logic.  update() on the other hand is called every frame, or every iteration of the game loop, and this is where you implement the logic of your behavior.

 

In this particular example we simple check for keyboard presses using the Sup.Input global object, testing if a key with the value “UP” or “DOWN” is pressed.  If it is, we move slightly up or down in the Y axis.  You can notice in this example that a Behavior can access the Actor it is attached to using the actor property.  Additionally you can see you can access components attached to the actor in a similar way, like we did with the Sprite Renderer via .spriteRenderer.  Finally just to illustrate that it can be done, we log the animation change using Sup.log().  Finally the script is registered with a call to Sup.registerBehavior().

Programming , ,

1. February 2016

 

Ever answered the question “If you could have any super power, what would it be?”  Myself, I’d go with whatever Superman has, as he seems to have the power to do whatever the heck he needs to have the power to do at any given time, so long as people don’t shove rocks from a dead planet at him...  However, if you answered “I want to have the power of collaborative game development!”  1) you need to think bigger 2) you are in luck!

 

Superpowers is a recently open sourced collaborative game engine for making 2D and 3D games, using TypeScript initially with Lua a WIP.  It’s built around HTML5 web technologies but isn’t really a browser game engine.  It’s available for Windows, Linux and Mac OS and it’s completely free, although I’m pretty certain the devs would appreciate some financial support should you find yourself digging it.

 

This on the other hand, as in this document you are reading right now, is the first part of a multi part tutorial series teaching you how to use Superpowers.  We are going to break this tutorial series across several posts, each covering a particular theme.  By the end though, you should be pretty well equipped to make your own game using the Superpowers engine.  So without further ado, let’s begin.

 

Gaining Superpowers

 

Getting the Superpowers Engine

First things first, we need to download and install the Superpowers engine.  There are two ways to go about doing this, from source on Github or the easy way.  We will take the easy way, because hey, it’s easy.  Simply click here and download the most recent Superpowers release.  You have the option of kicking in a bit of cash to help the developers at this point, but you don’t have to.  The key thing is, grab the version that is right for

image

 

I personally chose the Windows 64-bit version, mostly because I’m running 64bit Windows... 

Now that you’ve got the file downloaded, simply extract it to whatever directory you want to run Superpowers from.  In my case I chose d:\dev so Superpowers is installed in D:\Dev\superpowers-0.19.0-win-x64. 

And done.  Not exactly the most difficult install process you are going to encounter, eh?

 

Using Your Powers Wisely

Now locate the file superpowers (+ .exe on Windows) and double click it.

image

This is the Superpowers welcome screen, it may not be immediately obvious but click on the image of the kids to launch the engine proper.

Now we are brought to the Superpowers server window.

image

Creating a Server

Next create a server.  Simply click the ‘Add server’ button.  Don’t worry, we only need to do this part once.

image

You will then be prompted to name your server, do so.  By the way Superpowers team, you’ve got a bug in your button label here...  Once you’ve named your server, click ‘Add Server’

image

It will then prompt you for an IP address, and defaults out to 127.0.0.1:4237, which is a loopback or friendly way of saying “this machine”.  If you don’t have any reason to change this, don’t.  If you are running on a server and are going to be working externally with other developers you will use whatever your servers external IP address is instead. Click ‘Add server’ again.

image

 

TADA, you’ve got your own Superpower server:

image

 

Now double click your server to launch the Superpowers project manager.  We will be asked to create a user account:

image

 

After you click Log in:

image

 

Creating a New Project

Now we create a new project... bet you can’t guess how.  Ok, here’s how, click New project.

image

 

Next name your project, optionally describe your project and pick wether to use a template or not.  When complete click Create:

image

And finally, TADA, the Superpower editor:

image

 

Alright, that’s it for this tutorial.  We now have Superpowers installed, running and created our first project.  Click Next Part below to continue on to the, um, next part.

 

Next Part

Programming , ,

30. November 2015

 

Along side the release of Visual Studio 2015 SP1, Microsoft shipped a new version of the TypeScript programming language.  I personally am a huge fan of TypeScript, but I am not entirely certain I am onboard with the changes introduced in 1.7.  Speaking of those changes, here they are, taken from the MSDN TypeScript blog:

 

Async/Await for ES6 targets

With the 1.7 release, TypeScript now supports Async functions for targets that have ES6 generator support enabled (e.g. node.js v4 and above). Functions can now be prefixed with the async keyword designating it as an asynchronous function. Theawait keyword can then be used to stop execution until an async function's promise is fulfilled. Following is a simple example:

"use strict";
// printDelayed is a 'Promise<void>'
async function printDelayed(elements: string[]) {
    for (const element of elements) {
        await delay(200);
        console.log(element);
    }
}
async function delay(milliseconds: number) {
    return new Promise<void>(resolve => {
        setTimeout(resolve, milliseconds);
    });
}
printDelayed(["Hello", "beautiful", "asynchronous", "world"]).then(() => {
    console.log();
    console.log("Printed every element!");
});

We are working on bringing async/await support in TypeScript for other targets, including a breadth of browsers, which might not have ES6 generators support. For more information on current implementation of async/await and how to use it, see our previous blog post.

Polymorphic this Typing

After much community discussion and feedback, TypeScript 1.7 adds a new polymorphic this type. A this type can be used in classes and interfaces to represent some type that is a subtype of the containing type (rather than the containing type itself). This feature makes patterns such as hierarchical fluent APIs much easier to express.

interface Model {
    setupBase(): this;
}
interface AdvancedModel extends Model {
    setupAdvanced(): this;
}
declare function createModel(): AdvancedModel;
newModel = newModel.setupBase().setupAdvanced(); // fluent style works 

For a deep dive on this typing, checkout the TypeScript Wiki.

As a part of supporting the feature, TypeScript 1.7 has made changes in inferring the type from this. In a class, the type of the value this will be inferred to the this type, and subsequent assignments from values of the original type can fail. As a workaround, you could add a type annotation for this. A code sample with recommended work around, along with a list of other potentially breaking changes is available at GitHub.

ES6 Module Emitting

TypeScript 1.7 adds es6 to the list of options available for the --module flag and allows you to specify the module output when targeting ES6. This provides more flexibility to target exactly the features you want in specific runtimes. For example, it is now a breeze to target Node.js v4 and beyond, which doesn't support ES6 modules (but does support several other ES6 features).

//tsconfig.json targeting node.js v4 and beyond
{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es6"
    }
} 

ES7 Exponentiation

Finally, a little syntactic sugar! The ECMAScript committee recently moved the Exponentiation Operator proposal to stage 3. So we decided it was ready for TypeScript to adopt, and added support for it in TypeScript 1.7.

let squared = 2 ** 2;  // same as: 2 * 2
let cubed = 2 ** 3;  // same as: 2 * 2 * 2 

let num = 2;
num **= 2; // same as: num = num * num; 

Say goodbye to Math.pow()!

 

I hate Hate HATE the this operator in JavaScript, I think it is among the single biggest mistakes in language design I have ever encountered.  I really hope a polymorphic this in TypeScript isn’t a step down the road to AwfulVille™.  That said, I have faith in Anders Hejlsberg to do the right thing when it comes to language development, so I will take a wait and see approach.

 

You can get Typescript 1.7 as part of the Visual Studio 2015 service pack, or update using npm.

GameDev News

22. October 2015

 

As part of the ongoing Tiled Map Editor tutorial this part looks at using Object Layers, which can be used to interface your tiled map with your games code.  This particular example includes the code using TypeScript and the Phaser game library.  If you need more information on Phaser I’ve done a tutorial series here.

 

The video of this tutorial is available here or embedded below.

 

The 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="app.js"></script>
</head>
<body>
    <div id="content"></div>
</body>
</html>

app.ts

/// <reference path="phaser.d.ts"/>


class ObjectEntity {
    height: number;
    name: string;
    properties: any;
    rectange: boolean;
    rotation: number;
    type: string;
    visible: boolean;
    width: number;
    x: number;
    y: number;
}

class SimpleGame {
    game: Phaser.Game;
    map: Phaser.Tilemap;
    layer: Phaser.TilemapLayer;
    player: Phaser.Sprite;
    winZone: Phaser.Rectangle;

    constructor() {
        this.game = new Phaser.Game(640, 480, Phaser.AUTO, 'content', {
            create: this.create, preload:
            this.preload, update: this.update, render: this.render
        });
    }
    preload() {
        this.game.load.tilemap("ItsTheMap", "newMap.json", null, Phaser.Tilemap.TILED_JSON);
        var img = this.game.load.image("HF2_A2", "HF2_A2.png");
        this.game.load.image("Decepticon", "decepticonLarge.png");
    }
    update() {

        if (this.winZone.contains(this.player.x + this.player.width/2,this.player.y + this.player.height/2))
            alert("You Win!");

    }
    render() {
    }
    create() {
        this.map = this.game.add.tilemap("ItsTheMap", 32, 32, 64, 32);
        this.map.addTilesetImage("HF2_A2","HF2_A2");

        this.map.createLayer("Background").resizeWorld();

        this.player = new Phaser.Sprite(this.game, 0, 0, "Decepticon");
        this.player.width = 64;
        this.player.height = 64;
        this.game.world.addAt(this.player, 1);

        this.game.camera.follow(this.player);

        var something = this.map.objects["GameObjects"][0];
        var start = <ObjectEntity>this.map.objects["GameObjects"][0];
        var end = <ObjectEntity>this.map.objects["GameObjects"][1];


        this.winZone = new Phaser.Rectangle(end.x, end.y, end.width, end.height);

        this.player.position.set(start.x, start.y);

        this.game.input.keyboard.addKey(Phaser.Keyboard.LEFT).onUp.add(() => {
            this.player.position.add(-32, 0);
        });

        this.game.input.keyboard.addKey(Phaser.Keyboard.RIGHT).onUp.add(() => {
            this.player.position.add(32, 0);
        });

        this.game.input.keyboard.addKey(Phaser.Keyboard.UP).onUp.add(() => {
            this.player.position.add(0,-32);
        });

        this.game.input.keyboard.addKey(Phaser.Keyboard.DOWN).onUp.add(() => {
            this.player.position.add(0, 32);
        });
    }
}

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

 

 

The Video

 

Art, Design, Programming , , , ,

18. September 2015

 

The following is a video showing the process discussed in this earlier tutorial.  For all the source code mentioned, see the earlier link.

 

 

The video is also available in high definition here.

Programming , , ,

Month List

Popular Comments