Friday, April 24, 2015

Modular MVC using LoopBack/Express

Express is pretty simple to use, and simplicity comes at a price. For me, that price is organization. All the views are in one big folder, as are public assets. I prefer a modular organization, and reading this post (https://strongloop.com/strongblog/bypassing-express-view-rendering-for-speed-and-modularity/) pointed out that the key is that the rendering engine breaks modularity.

So I created a top level folder named application, and moved the views out of the server folder, and static content out of clent:

project
| -- application                modules
|     | -- index.coffee  module bootstrap
|     | -- modules.json  module config
|     + -- user          
|           | -- client/public
|           | -- server/boot
|           | -- server/views
|     + -- game          
|           | -- client/public
|           | -- server/boot
|           | -- server/views
| -- client                     not used
| -- common/modules   unchanged
| -- server                     removed views
| -- .bowerrc                   the usual
| -- .gitignore                 ditto

In the main server/server.coffee, after the standard boot:

boot app, __dirname
...
modules = require('../application')
modules app

This runs application/index.coffee, which boots each module, based on the config:
./modules.json:

{
  "user": true,
  "game": true
}

./index.coffee:
fs = require('fs')
path = require('path')
loopback = require("loopback")

module.exports = (app) ->

  for name, enabled of require('./modules.json')

    # -- Boot the module scripts  --
    if enabled
      do (name) ->  # closure on name value
        mod = {}    # and for communication within module

        for filename in fs.readdirSync(path.join(__dirname, name, 'server/boot'))
          if path.extname(filename) in ['.coffee','.js']
            boot = require(path.join(__dirname, name, 'server/boot', filename))
            boot(app, mod)

    # -- Mount static files --
    app.use loopback.static(path.join(__dirname, name, 'client/public'))


All of the content is created from each applications server/view and client/public folders.
Each application has it's own server/boot folder, where I put controllers and rendering engine.
And if I do it right, I can drop my used module into another project and be good to go.

An extra benefit - my user module uses jade templating, while my game module is using liquid templating. Why would you want more than 1 templating engine? Well, I'm lazy. My user module is essentially the loopback-example-passport github repo that I'm tweaking a bit. All of their views use jade. But, I prefer using liquid for my own development.

The full project (wip) is over here - https://github.com/darkoverlordofdata/games. 

Friday, April 17, 2015

Using View Layouts in CodeIgniter

I'll show you how tp extend CodeIgniter's loader to enable layout views.

CodeIgniter doesn't use a template engine. I think their argument that PHP is already a templating language is acceptable for small projects - my team is just me, templates would just add to project complexity and maybe impact performance.

But I do miss the concept of layouts. Instead, codeigniter uses this idiom:

    $this->load->view('templates/header', $data);
    $this->load->view('pages/'.$page, $data);
    $this->load->view('templates/footer', $data);

That's ugly. As your site grows, and you need to sync css to javascript libraries between headers and footers, this results in maintenance pains. I'd prefer to embed my content in a layout:

  <html>
    <head>
        <title>Hello</title>
    </head>
    <body>
        <h1>Hey!</h1>
        <div class="content">
        <?php echo $content; ?>
        </div>
        <hr />
        <em>© 2014</em>
    </body>
</html>

And then invoke like this ...

    $this->load->setLayout('layouts/main');
    $this->load->view('pages/'.$page, $data);


Well, it's pretty simple to extend CodeIgniter to do this by customizing the view load behavior. First, we'll create the class ./application/core/MY_Loader.php (MY_ is our customization namespace), and add a couple member variables:

    class MY_Loader extends CI_Loader {

        var $layout = '';
        const EXT = '.phtml';

    }

The $this->layout variable holds the file path to the layout. I am also using a different file extension for my views. This keeps me mindful not to burden my views with too much logic. It's too easy to get mixed up when with the views and code have the same file extension.

 Now the constructor:

    function __construct() {
        parent::__construct();
        
        $layout = config_item('layout');
        if ($layout <> '') {
            $this->layout = $layout.self::EXT;
        }
    }    

Make sure to call the core class constructor, and fetch a default layout value from the site configuration (we'll see how to add that below). We'll add a convenience method to set the layout manually:

    function setLayout($layout) {
        $this->layout = $layout.self::EXT;
    }

And finally, we override the view method of loader:

    function view($view = '' , $view_data = array(), $return = FALSE) {  
        if ($view <> '') {
            $view = $view.self::EXT;
        }
        if ($this->layout <> '') {
            $view_data['content'] = parent::view($view, $view_data, TRUE);
            return parent::view($this->layout, $view_data, $return);
        } else {
            return parent::view($view, $view_data, $return);
        }
    }

If there is no layout, we use the standard process. Otherwise, we first merge the view and data to create partial content, and them inject that into the layout.

Remember the configuration? We add the following line to the end of ./application/config/config.php:

$config['layout'] = 'layouts/default';

Of course, we also have to create our default layout: views/layouts/default.phtml - I'll leave that up to you.

 You can find more about extending codeigniter at http://www.codeigniter.com/user_guide/general/core_classes.html

Monday, April 13, 2015

CodeIgniter Is Back!

CodeIgniter just released version 3.0 a couple of weeks ago. I was sad to see EllisLab pull support, but it's been picked up by British Columbia Institute of Technology

Hooray! CodeIgniter is my go to php framework. To celebrate, I installed it to OpenShift. To facilitate this, I've forked a copy of the CodeIgniterQuickStart , updating it for 3.0.0

I've also moved assets and index.php to a public folder, which OpenShift accepts as the DocumentRoot. This simplifies asset management  - style sheets are now in css, not in assets/css. Plus, the php code isn't as exposed.

To use this quickstart, select Add Application from the OpenShift console, and select a CodeIgniter 2 application. Then, enter this repository url into the Source Code field: https://github.com/darkoverlordofdata/CodeIgniterQuickStart, and click Create Application.


Sunday, April 12, 2015

Using Ash with Phaser

The coffeescript port of Ash now works as a Phaser plugin.  To show you how it works, I've taken the old standby Making your first Phaser game and converted it to use Ash.

We start out pretty much like any phaser game, with one exception - you'll note that I haven't given phaser an update function:

    @game = new Phaser.Game(@width * @scale, @height * @scale, Phaser.CANVAS, '',
      init: @init, preload: @preload, create: @create)


Our init and preload are also no different:

  init: =>
    @game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL
    @game.scale.minWidth = @width * @scale
    @game.scale.minHeight = @height * @scale
    @game.scale.maxWidth = @width * @scale
    @game.scale.maxHeight = @height * @scale
    @game.scale.pageAlignVertically = true
    @game.scale.pageAlignHorizontally = true
    return

  preload: =>
    @game.load.image 'sky', 'assets/sky.png'
    @game.load.image 'ground', 'assets/platform.png'
    @game.load.image 'star', 'assets/star.png'
    @game.load.spritesheet 'dude', 'assets/dude.png', 32, 48
    return

Things change once we get to create.

  create: =>

    game = @game

    @stars = game.add.group()
    @platforms = game.add.group()
    @scoreListener = new Phaser.Signal()
    @cursors = game.input.keyboard.createCursorKeys()

    @ash = game.plugins.add(ash.ext.PhaserPlugin, Nodes, Components)


The Ash plugin take 2 parameters: Nodes and Components - these are simply hashed lists. A components are simple classes, for example the Collision component:

Collision: class Collision
    a       : null
    b       : null
    constructor: (@a, @b) ->

While nodes are simply property lists

Nodes = do ->
  CollisionNode: class CollisionNode
    collision : Components.Collision
  CollectorNode: class CollectorNode
    collector : Components.Collector
  PlayerNode: class PlayerNode
    player    : Components.Player

After initializing the ash plugin, we create our entities and start our systems. It's these systems that take the place of the update function:

    @createBackground('sky')
    @createGround('ground')
    @createLedge('ground', 400, 400)
    @createLedge('ground', -150, 250)
    @createStars('star', 70, 0, 12, 10)
    @createPlayer('dude', 150, 350)
    @createScore(16, 16, 'score: 0', fontSize: '32px', fill: '#000')

    @ash.addSystem(new CollisionSystem(this), SYSTEM_RESOLVE_COLLISIONS)
    @ash.addSystem(new PlayerMovementSystem(this), SYSTEM_MOVE)
    @ash.addSystem(new CollectorSystem(this), SYSTEM_UPDATE)
    return


When creating the entity, I use a parallel construction, building the phaser game object alongside the ash entity:

createBackground: (key) ->

    # phaser sprite
    sprite = @game.add.sprite(0, 0, key)
    @game.world.sendToBack(sprite)
    @game.physics.enable(sprite, PHYSICS_TO_USE)

    # ash entity
    sky = new ash.core.Entity('sky').add(sprite)
    @ash.addEntity(sky)
    return


You can get all the code needed for this demo at https://gist.github.com/darkoverlordofdata/eb26c00c6c2bf05da1ba

It's also include as the example program for my phaser game controller plugin.



Friday, April 3, 2015

Getting the Physics Step Right

After porting the Ash framework to coffeescript it seemed to me the next logical step was to use Box2d to calculate the asteroid movement. This actually made the game fun - now the asteroids bounce off each other, and stuff...

But performance on android suffered. Especially in the Cocoon Canvas+ environment, which puzzled me because I'm using the native Box2d plugin. Until I found this excellent post from Allan Bishop, which explained very well what I was running into.

I had been naively calling world.Step() from my game loop, which is driven by requestAnimationFrame. This works ok in the chrome desktop browser, until there is a performance load, and not ok at all in chrome for android. The problem is, when performance suffers, the frame rate starts to slip, resulting in the 'jiggly' physics I was seeing. There are a couple of ways to work with this:

  • Fixed Time Step
  • Interpolate the time delta to sync with the frame rate

So, splitting my PhysicsSystem into two classes, I implemented both. 

One, FixedPhysicsSystem, uses setInterval to cause world.Step() to be called every 1/60 seconds. 
The other, the SmoothPhysicsSystem - implements Allan's ActionScript example.

As it turns out, I need both.  When using the Cocoon Box2d plugin, using an absolute value of 1/60 to advance the physics works well, but interpolation makes it worse. I found the opposite to be true in the browser. So I check to see if the plugin is present, and use the appropriate physics system class.