Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon

12. October 2012

Just a heads up, this post has absolutely nothing to do with game development.  It was a little annoyance I ran into today that had a completely unintuitive answer.  I post here so that, thanks to the power of Google, others may learn from my frustration.

 

I have a laptop that is for portability, the one I use when I am out and about ( which is more often then not ), but when I am home, my wife often makes use of it.  For debugging reasons, I hate having unknown processes running in the background, so I always log her account off the next time I log in.  I have done it the same way for years, open Task Manager ( CTRL+SHIFT+ESC ), go to the Users tab, right click the user name and select log off.  As the title suggests, today things didn’t quite work out and I received the error “User username (SessionId=1) could not be logged off.  Access denied.”.  First off, my wife’s name isn’t Bob in case you are wondering.

 

Second, the fix is really easy, just completely confusing why it is a fix at all!

In Task Manager, switch over to the process tab and click “Show processes from all users.”

 

image

 

That’s it, you can now log the other user off.

 

Again, I haven’t got the foggiest idea why this works.  I have that feature checked 99.99% of the time, so I have never run into this problem before.  Obviously more happens behind the scenes than just displaying more processes when you click that button.

 

Anyways, hope that proves useful to someone at some point. 

 

Now back to our regularly scheduled programming.

Totally Off Topic

11. October 2012

Our application hasn’t looked very… applicationy up until this point.  The menu area was basically a space full with “coming soon”.  In this post we will address adding a menu to our HTML app and show how we can pass fire and handle menu click events.

 

First change I suppose, we need a menu.  We will be using the YUI menu plugin MenuNav.  If I am honest, it is unweildy compared to some HTML UI widgets I have used in the past, but since we are using YUI, might as well use it for everything.

 

We make the following changes to mainMenu.Template

 

<div style="width:100%" class="yui3-skin-sam">
    <div id="appmenu" class="yui3-menu yui3-menu-horizontal"><!-- Bounding box -->
        <div class="yui3-menu-content" ><!-- Content box -->
            <ul>
                <li>
                <a class="yui3-menu-label" href="#file">File</a>
                <div id="file" class="yui3-menu">
                    <div class="yui3-menu-content">
                        <ul>
                            <li class="yui3-menuitem" id="menuFileExit">
                                <a class="yui3-menuitem-content" href="#">Exit</a>
                            </li>
                        </ul>
                    </div>
                </div>
                </li>
            </ul>
        </div>
    </div>
</div>

Read the link above for more details about exactly what is going on here.  The key things to notice are the id’s for the menu (appmenu) and menu item (menuFileExit), both of those will be used shortly.  It is also of key importance to give the containing div the class yui3-skin-sam, as this is what brings in all of the YUI3 css and formatting.  You could also add this to the <BODY> tag in editor.View.js, which we may do as we add more YUI controls.  Just be aware that a parent node within the DOM needs to have this class declared.

 

So, that’s is our markup, lets look at the code side of things.  Open up and change mainMenu.View.js

YUI.add('mainMenuView',function(Y){
    Y.MainMenuView = Y.Base.create('mainMenuView', Y.View, [], {
        initializer:function(){
            var results = Y.io('/scripts/views/templates/mainMenu.Template',{"sync":true});
            // No need to compile, nothing in template but HTML 
            // this.template = Y.Handlebars.compile(results.responseText);
            this.template = results.responseText;
        },
        render:function(){
            this.get('container').setHTML(this.template);
            var container = this.get('container');

            var menu = container.one("#appmenu");
            menu.plug(Y.Plugin.NodeMenuNav);

            //Register menu handlers
            var menuFileExit = container.one('#menuFileExit');

            menuFileExit.on("click",function(e){
                alert("Publishing");
                Y.Global.fire('menu:fileExit', {
                    msg:"Hello"
                });
            });

            var menuFileAddSpriteSheet = container.one('#menuFileAddSpriteSheet');
            menuFileAddSpriteSheet.on("click", function(e){
                Y.Global.fire('menu:fileAddSpriteSheet', {msg:null});
            });

            return this;
        }
    });
}, '0.0.1', { requires: ['view','io-base','node-menunav','event','handlebars']});

