And the best offline blogging software for Mac OS is…….. MarsEdit

29. October 2012

 

Since I've been working on a Mac more and more often these days, I've been looking for an alternative to the wonderful Windows Live Writer for Windows.  I started with a trial of MarsEdit, which I really liked, except it's inability to display formatted source code ( a big deal for me ), its lack of tagging ( not a really big deal, but a nuisance ) and the lack of image formatting options.

 

Then I found and discovered Adobe Contribute, which has a 100$ price tag.  It started off strong but quickly took a jump off a cliff into the land of truly awful.  It seems to be poorly supported by Adobe, has documented features that don't appear to exist anymore, has some gigantic bugs ( such as the Paste menu never being enabled! ).  It did however have incredible table formatting tools!  I know in the age of CSS, table is a bit of a swear word, but damned if a lot of your data isn't in a tabular format.  The image formatting options were easily the best of all packages I've used, including Live Writer.  But good tables and good image positioning tools don't even come close to making up for the brutal flaws, especially at a 100$ price point.

 

I then tried out Qumana, a completely free option:

Qumana screenshot

At first glance, it pushes all the buttons.  It doesn't support tags ( only Live Writer seems to ), but image formatting is decent, and you can directly edit the HTML of your post, so if you know HTML, the sky is the limit.  I attempted to write the previous post with Qumana and ran in to a gigantic deal breaker attempting to insert an IFrame… you can't.  I pasted the HTML code for a Youtube video, then when I switch back to WYSIWG view, poof gone.  Game over.

 

So then, back to MarsEdit, which I went ahead and purchased.  In the end, MarsEdit was easily the best option of what is available for Mac.  The biggest sellable point was the ability to drop to and edit HTML, which is nicely preserved when switching back to rich text mode.

 

Now, Red Sweater, if you are listening, please add the ability to create plugins, or failing that, the ability to post formatted source code.  Also, tag support would be nice!

 

If you are a MarsEdit user, and currently post code samples on your blog, how are you doing it?

General




Creating game creation tools using HTML5: Adding a sprite sheet upload dialog

17. October 2012

 

A level is made up of sprites and sprites come from somewhere.  In our editor, we are going to allow the user to “upload” multiple image files containing sprite sheets.  However, are server is not required and that is going to require a bit of work.  Also, we are going to need some form of UI where users can upload the spritesheet, without cluttering our main UI too much, so we will implement it as a modal dialog box.

 

Well, let’s get to it.  First lets create a data type for holding our sprite sheet collection.  For now, a spritesheet is simply an image, the dimensions of each sprite and a name.  In your models folder create a new file named spriteSheet.js

spriteSheet.js

 

YUI.add('spriteSheet',function(Y){
    Y.SpriteSheet = Y.Base.create('spriteSheet', Y.Model, [],{
            count:function(){
                return this.get('spritesheets').length;
            },
            add:function(name,width,height,img){
                this.get('spritesheets').push({name:name,width:width,height:height,img:img});
            }
        },{
            ATTRS:{
                spritesheets: {
                    value: []
                }
            }
        }
    );
}, '0.0.1', { requires: ['model']});

Nothing really special.  Our spritesheets attribute is just an empty array for now.  We also included a pair of methods, add, for adding a new spritesheet and count for getting the current count of spritesheets already declared.  Everything else here should already be familiar at this point.

 

Now we want to create a dialog that will be displayed when the user wants to add a spritesheet.  As a bit of a spoiler, here is what we are going to create:

image

This isn’t a View and it isn’t a model, so we create a new folder called classess and create the long-winded file named AddSpriteSheetDialog.js

AddSpriteSheetDialog.js