Here we changed our initializer to load synchronously as well, otherwise the basics are pretty much the same.  Not that we added the ‘node-menunav’ and ‘event’ dependencies to our requires array.  Otherwise the key changes are:

var menu = container.one("#appmenu");
menu.plug(Y.Plugin.NodeMenuNav);

This locates our appmenu div and plugs the NodeMenuNav into it, turning our DIV into a YUI3 style menu.  Basically this is where the magic happens.  Then:

var menuFileExit = container.one('#menuFileExit');
menuFileExit.on("click",function(e){
    alert("Publishing");
    Y.Global.fire('menu:fileExit', {
        msg:"Hello"
    });
});

Next we find our menuFileExit menu item and register an onClick handler for it.  When a click occurs we fire a global event named “menu:fileExit”, with a msg of Hello.  The name menu:fileExit was chosen by me and can be anything.  So, when the user clicks the Exit item in the menu, this event will be fired.  Let’s look at how you handle “catching” this event.  Open up editor.View.js and at the bottom of the initializer() function, add the following code:

Y.Global.on('menu:fileExit', function(e){
   alert(e.msg);
});

Basically, this monitors for a menu:fileExit event being fired, and simple alerts the contents.  This illustrates a simple way to provide a global menu which can be handled across multiple views.

 

Here is our project in action now:

Basically, it is exactly the same as before, but now it has a menu.

 

You can download the complete source code here.

Design, Programming , , ,

9. October 2012

As we saw in the last part, our application is made up of a single view composed of 3 child views.  In this post I am going to focus on the left hand view, which is where the actual map will be drawn.  This is easily the most important part.

 

All I hoped to accomplish today was to get an EaselJS stage integrated in to a YUI View, which with some horrific hacking, I have accomplished.  There are a few very important requirements.

 

First, we need to have a canvas element that EaselJS can work with.

Second, we want the canvas element to take up as much room on the UI as possible.  The right hand view is going to be fixed at 280 pixels in width, so we want the map editing area to consume the rest of the screen.

Finally, I want the whole thing to resize if the window is resized, so our application can support any resolution.

 

To accomplish this, I have altered the person.Template ( the right hand side placeholder for now ), to look like this:

<div style="width:280px;min-width:280px;max-width: 280px;float:right">
    <div align=right>
        <img src="http://www.gamefromscratch.com/image.axd?picture=HTML-5-RPG_thumb_1.png" 
             alt="GameFromScratch HTML5 RPG logo" />
    </div>
    <p><hr /></p>
    <div>
        <h2>About {{name}}:</h2>
        <ul>
            <li>{{name}} is {{height}} feet tall and {{age}} years of age.</li>
        </ul>
    </div>
</div>

Only real change here is the alteration to the parent div.

 

In editor.View.js I made the following simple change that the bottom of the render() function:

Y.one('body').setStyle("margin",0);
return this;

This is simply overriding the YUI default BODY styling, as I do not want any margins, padding or spaces between elements.

 

Then I altered map.Template as follows:

<div style="margin:0px;float:left;display:block" id="panel">
    <canvas width=300 height=300 id="mainCanvas" style="background-color: black;">
        Your browser doesn't support the canvas tag.
    </canvas>
</div>

I needed a named div to access programmatically, so I created one called “panel”.  I also changed the styling on the canvas so the background color would be black, making debugging a bit easier.  The dimensions passed to the canvas are going to be completely ignored.  Why the heck Canvas didn’t support % layout, I will never understand.

 

Finally, the majority of changes are in map.View.js, which I basically re-wrote:

YUI.add('mapView',function(Y){
    var Instance = null;
    Y.MapView = Y.Base.create('mapView', Y.View, [], {
        events:{
          "#mainCanvas": {
              click:function(e)
              {
                  alert("Blah");
              }
          }
        },
        initializer:function(){
            Instance = this;
            var results = Y.io('/scripts/views/templates/map.Template',{"sync":true});
            template = Y.Handlebars.compile(results.responseText);
        },
        prepareCanvas:function(){
            this.resizeEvent();
            createjs.Ticker.setFPS(30);
            createjs.Ticker.addListener(this.gameloop);

            Y.on('windowresize',this.resizeEvent);
        },
        render:function(){
            if(this.template === null)
                this.initializer();
            this.get('container').setHTML(template());
            this.prepareCanvas();
            return this;
        },
        gameloop:function(){
            Instance.stage.update();
            Instance.stage.getChildAt(0).x++;
            if(Instance.stage.getChildAt(0).x > Instance.stage.canvas.width)
                Instance.stage.getChildAt(0).x = 0;
        },
        resizeEvent:function(){
            var container = Instance.get('container');
            var canvas = container.one("#mainCanvas");
            var panel = container.one('#panel');

            var body = Y.one("body");
            var screenWidth = body.get("clientWidth");
            var screenHeight = body.get("scrollHeight");

            var width = Math.floor(screenWidth -280);
            var height = Math.floor(screenHeight );

            canvas.setStyle("width",width);
            canvas.setStyle("height",height);

            this.stage = new createjs.Stage(canvas.getDOMNode());
            // for some reason, easel doesn't pick up our updated canvas size so set it manually
            this.stage.canvas.width = width;
            this.stage.canvas.height = height;

            var shape1 = new createjs.Shape();
            shape1.graphics.beginFill(createjs.Graphics.getRGB(0,255,0));
            shape1.graphics.drawCircle(200,200,200);

            this.stage.addChild(shape1);
        }
    });
}, '0.0.1', { requires: ['view','event','io-base','handlebars']});

 

The variable Instance is a horrible hack, that I intend to replace at some point in the future.  That’s the joy of exercises like this, I can refactor out my hacks later on.  So, why does it exist… well you see, I make a couple of functions that are called back by external code, which completely clobber my this pointer.  I suppose it’s a poor mans singleton of sorts.

 

The end result of this code:

 

 

First thing I did within MapView is declare an event if someone clicks on our canvas ( which needs the id mainCanvas… this is another hackish solution that should possibly be factored away, although frankly, I am OK with requiring the canvas tag to have a certain ID, so I probably wont ) this function is called.  It was simply written to figure out how YUI views handled events.  All it does is pops up an alert with the text Blah.  As you can see, handling element level events in relatively simple, although sadly I couldn’t figure out how to capture document level events here.  Another thing on the todo list.

 

In the initializer function I take a copy of the this pointer in the Instance variable ( *hack* *hack* ), and have changed the template fetching code to no longer be asynchronous, to completely remove some unnecessary race conditions that can result from a network delay retrieving the template. Frankly in this case, async bought us nothing but headaches.

 

prepareCanvas is the method responsible for setting up the easelJS integration.  It starts off by calling resizeEvents, which is where the bulk of the actual work is done.  resizeEvents was factored out to a separate function, because this logic is the same on initial creation as it is when the window is resized.  When resizeEvent() is called, we first find the BODY tag, and get its width and height using clientWidth and scrollHeight.  You would think the obvious value would be clientHeight, but you would be wrong, this is just one of those ways that HTML sucks.  Once we have the width and height, we then calculate our view dimensions, by subtracting the space needed for the other views ( or… will soon for height that is ).  We then set the canvas to those dimensions using setStyle(), which resizes the CANVAS in the browser.  We then create our Stage object from our canvas.  One thing to keep in mind, YUI get() and one() functions return YUI Node objects, not actual DOM objects, so when dealing with 3rd party libraries, you need to access the actual DOM item the node contains, that can be done with .getDOMNode().  Next we manually update the stage.canvas width and height, because of what I can only assume is a bug, EaselJS doesn’t pick up the modifications we made to the Canvas dimenions… who knows, there might be something else going on behind the scenes.  Next we create a circle… just so we have something visible on screen, and add it to our stage.

 

Now that resizeEvents is done, back in prepareCanvas we then set up a Ticker, which is an EaselJS callback mechanism, somewhat like setTimeout.  This is the heartbeat of your application, and due to the setFPS(30) call, it *should* be called 30 times per second.  This is your traditional game loop within the application and will probably be used quite a bit in the future.  Finally we handle windowresize events using the Y.on() handling mechanism, to catch the case the user resizes the screen, and if they do we call resizeEvents ( which being an eventhandler, will clobber all over our this pointer ).

 

Finally, we have the aforementioned gameloop, which is a function that is going to be called every time createjs.Ticker, um… Ticks.  For now we simply update our stage, then find the one and only item on our stage with getChildAt(0), which is our circle, and increment it’s X value until it scrolls off the screen.

 

It seems a bit more complicated than it is, but the basics of most of what we are going to want to deal with is now in place.  We can handle UI events via YUI, can render to the Canvas using the EaselJS library and best of all, take full advantage of the screen resolution, no matter how big or small, and gracefully handle changes in size, something Canvas doesn’t do easily.

 

Figuring out how everything interacted was more of a headache than I expected, but I am reasonably happy with this setup for now.  Of coure, I am going to need to add real functionality to the map view, and have it feed by a Map model instead of just drawing a circle on screen, but all things in time.

 

You can download the complete project as of this point right here.

You can see the project in action by clicking here.  As you resize, so will the canvas element.

Programming, Design , , ,

8. October 2012

 

As per this post I am currently going through the process of creating some simple game creation tools using HTML5, more specifically using the YUI 3 library as well as the EaselJS canvas library.

 

This post illustrates the very skeleton upon which we are going to create our app.  YUI3 provides a full MVC framework which you can use to create your application so I decided to make use of it.  The end result of this code is remarkably minimal, it just creates a single page web application with different views representing different portions of the UI.  Specifically, we will create a top zone where the menu will go, a left hand area where the level editing will occur, then a right hand panel which will change contextually.  I also created a very simple data class, to illustrate how data works within the YUI MVC environment.

 

First off, if you have never heard of MVC, it is the acronym of Model View Controller.  MVC is a popular design practice for separating your application in to logically consistent pieces.  This allows you to separate your UI from your logic and your logic from your data ( the last two get a little gray in the end ).  It adds a bit of upfront complexity, but makes it easier to develop, maintain and test non-trivial applications… or at least, that’s the sales pitch.

 

The simplest two minute description of MVC is as follows.  The Model is your application’s data.  The View is the part of your application that is responsible for displaying to the end user.  The Controller part is easily the most confusing part, and this is the bit that handles communications between the model and view, and is where you actual “logic” presides.  We aren’t going to be completely pure in this level in this example ( MVC apps seldom are actually ), as the Controller part of our application is actually going to be a couple pieces, you will see later.  For now just realize, if it aint a view and it aint a model, it’s probably a controller.

 

It is also worth clarifying that MVC isn’t the only option.  There is also MVVM ( Model-View-ViewModel ) and MVP ( Model-View-Presenter ), and semantics aside, they are all remarkably similar and accomplish pretty much the same thing.  MVC is simply the most common/popular of the three.

 

Put simply, it will look initially more complex ( and it is more complex ), but this upfront work makes life easier down the road, making it generally a fair trade off.

 

Alright, enough chatter, now some code!  The code is going to be split over a number of files.  A lot of the following code is simply the style I chose to use, and is completely optional.  It is generally considered good practice though.

 

image 

At the top level of our hierarchy we have a pair of files, index.html and server.js.  server.js is fairly optional for now, I am using it because I will (might?) be hosting this application using NodeJS.  If you are running your own web server, you don’t need this guy, and won’t unless we add some server-side complexity down the road.

 