YUI.add('addSpriteSheetDialog', function(Y){

    Y.AddSpriteSheetDialog = new Y.Base();
    var spriteSheets = null;
    Y.AddSpriteSheetDialog.show = function(ss,onComplete){
        spriteSheets = ss;
        var panel = new Y.Panel({
            width:500,
            height:300,
            centered:true,
            visible:true,
            modal:true,
            headerContent:'Select the image file containing your sprite sheet',
            bodyContent:Y.Node.create(
                "<DIV>\
                <input type=file id=spritesheet /> \
                <br /> <div id=imgName style='padding-top:25px;padding-bottom:25px'> \
                Click above to select a file to download</div>\
                <br />Sheet name:<input type=Text id=name size=30 value=''> \
                <br />Sprite Width:<input type=Text id=width size=4 value=32> \
                Sprite Height:<input type=Text id=height size=4 value=32> \
                <br /><input type=button id=done value=done />\
                </DIV>\
                "
            ),
            render:true
        });

        var fileUpload = Y.one("#spritesheet");
        fileUpload.on("change", Y.AddSpriteSheetDialog._fileUploaded);

        var buttonDone = Y.one("#done");
        buttonDone.on("click", function(){
            panel.hide();
            onComplete();
        })
        panel.show();

    };

    Y.AddSpriteSheetDialog._fileUploaded = function(e){
        if(!e.target._node.files[0].type.match(/image.*/)){
            alert("NOT AN IMAGE!");
            return;
        }
        var selectedFile = e.target._node.files[0];
        var fileReader = new FileReader();

        var that=this;
        fileReader.onload = (function(file){
            return function(e){
                if(e.target.readyState == 2)
                {
                    var imgData = e.target.result;
                    var img = new Image();
                    img.onload = function(){
                        Y.one('#imgName').set('innerHTML',selectedFile.name + " selected");
                        var name = Y.one('#name').get('value');
                        var width = Y.one('#width').get('value');
                        var height = Y.one('#height').get('value');
                        spriteSheets.add(name,width,height,img);
                    }
                    img.src = imgData;
                }
            };

        })(selectedFile);
        fileReader.readAsDataURL(selectedFile);

    };


},'0.0.1', {requires:['node','spriteSheet','panel']});

The editorView owns the spritesheet collection, and passes it in to the show() method of AddSpriteSheetDialog.  We also pass in a callback function that will be called when we are done.

We start off creating the panel which is a Y.Panel.  Most of the properties should be pretty straight forward, headerContent is the title and bodyContent is either the ID of the object to render the panel in, or in our case, we actually create a new node with our dialog HTML.  We then wire up a change handler on our file upload button, this will fire when a file is uploaded and call the _fileUploaded function.  We then wire up the Done button’s on click handler to hide the panel then call the callback function that was passed in.  Finally we display the panel.

 

When the user clicks the Choose File button, _fileUploaded is called.  First thing we check to make sure it is an image that is uploaded and error out if it isn’t.  We then want to read the selected file, which we do with the FileReader api.  Word of warning, this isn’t completely supported in every browser… frankly though, I don’t care about supporting IE in a project like this, cross browser support takes all of the fun out of web app development! Smile

 

Next is well… JavaScript at it’s most confusing. We are registering an onload event that will be fired once the file has been loaded, which in turn fires off an anonymous method.  It checks the readystate of the file to make sure it is ready and if so, our “uploaded” file will be in e.target.result.  We then create an Image object, then register yet another onload handler, this one for when the image has completed loading.  Once the user has uploaded the file, its finished loading and populated in our newly create Image, we then get the width, height name and our newly populated image and at it to the screenSheets object we passed in during show().  Yes, this is a bit screwy of an interface, in that you need to populate the text fields before uploading the interview.  I will ultimately clean that up ( and add edit ability ), but it would needlessly complicate the code for now.  Finally, no that our fileReader.onload() event is done, we actually read the file now with readAsDataUrl() the file that was chosen, which fires off the whole onload event handler in the first place.   Welcome to asynchronous JavaScript programming!  Don’t worry, if this is new to you, thinking async will come naturally soon enough…

 

So, that is how you can create a modal dialog to edit app data.  Now we wire it up and deal with a bit of a gotcha.

 

The gotcha first…  the Panel dialog requires a parent HTML element in the DOM to have a YUI skin CSS class declared.  At the bottom on the render function in editor.View.js add the following code:

Y.one('body').setStyle("margin",0);
Y.one('body').setStyle("overflow","hidden");
// The below needs to be added as some controls, such as our add sprite dialog, require a parent container
// to have the YUI skin defined already
Y.one('body').setAttribute("class","yui3-skin-sam");
return this;

This adds the yui3-skin-sam class to the page’s body, which brings in all the styling for the Panel ( and other YUI widgets ).

 