index.html is pretty much the heart of our application, but most of the actual logic has been parted out to other parts of the code, so it isn’t particularly complex.  We will be looking at it last, as all of our other pieces need to be in place first.

 

Now within our scripts folder, you will notice two sub-folders models and views.  These predictable enough are where our models and views reside.  In addition, inside the views directory is a folder named templates. This is where our moustache templates are.  Think of templates like simple HTML snippets that support very simple additional mark-up, allowing for things like dynamically populating a form with data, etc.  If you’ve ever used PHP, ASP or JSP, this concept should be immediately familiar to you.  If you haven’t, don’t worry, our templates are remarkably simple, and for now can just be thought of as HTML snippets.  The .Template naming convention is simply something I chose, inside they are basically just HTML.

 

If you are basing your own product on any of this code, please be sure to check out here, where I refactored a great deal of this code, removing gross hacks and cleaning things up substantially!

 

Let’s start off with our only model person.js, which is the datatype for a person entry.  Let’s look at the code now:

 

person.js

YUI.add('personModel',function(Y){
    Y.Person = Y.Base.create('person', Y.Model, [],{
            getName:function(){
                return this.get('name');
            }
        },{
            ATTRS:{
                name: {
                    value: 'Mike'
                },
                height: {
                    value: 6
                },
                age: {
                    value:35
                }
            }
        }
    );
}, '0.0.1', { requires: ['model']});

The starting syntax may be a bit jarring and you will see it a lot going forward.  The YUI.add() call is registering ‘personModel’ as a re-usable module, allowing us to use it in other code files.  You will see this in action shortly, and this solves one of the biggest shortcomings of JavaScript, organizing code.

 

The line Y.Person = Y.base.create() is creating a new object type in the Y namespace, named ‘person’ and inheriting all of the properties of Y.Model.  This is YUI’s way of providing OOP to a relatively un-OOP language.  We then define a member function getName and 3 member variables name, height and age, giving each of the three default values… just cause.  Of course, they aren’t really member variables, they are entries in the object ATTRS, but you can effectively think of them as member variables if you are from a traditional OOP background.  Next we pass in a version stamp ( 0.0.1 ), chosen pretty much at random by me.  Next is a very important array named requires, which is a list of all the modules ( YUI, or user defined ) that this module depends on.  We only need the model module.  YUI is very modular and only includes the code bits you explicitly request, meaning you only get the JavaScript code of the classes you use.

 

So that is the basic form your code objects are going to take.  Don’t worry, it’s nowhere near as scary as it looks.  Now let’s take a look at a view that consumes a person model.  That of course would be person.View.js.  Again, the .View. part of that file name was just something I chose to do and is completely optional.

person.View.js

YUI.add('personView',function(Y){
        Y.PersonView = Y.Base.create('personView', Y.View, [], {
        initializer:function(){
            var that=this,
                request = Y.io('/scripts/views/templates/person.Template',{
                    on:{
                        complete:function(id,response){
                            var template = Y.Handlebars.compile(response.responseText);
                            that.get('container').setHTML(template(that.get('model').getAttrs(['name','age','height'])));
                        }
                    }
                });
        },
        render:function(){
            return this;
        }
    });
}, '0.0.1', { requires: ['view','io-base','personModel','handlebars']});

Just like with our person model, we are going to make a custom module using YUI.add(), this one named ‘personView’.  Within that module we have a single class, Y.PersonView, which is to say a class PersonView in the Y namespace.  PersonView inherits from Y.View and we are defining a pair of methods, initializer() which is called when the object is created and render() which is called when the View needs to be displayed.

 

In initializer, we perform an AJAX callback to retrieve the template person.Template from the server.  When the download is complete, the complete event will fire, with the contents of our file in the response.responseText field ( or an error, which we wrongly do not handle ).  Once we have our template text downloaded, we “compile” it, which turns it into a JavaScript object. The next line looks obscenely complicated:

that.get('container').setHTML(template(that.get('model').getAttrs(['name','age','height'])));

A couple things are happening here.  First we are using that because this is contextual in JavaScript.  Within the callback function, it has a completely different value, so we cached the value going in.  Next we get the property container  that every Y.View object will have, and set it’s HTML using setHTML().  This is essentially how you render a view to the screen.  The parameter to setHTML is also a bit tricky to digest at first.  Essentially the method template() is what compiles a moustache template into actual HTML.  A template, as we will see in the moment, may be expecting some data to be bound, in this case name, age and height which all come from our Person model.  Don’t worry, this will make sense in a minute.

 

Our render method doesn’t particularly do anything, just returns itself.  Again we specify our modules dependency in the requires array, this time we depend on the modules view, io-base, personModel and handlebars.  As you can see, we are consuming our custom defined personModel module as if it was no different than any of the built-in YUI modules.  It is a pretty powerful way of handling code dependencies.

 

Now let’s take a look at our first template.

person.Template

<div style="width:20%;float:right">
    <div align=right>
        <img src=http://www.gamefromscratch.com/image.axd?picture=HTML-5-RPG_thumb_1.png 
alt="GameFromScratch HTML5 RPG logo" />
    </div>
    <p><hr /></p>
    <div>
        <h2>About {{name}}:</h2>
        <ul>
            <li>{{name}} is {{height}} feet tall and {{age}} years of age.</li>
        </ul>
    </div>
</div>

As you can see, a template is pretty much just HTML, with a few small exceptions.  Remember a second ago when we passed data in to the template() call, this is where it is consumed.  The values surrounded by {{ }}  ( thus the name moustache! ) are going to be substituted when the HTML is generated.  Basically it looks for a value by the name within the {{ }} marks and substitutes it into the HTML.  For example, {{name}}, looks for a value named name, which it finds and substitutes it’s value mike in the results.  Using templates allows you to completely decouple your HTML from the rest of your application.  This allows you to source out the graphic work to a designer, perhaps using a tool like DreamWeaver, then simply add moustache markup for the bits that are data-driven.

 

What you may be asking yourself is, how the hell did the PersonView get it’s model populated in the first place?  That’s a very good question.

 

In our application, our view is actually going to be composed of a number of sub-views.  There is a view for the area the map is going to be edited in, a view for the context sensitive editing will occur ( currently our person view ), then finally a view where our menu will be rendered.  However, we also have a parent view that holds all of these child views, sometimes referred to as a composite view. This is ours:

editor.View.js

YUI.add('editorView',function(Y){
    Y.EditorView = Y.Base.create('editorView', Y.View, [], {
        initializer:function(){

            var person = new Y.Person();
            this.pv = new Y.PersonView({model:person});
            this.menu = new Y.MainMenuView();
            this.map = new Y.MapView();
        },
        render:function(){
            var content = Y.one(Y.config.doc.createDocumentFragment());
            content.append(this.menu.render().get('container'));

            var newDiv = Y.Node.create("<div style='width:100%'/>");
            newDiv.append(this.map.render().get('container'));
            newDiv.append(this.pv.render().get('container'));

            content.append(newDiv);
            this.get('container').setHTML(content);
            return this;
        }
    });
}, '0.0.1', { requires: ['view','io-base','personView','mainMenuView','mapView','handlebars']});

The start should all be pretty familiar by now.  We again are declaring a custom module editorView. This one also inherits from Y.View, the major difference is in our initializer() method, we create a Y.Person model, as well as our 3 custom sub-views, a PersonView, a MainMenuView and a MapView ( the last two we haven’t seen yet, and are basically empty at this point ).  As you can see in the constructor for PersonView, we pass in the Y.Person person we just created.  This is how a view gets it’s model, or at least, one way.

 