While we are in editor.View.js, we wire up a menu handler for when the user clicks the add spritesheet button ( we will add in a second ).  That handler is basically the same as the menu:fileExit handler we created earlier.  Right below that handler in the initializer function, add the following:

 

var that = this;
Y.Global.on('menu:fileAddSpriteSheet',function(e){
    var dialog = Y.AddSpriteSheetDialog.show(that.spriteSheets,function(){
        var sheet = that.spriteSheets.get("spritesheets")[0];
        console.log(sheet);
    });
});

There is the that=this hack again, there are alternatives ( you can pass the context in to the Y.Global.on event handler ), but this is a fair bit easier at the end of the day, as we would lose this again when the callback is called.  Otherwise, when the menu:fileAddSpriteSheet event is received, we simply call AddSpriteSheetDialog.show(), passing in our spritesheet and the function that is called when the panel is complete.  For now we simply log the spritesheet out to the console to prove something changed.

We also need to add the SpriteSheet to our editor.View.js, like so:

 

 Y.EditorView = Y.Base.create('editorView', Y.View, [], {
        spriteSheets:new Y.SpriteSheet(),
        initializer:function(){

 

Now we need to add the menu item.  First add it to the template mainMenu.Template,like so:

<ul>
    <li class="yui3-menuitem" id="menuFileAddSpriteSheet">
        <a class="yui3-menuitem-content" href="#">Add SpriteSheet</a>
    </li>
    <li class="yui3-menuitem" id="menuFileExit">
        <a class="yui3-menuitem-content" href="#">Exit</a>
    </li>
</ul

And we wire it up in the mainMenu.View.js, add the bottom of render() add the following code:

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

Oh, and our newly added script AddSpriteSheetDialog.js is added to index.html to guarantee it gets loaded and evaluated.

 

And done.  We now added a dialog for adding sprite sheet images, and can store the image results locally without requiring any server interaction at all.

 

Here is the end result, select File->Add Spritesheet to bring up the newly created dialog:

 


You can download the entire updated source code here.

One step closer to a full web based game editor, one very tiny step. Smile

Programming, General , , ,




The near future of the JavaScript language

14. October 2012

 

I don’t think there are many people out there that would argue that JavaScript isn’t an important language.  It certainly is, and with the recent death of Flash and Silverlight in the browser and the hype behind HTML5, to say nothing of Node, it is actually getting more popular

 

I also don’t think there are many people out there that would argue that JavaScript is a heavily broken language too.  As systems written in JavaScript become larger and more complex, the language flaws become more and more pronounced.  Just as C++ ultimately came about from C’s (arguable by some) inability to deal with complexity, a number of companies and groups are looking at possible successors to JavaScript.  Generally all of these languages are backward compatible with JavaScript in some form.  Let’s take a look at the contenders for the short term future of JavaScript.

 

 

ECMAScript 6 AKA Harmony AKA ES.next

 

When talking about the future of JavaScript, the most logical place to start is … well, the future of JavaScript, the next version.  The spec is a work in progress and you can read it here, the most recent revision as of writing (September 27th, 2012).  It would seem obvious that the next version of JavaScript would be ECMAScript 6, but don’t bet the farm just yet.  After all, ECMAScript 6 is effectively a scaled back version of ECMAScript 4, while ECMAScript 5 (the JavaScript version in common usage today), is essentially a fork of ECMAScript 3.  Firefox and Chrome already support bits of ECMAScript 6, so it’s future is quite bright, but by no means are things certain.  Plus there is no way of knowing how long until ECMAScript 6 is supported enough to actually make it useful.  For an idea of where ECMAScript support in various browsers is, check out this handy table.

 

This has opened the door to a number of alternatives, many are languages that compile down to JavaScript making them useful today. Others (like Dart) compile down to JavaScript as a fallback, but perform better in their native environment.

 

 

The 900lb gorillas.

 

Two of the companies are very interested in the future of JavaScript are Google and Microsoft.  Each has created a language they hope will be the future of JavaScript, Dart and TypeScript respectively.

 

This interview between Anders Hejlsberg ( Microsoft, creator of Delphi, C# and now TypeScript ) and Lars Bak ( Google, creator of V8 JavaScript engine and Dart ) is very good summary.  It allows each developer to describe their opinions of the existing problems with JavaScript ( on which they largely agree ) and describe the strengths of each of their companies offerings.

 

Anders Heljsberg & Lars Bak on TypeScript/Dart and the problems with JavaScript today

 

 

Google Dart

 

http://code.google.com/p/dart/ or http://www.dartlang.org/

image

 

In Their Words:

Why Dart?

At Google we've written our share of web apps, and we've tried in many ways to make improvements to that development process, short of introducing a new language. Now we think it's time to take that leap. We designed Dart to be easy to write development tools for, well-suited to modern app development, and capable of high-performance implementations.

 

Dynamic or Static Typed?

Dynamic

 

Key language features

Compiles down to JavaScript, or to the Dart VM ( which is currently only available in Chrome ).  Code running in the Dart VM will perform better.

Language is basically JavaScript with prototypes removed and classes added.  They’ve added lexical closures, sane this management, optional static types, named parameters, cleaner event and DOM programming and more.

The language also comes with an IDE, the Dart Editor, which is a mash-up of Eclipse, Chromium and the DartVM.  For those like me that prefer WebStorm/IntelliJ over Eclipse, they also have a plugin available.  There used to be a cloud based editor, but it appears to have been retired.

 

My 2 cents

Dart technically solves most of the problems with JavaScript and is compatible with existing JavaScript.  That said, I checked out Dart shortly after it was released, then again 6 months later and as usual, Google’s developer support stunk.  They just don’t put the extra effort in to making the experience easy on developers ( at the time, the Windows build didn’t work, you need to compile everything yourself, etc… this lack of polish is just as common with other Google developer tools such as GWT, NativeClient even Android), but the package seems to be improved quite a bit.  Just a warning though, if you aren’t experienced with Google developer support, be prepared for a ton of frustrations if you run in to any problems.

Probably the biggest flaw with Dart is going to be the lack of adoption.  Dart compiles to JavaScript as a fall back, but the VM is obviously the preferred platform.  Google announced their intention of submitting Dart to a standards body, but do you see Microsoft or Mozilla adopting Dart?  Yeah, me neither.  That said, Chrome is getting a pretty big install base.

My biggest problems are the above mentioned Google support, and their tendency to kill off projects at the drop of a hat lately. 

 

 

Microsoft TypeScript

 

http://www.typescriptlang.org/

 

image

In Their Words:

Why TypeScript?

TypeScript is a language for application-scale JavaScript development. TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Any browser. Any host. Any OS. Open Source.

Dynamic or Static Typed?

Static

 

Key language features

TypeScript is compiled down to JavaScript.

Language allows you to add static types to JavaScript, allowing you to catch type errors during the compilation process ( although the compilation will still generate a JS file ).  Allows you to mix and match TypeScript and JavaScript in existing files.  Adds new constructs to the language such as classes, interfaces and modules.

IDE support is available in the form of a Visual Studio 2012 plugin, as well as plugins for Sublime Text, Vi and Emacs.  They also have Node support out of the box and you can download TypeScript using NPM.

 

My 2 cents

I will admit, I am a bit of a Anders fanboy, so that has gotten me excited about this language.  Language design is all about pragmatic choices, and Anders just seems to pick the right compromises.

At the end of the day, TypeScript is less of a gamble than Dart, and this has it’s advantages and disadvantages.  As Lars said in that video above, TypeScript is “the safe bet” and that is a pretty apt description.  It is a layer on top of JavaScript and nothing more, in many ways it is quite similar to CoffeeScript.  In the end though, TypeScript is probably the one that will best integrate with existing Javascript and given the massive variety of existing code, that is probably a pretty big advantage.  At the end of the day though, TypeScript is ends up being JavaScript, so don’t expect any performance improvements.

The tooling support is shockingly not Microsoft.  Would you have ever expected Vi and Emacs support from day 1?  What about Node support?  There is a noted lack of documentation at this point, which is shocking for a Microsoft product.  They do however have a nifty Playground/Tutorial environment that allows you to type TypeScript and see the generated JavaScript.  Sadly for now, comments and whitespaces are mangled as part of the process, although this is a temporary flaw.

 

 

CoffeeScript

http://coffeescript.org/

 

In Their Words:

CoffeeScript is a little language that compiles into JavaScript. Underneath all those awkward braces and semicolons, JavaScript has alwaysimage had a gorgeous object model at its heart. CoffeeScript is an attempt to expose the good parts of JavaScript in a simple way.

The golden rule of CoffeeScript is: "It's just JavaScript". The code compiles one-to-one into the equivalent JS, and there is no interpretation at runtime

 

Dynamic or Static Typed?

Dynamic

 

Key Language Features

Coffeescript is a whitespace ( as opposed to curly brace ) based language that compiles down to JavaScript.  It is certainly the elder statements of the group and has been around for a number of years.

Coffeescript provides a number of features to JavaScript including a class system, lexical scoping, splats (…) for variable arguments, array slicing and more.  Additionally it provides a layer of syntactical sugar over some of the JavaScript warts such as is instead of === or unless as the inverse of if.

Coffeescript also offers impressive tooling support.  Like TypeScript, it is available as a Node utility, making installation via NPM trivial.  Most IDEs support Coffeescript ( IntelliJ, Eclipse, WebStorm, Netbeans, Sublime Text, etc ) out of the box.

 

My 2 cents

I only gave CoffeeScript the smallest of evaluations and that was a few years back.  You see, I have an irrational hatred of whitespace based languages.  What I found most irksome ( and TypeScript fixed this ), is that it’s a language on-top of JavaScript, not within Javascript.  So you had to program things the Coffeescript way, then compile it to JavaScript.  Coffeescript felt like a completely different language than JavaScript, while neither Dart nor TypeScript gave me that impression.  Mostly though, I never got over my hatred of whitespace based languages.

All that said, CoffeeScript solved many of the problems that Dart and TypeScript are setting out to solve, and it solved them years ago.  It’s by far the most mature and as a result had the most time to iron out the kinks.

 

 

Other Options

 

Dart, TypeScript and CoffeeScript are by no means the only options when it comes to more programmer friendly JavaScript programming languages, but they are the three that are closest to JavaScript itself.  The following are a selection of other languages that will compile to JavaScript.

 

 

GWT – Google Web Toolkit

 

https://developers.google.com/web-toolkit/

Google Web Toolkit (GWT) is a development toolkit for building and optimizing complex browser-based applications. GWT is used by many products atimage Google, including Google AdWords and Orkut. It's open source, completely free, and used by thousands of developers around the world.

Basically GTW is a Java –> JavaScript compiler.  That is over generalizing, but basically you write your code using a subset of libraries in the Java language, and it is compiled down to JavaScript.  Or a bit of mix and match, with Java running on the server and JavaScript on the client.  The programmer never really works in JavaScript when working with GWT.

 

As is pretty typical with Google projects, IDE support is mostly Eclipse based.  There are a few published books available for GWT.  GWT has been around for quite a while and integrates nicely with Google App Engine.  That said, if you aren’t a Java developer, GWT really isn’t for you.

 

 

 

Haxe

 

http://haxe.org/

Haxe is a powerful modern language with many compelling features. It is aimed at giving developers a tool to create websites & applications using aimage single unified programming language. Whether you use Haxe for its cross-platform features, or focus on a single platform, there are many reasons to adopt it.

Haxe is a language that allows you to compile down to JavaScript, Flash, NekoVM, PHP, C++, C# and Java.  It provides a standard language and library that compiles down to the mentioned languages, while filling in the missing pieces of each language, such as packages and typing for JavaScript, reflection for C++, etc.  The Haxe language itself is derived from ActionScript 3, which itself is a ECMAScript language. Haxe has pretty good IDE support. Haxe also has a few published books which is always handy.

 

I’ve not yet used Haxe, mostly because I have no prior ActionScript experience and because I never really had the time to look into it further. That said, HaxeNME, which is a gaming library targeting web, mobile and desktop certainly has piqued my interests.

 

 

 

Other other options…

 

This doesn’t even come close to listing all of the languages that compile to JavaScript, for a more complete list see this.  This does however cover the major players, at least as I see them.  If you think I made a major omission or mistake in this list, please let me know!

 

JavaScript is becoming more important and JavaScript programs are becoming more complex.  The language does have a number of flaws, but fortunately there are a number of options to help you cope, at least until ECMAScript 6 arrives.

General, Programming ,




Creating game tools in HTML5

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




Moai Tutorial Part 7: Tile maps so easy your mother could do it

3. October 2012

 

Not to make any assumptions about your mother’s computing abilities of course!  My mother is flummoxed by powering a computer on and its all down hill from there, so perhaps not quite easy enough *my* mother could do it.  But it is easy, really easy.  Really.  Easy.  This is just one of those areas Moai really shines.

 

If you are unfamiliar with the concept, a tilemap is pretty straight forward.  You have an image or series of images that hold the art for your game.  In this example, we are going to use a regular top down ( not isometric ) perspective and our image map is composed of tiles 32x32 pixels in size.  Your game map is then made up of a grid that says “at this location, draw this tile”.

 

First, the topic of the image itself.  That one, in the spirit of open source, I am ripping off someone else’s work! Smile  You may remember a while back Mozilla released a completely free HTML5 based MMO, BrowserQuest.  Well, we are going to make use of one of the tilesheets from that project.  This is the file right here (it is big).  This is massive overkill, but I like massive overkill.  Here is a shrunk down version of the image we are going to be working with:

image

 

The image is composed of 20 columns of 32x32 images and 98 rows of them, for a grand total of 1,960 tile images or cells, in a single image.  So, that covers our image, let’s take a look at the code:

screenWidth = MOAIEnvironment.screenWidth
screenHeight = MOAIEnvironment.screenHeight
if screenWidth == nil then screenWidth =1280 end
if screenHeight == nil then screenHeight = 800 end

MOAISim.openWindow("Window",screenWidth,screenHeight)

local viewport = MOAIViewport.new()
viewport:setSize(screenWidth,screenHeight)
viewport:setScale(480,320)

local layer = MOAILayer2D.new()
layer:setViewport(viewport)
MOAIRenderMgr.pushRenderPass(layer)

local map = MOAIGrid.new()
map:initRectGrid(15,10,32,32)
map:setRow(10,0x0b,0x0c,0x0d,0x0b,0x0c,0x0b,0xc7,0xc7,0xc7,0xc7,0x0d,0x0b,0x0c,0x0d,0xc7)
map:setRow(9,0x2e,0x2f,0x30,0x31,0x32,0x0b,0x0c,0x0d,0xc7,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(8,0x41,0x42,0x43,0x44,0x45,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(7,0x55,0x56,0x57,0x58,0x59,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(6,0x69,0x6a,0x6b,0x6c,0x6d,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(5,0x7d,0x7e,0x7f,0x80,0x81,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(4,0x91,0x92,0x93,0x94,0x95,0x0b,0x0c,0x0d,0xc7,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(3,0xa5,0xa6,0xa7,0xa8,0xa9,0x0b,0x0c,0xc7,0xc7,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(2,0xb9,0xba,0xbb,0xbc,0xbd,0xc7,0xc7,0xc7,0xc7,0xc7,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(1,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2)


local mapTiles = MOAITileDeck2D.new()
mapTiles:setTexture("tilesheet.png")
mapTiles:setSize(20,98)

local prop = MOAIProp2D.new()
prop:setDeck(mapTiles)
prop:setGrid(map)
prop:setLoc(-480/2,-320/2)
-- functionally the same as above
-- prop:setPiv(480/2,320/2)

layer:insertProp(prop)

And if we run this code, we see:

 

image

 

Ok, that’s a pretty cool amount of stuff on screen, for not so much code!  Let’s take a look at exactly what we did here.  Once again from the top ( one of these examples I am going to do from the bottom! ).  Once again, we are only going to look at the new bits, so if I fail to cover something, check out the prior tutorials, chances are I covered it then.

 

local viewport = MOAIViewport.new()
viewport:setSize(screenWidth,screenHeight)
viewport:setScale(480,320)

We’ve seen this many times before, but always in the past I’ve set setSize and setScale to the same value, this time I didn’t… why?  Well the biggest reason is, I defined the grid of map values by hand, which was a gigantic pain in the butt for a screen made up of a 15x10 array of tiles ( 480/32==15, 320/32==10 ), let alone a 1280x800 screen!  By setting the viewport to the actual resolution of your device, but setting the scale to your target resolution ( in this case, the iPhone 3g’s native resolution ), MOAI automatically handles the scaling for you.  This is a nice easy way to support a number of different screen resolutions without having to code each one by hand.

 

Speaking of the map values:

local map = MOAIGrid.new()
map:initRectGrid(15,10,32,32)
map:setRow(10,0x0b,0x0c,0x0d,0x0b,0x0c,0x0b,0xc7,0xc7,0xc7,0xc7,0x0d,0x0b,0x0c,0x0d,0xc7)
map:setRow(9,0x2e,0x2f,0x30,0x31,0x32,0x0b,0x0c,0x0d,0xc7,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(8,0x41,0x42,0x43,0x44,0x45,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(7,0x55,0x56,0x57,0x58,0x59,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(6,0x69,0x6a,0x6b,0x6c,0x6d,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(5,0x7d,0x7e,0x7f,0x80,0x81,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(4,0x91,0x92,0x93,0x94,0x95,0x0b,0x0c,0x0d,0xc7,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(3,0xa5,0xa6,0xa7,0xa8,0xa9,0x0b,0x0c,0xc7,0xc7,0x0c,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(2,0xb9,0xba,0xbb,0xbc,0xbd,0xc7,0xc7,0xc7,0xc7,0xc7,0x0d,0x0b,0x0c,0x0d,0x0b)
map:setRow(1,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2)

In the immortal words of Douglas Adams DON’T PANIC!  This looks a lot scarier than it actually is.  We are creating our map, which is a variable of type MOAIGrid.  Think of a grid as a 2d array of sorts that holds references to the tiles at each location.  Really that’s about what it does.  So we start of by initializing with a call to initRectGrid() passing in the number of tiles ( 15x10 ) and the width and height of each tile ( 32,32 ).  The next 10 lines are simply populating the grid with calls to setRow(), the first value is the row index, then what follows is a list of 32bit indexes in hexidecimal.  This is where the scary comes in.

 

Basically the top left tile in our image map is at 1 ( 0x01 ) and there are 20 tiles per row in the image we used, so the first image in the second row is therefore at 21 ( row count * row width + offset == 1 * 20 + 1 == 21 ), which is then translated in to hex, which is 0x15. 

 

So, basically we “draw” our map using image locations ( as a 1d index using the formula above, converted to hex ).  The MOAIGrid itself, row 1 is the bottom most row, which is why our grid counts down from 10.  Now let’s take a look at how we created our source image:

 

local mapTiles = MOAITileDeck2D.new()
mapTiles:setTexture("tilesheet.png")
mapTiles:setSize(20,98)

Pretty simple over all.  We create a MOAITileDeck2D.  Remember, a Deck is parlance for an image source, and in this case our source is a single image composed of dozens of tiles.  We set the actual image with a call to setTexture() and pass in our filename tilesheet.png.  We then set it’s size, letting it know it is made up of 20 columns and 98 rows of tiles.

 

local prop = MOAIProp2D.new()
prop:setDeck(mapTiles)
prop:setGrid(map)
prop:setLoc(-480/2,-320/2)
-- functionally the same as above
-- prop:setPiv(480/2,320/2)

Neither MOAITileDeck2D or MOAIGrid are display items, for the we need to create a MOAIProp2D.  We set it’s deck ( or source ) to our newly created MOAITileDeck2D mapTiles and it’s grid to our MOAIGrid map.  Finally we set it’s position with a call to setLoc.  This is an area of some possible confusion ( and why I showed the commented setPiv() as well ), because by default our prop will be at (0,0), which is the dead center of the screen.  However, the pivot point of our prop in the case is actually the bottom left corner of our map.  Therefore, we either need to move the pivot point to the center ( what the commented out code does ), or we position the prop offset from the center of the screen by half the width and height of the viewport.

 

You can actually accomplish a heck of a lot with just a bit of code.  Obviously in your case, you want want to use a tool to generate the MOAIGrid indices, doing it by hand is a PITA ( trust me! ).  Really though, the visual rendering of a top down RPG game just boiled down to a dozen or so lines of code!  Perhaps most impressively, this just scratched the surface of what MOAIGrid can do.

 

Coming Soon

General, Programming , ,