Our render() method is a bit more complicated, because it is responsible for creating each of it’s child views.  First we create a documentFragment, which is a chunk of HTML that isn’t yet part of the DOM, so it wont fire events or cause a redraw or anything else.  Basically think of it as a raw piece of HTML for us to write to, which is exactly what we do.  First we render our MainMenuView, which will ultimately draw the menu across the screen.  Then we create a new full width DIV to hold our other two views.  We then render the MapView to this newly created div, then render the PersonView to the div.  Finally we append our new div to our documentFragment.  Finally we set our view’s HTML to our newly created fragment, causing all the views to be rendered to the screen.

 

Once again, we set a version stamp, and declare our dependencies.  You may notice that we never had to include personModel, this is because personView will resolve this dependency for us.

 

Lets quickly look at each of those other classes  ( mainMenuView and mapView ) and their templates, although all of them are mostly placeholders for now.

 

mainMenu.View.js

YUI.add('mainMenuView',function(Y){
    Y.MainMenuView = Y.Base.create('mainMenuView', Y.View, [], {
        initializer:function(){
            var that=this,
                request = Y.io('/scripts/views/templates/mainMenu.Template',{
                    on:{
                        complete:function(id,response){
                            var template = Y.Handlebars.compile(response.responseText);
                            //that.get('container').setHTML(template(that.get('model').getAttrs(['name','age','height'])));
                            that.get('container').setHTML(template());
                        }
                    }
                });
        },
        render:function(){
            return this;
        }
    });
}, '0.0.1', { requires: ['view','io-base','handlebars']});

mainMenu.Template

<div style="width:100%">This is the area where the menu goes.  It should be across the entire screen</div>

 

map.View.js

YUI.add('mapView',function(Y){
    Y.MapView = Y.Base.create('mapView', Y.View, [], {
        initializer:function(){
            var that=this,
                request = Y.io('/scripts/views/templates/map.Template',{
                    on:{
                        complete:function(id,response){
                            var template = Y.Handlebars.compile(response.responseText);
                            that.get('container').setHTML(template());
                            //that.get('container').setHTML(template(that.get('model').getAttrs(['name','age','height'])));
                        }
                    }
                });
        },
        render:function(){
            return this;
        }
    });
}, '0.0.1', { requires: ['view','io-base','handlebars']});

map.Template

<div style="width:80%;float:left">
    This is where the canvas will go
</div>

Now, we let’s take a quickly look at server.js.  As mentioned earlier, this script simply provides a basic NODEJS based HTTP server capable of serving our app.

server.js

var express = require('express'),
    server = express();

server.use('/scripts', express.static(__dirname + '/scripts'));

server.get('/', function (req, res) {
    res.sendfile('index.html');
});

server.listen(process.env.PORT || 3000);

 

I wont really bother explaining what’s going on here.  If you are going to use Node, there is a ton of content on this site already about setting up a Node server.  Just click on the Node tag for more articles.

 

Finally, we have index.html which is the heart of our application and what ties everything together and this is the file that is first served to the users web browser, kicking everything off.

index.html

<!DOCTYPE html>

<html>
<head>
    <title>GameFromScratch example YUI Framework/NodeJS application</title>
</head>
<body>

<script src="http://yui.yahooapis.com/3.5.1/build/yui/yui-min.js"></script>
<script src="/scripts/models/person.js"></script>
<script src="/scripts/views/person.View.js"></script>
<script src="/scripts/views/map.View.js"></script>
<script src="/scripts/views/mainMenu.View.js"></script>
<script src="/scripts/views/editor.View.js"></script>

<script>
    YUI().use('app','editorView', function (Y) {

        var app = new Y.App({
            views: {
                editorView: {type: 'EditorView'}
            }
        });

        app.route('/', function () {
            this.showView('editorView');//,{model:person});
        });

        app.render().dispatch();
    });
</script>


</body>
</html>

 

This sequence of <script> tags is very important, as it is what causes each of our custom modules to be evaluated in the first place.  There are cleaner ways of handling this, but this way is certainly easiest.  Basically for each module you add, include it here to cause that code to be evaluated.

 

Next we create our actual Y function/namespace.  You know how we kept adding our classes to Y., well this is where Y is defined.  YUI uses an app loader to create the script file that is served to your clients browser, which is exactly what YUI.use() is doing.  Just like the requires array we passed at the bottom of each module definition, you pass use() all of the modules you require, in this case we need the app module from YUI, as well as our custom defined editorView module.

 

Next we create a Y.App object.  This is the C part of MVC.  The App object is what creates individual views in response to different URL requests.  So far we only handle one request “/”, which causes the editorView to be created and shown.  Finally we call app.render().dispatch() to get the ball rolling, so our editorView will have it’s render() method called, which will in turn call the render method of each of it’s child views, which in turn will render their templates…

 

Don’t worry if that seemed scary as hell, that’s about it for infrastructure stuff and is a solid foundation to build a much more sophisticate application on top of.

 

Of course, there is nothing to say I haven’t made some brutal mistakes and need to rethink everything! Smile

 

Now, if you open it up in a browser ( localhost:3000/ if you used Node ), you will see:

image

 

Nothing too exciting as of yet, but as you can see, the menu template is rendered across the top of the screen, the map view is rendered to the left and the Person view is rendered on the right.  As you can see from the text, the data from our Person model is compiled and rendered in the resulting HTML.

 

You can download the complete project archive right here.

Design, Programming , , ,

5. October 2012

I am about to embark on a bit of a sidetrack here on GameFromScratch.com, hopefully a few of you find it interesting.

 

Basically I am going to start looking at developing game tools using HTML5.  Tooling is a massive part of the game development process and traditionally i've used RAD client only tools like C# + WinForms in this capacity, but HTML5 is becoming increasingly appealing.  I have done a great deal of traditional web development, but nothing really like this.

 

My first project is going to be a dry run on a level editing tool.  I have NO intentions of actually using the end result in a production environment, it is as much a learning experience for me as anything else.  This unshackles me from spending time on stuff like… design, as I intend to throw away everything anyways ( famous last words? ).  Besides, until you have a solid grasp of what you are doing and what problems you are going to face, it's pretty hard to create much of a design anyways.  Now, if I enjoy the experience and the results, I will put a great deal of thought into the design of the finished product.  But when just trying things out, design mostly just gets in the way.

 

This is not the first time I have gone down this road, I've started a number of times and run in to the same problem over and over.  Too much choice, not enough knowledge to make the decision.  I always end up looking at frameworks, design patterns, libraries, toolkits etc, and always end up getting nowhere.  Even picking a client side JS library can consume weeks of your life, throw in a persistence framework, MVC or MVVM framework and months of your life are gone.

 

In the past I went down this road, I looked in to technologies ( such as YUI, Kendo, jQuery, Backbone, Moustache, Dojo, etc… ) and found strengths and faults with all of them.  What I didn't find is success…  This is an area that is anathema to me.  I like to research things, know my options going in and make a decision from a position of some knowledge.  Problem is, there are just too damned many frameworks and options.

 

So I am doing something I never do.  I am picking the technologies up front, and come hell or high water, I am sticking with them until the end.  Therefore for my upcoming project I am going to work with:

- YUI 3 for UI, controls, data, program flow, etc...

- EaselJS for graphics.

 

 

Why YUI 3?  Well because it is pretty much an all encompassing framework, it does about everything, taking decisions away from me.  I don't need to pick a client side technology like jQuery, nor a mobile suite like jQueryMobile, nor a back end like Backbone or ember, package system like require, etc…  YUI pretty much has it all out of the box.

 

Why EaselJS instead of a plethora of game/animation HTML5 libraries?  God knows there are enough of them!  Well, because I haven't used it and I intended to look in to it.

 

So, I am not saying either of these technologies are better than their alternatives, I simply don't have the experience yet to make such a judgement.  I am going with them because, well, they are there.

 

Hope you find the process interesting.

Design, General, Programming

Month List

Popular Comments