Puny MVC JS

I got inspired to learn more MVC after reading some posts by Peter Michaux, and especially his MVC Architecture for JavaScript Applications article. He’s right, you can meditate on it for days.

However, I found the sample MVC Clock example code a little clunkier than I’d like (ie, I didn’t grok it well enough the first time) and never the one to leave well enough alone, I started reworking it.

Thus is born Puny MVC, a little javascript mvc example that’s perhaps a little more logically organized to my mind than the MVC Clock. I’ve chosen a tormented example for it, which you can get at my bitfool github. Or you can see it all right here (NSFW).

Basics:
This (like Peter’s MVC Clock example) is a hybrid… there is a Model, and a Controller and a View, neatly separated, but there is also a Widget, which Peter describes as a semi-heretical construct whereby a view incorporates aspects of a controller unto itself and communicates directly with the Model. There is also a Mediator, of sorts, which is of the Observer type. In short your various UI components become Observers that can communicate with the Model (directly through their Widgets or indirectly through their Views to Controllers), and the Model can message out to the Observers. Finally, there is a Bootstrap section to set everything up and get started.

Unlike Peter, I tried to abstract the meat of the Model and Observer out and into its own function, called a Puny. The Puny handles all the Observer stuff, to unclutter the Model code.

Let’s start at the bottom:

Bootstrap: To run this program, we do just a few things.


//this inits the Puny, which keeps track of observers
var puny = makePuny();

//this inits the custom model, and passes in the Puny
var curseModel = makeQuoteModel(puny);

//this inits the Controller, and passes in the Model
// (the Controller manages the UI start/stop/reset buttons)
var curseKnobsController = makeCurseKnobsController(curseModel);

//this inits the View, and passes in the Controller
// (the View creates the UI start/stop/reset buttons)
var curseKnobsView = makeCurseKnobsView(curseKnobsController);

//this inits the Widget, and passes in the Model
// (the Widget creates the UI blockquote for the Shakespeare)
var cursingShakespeareWidget = makeCursingShakespeareWidget(curseModel);

//the View and Widget have constructors for all the DOM elements,
// so here's where we use them to build the DOM
document.body.appendChild(curseKnobsView.getRootEl());
document.body.appendChild(cursingShakespeareWidget.getRootEl());

That’s pretty easy, nice and organized. The Widget displays a random bowdlerized Shakespearean quote that is generated at 1 second intervals by the Model. The View has Start/Stop/Reset buttons to control the actions of the Widget (via the Controller, and the Model).

But you can read code. The actual meat of the sample is silliness, but I like the organization and maybe will build on it a bit in the future. You can go get it at GitHub Puny MVC Javascript example.

Use categories in Objective C to add instance variables to a CCSprite or anything else

Ok, I’ve got this down to about 10 lines of code.

I’ve got some button sprites in Cocos2D that need an instance variable.  I’m already using userData, and found that I was starting to overload it to use it the text in there for more than one purpose… if you start stripping off substrings from the userData to code for things, you might be interested in having another instance variable.

So you want to add “.mydata” to your sprites?  Try this:

1.  Decide where you want the scope of this.  In my app, there’s only one scene with one layer, and so in the MyLayer.m file where all my button sprites are, I’m adding this code at the top, just above the @interface MyLayer line:

@interface CCSprite (MyExtras)
@property (nonatomic,retain) id mydata;
@end
#import <objc/runtime.h>
static char const * const mydataKey = "mydata";
@implementation CCSprite (MyExtras)
@dynamic mydata;
- (id) mydata { return objc_getAssociatedObject(self, mydataKey); }
- (void) setMydata:(id)new { objc_setAssociatedObject(self, mydataKey, new, OBJC_ASSOCIATION_RETAIN_NONATOMIC); }
@end

That’s 10 lines.

2. Test it out.  Something like this:

CCSprite* buttonTest = [CCSprite spriteWithFile:@"buttontest.png"];
[buttonTest setMydata:[NSNumber numberWithInt:6]];   //use official setter method
buttonTest.mydata = [NSString stringWithFormat:@"hello"];  //ok too
CCLOG(@"buttonTest:%@",buttonTest.mydata);

All this does is attach an object to your sprite button, and spit it back out into the console log.  It’s flexible… attach any object you want this way, pretty much.  The second line makes it a NSNumber object, and the 3rd line replaces that with a NSString.  The only restriction here is you have to give .mydata an ID… that means you can’t say:

[buttonTest setMydata:6];

Because 6 is an int, not an id.  Get around that by using NSNumber.

If you want to read more, there’s lots of blog posts out there about this topic (try “associative references” in Objective C), and how to add other methods to extend existing classes, etc.  But this is just one common use case, simplified to its essentials.

 

Real quick new Kobold2D templates

So, in the project I’m working on now, we need new Kobold2D templates every week or two.  Why?  It’s easier this way… the two of us code separately mostly in different parts of the app, then merge every few days or weekly, and going forward we make a new template to use.  Then we can start and try test apps with new features, and not worry about them.

Real quick new template procedure:

1.  Clean Up Your App:  You have a working app in Kobold2D that you want to use as your new template.  Great.  Now clean it up.  I recommend putting all your Resources neatly organized in a /Resources folder, and all your classes in a /Classes folder, inside your /Projectfiles folder.  Really.  Do this.  In a Finder window, so that the Groups of classes and Resources in XCode match the folder organization in Finder.  Feel free to have folders in folders.  Ok… is it clean and tidy?  Groups in XCode match folders in Finder exactly?  Ready to move on.

2. Make A New Template App:  Close XCode, and use Kobold2D Project Starter app to make a new app, named “_Code7-Template_” (this template will then show up as “Code7″ in the Kobold2D Project Starter app when you’re done).  Click Create Project From Template to start this up in XCode.   Use the Empty-Project template if this is your first template, or use your latest template as a starter, since that should be similar to this one structurally.

[You don't have to close XCode first, but it needs to restart.  Choose Revert usually, if it asks because you didn't follow my suggestion to close it.]

3. Clean Up The Template in XCode:   In your new “_Code7-Template_” app in XCode, open the Projectfiles group.  Get rid of the HelloWorldLayer and AppDelegate class files (select, right click, DELETE – not just remove references).  Do the same for the Resources group (including the config.lua file… you’re going to use a new one, right?).  Leave the “Supporting Files” group alone (main.m and two pch files).  These deletes will render the app useless and broken for the moment.  That’s ok.

4.  Close XCode.  You don’t want it open right now while you change things in Finder.

5.  Clean Up The Template in Finder:  In Finder, go to your new template app (something like: ~/Kobold2D/Kobold2D-1.0.1/_Code7-Template_/).  Clean out the Projectfiles folder.  It will probably still have a /Resources folder in it.  Get rid of it.  Leave the other three Supporting Files files.

6. Add Your New Files In Finder:  Open another Finder window and copy (Option-Drag-Drop) your neatly organized Classes and Resources folders full of goodies from your working app, into the Projectfiles folder of the Code7 template you just cleaned up.

7.  Add New Files in XCode:  Restart XCode with your Kobold2D workspace.  Navigate to the Projectfiles group of your Code7 app.  Right click on Projectfiles, and select the Add files to “_Code7-Template_” option.  Browse to your Projectfiles folder of the Code7-Template, and select the Classes folder, and add it, being sure to select Create Groups for any added Folders.  Repeat to add the Resources folder.

8.  Bingo.  Test your app in the simulator to make sure it works just like the one you’re copying from.  Now it’s ready to become the newest template in your arsenal.

9. Make it a template: Close XCode (or not).

(a) In Finder, copy your _Code7-Template_ folder over into the ~/Kobold2D/Kobold2D-1.0.1/__Kobold2D__/templates/project folder, where the other templates reside.

(b) Make a _description_ file, by copying one from another template into your template folder, opening it up in a text editor, and rewrite it to describe this template.  Save.

(c) You’re done.  If you’ll be sharing this template with anybody, get rid of your build products taking up space… right click on the _Code7-Template_.xcodeproj package, and select Show Package Contents to open it in a new Finder window.  Trash the xcuserdata folder, it’s unwanted now.

10.  Test it… use Kobold2D Project Starter app and your new template should show up.  Start a new app (Code8 of course) and keep moving.

I know, ten steps doesn’t sound so “real quick” but I’ve got the whole thing down to about 5 minutes now, because my app structure is clean and I know what to do.  You can too.

 

 

 

 

 

 

 

Kobold2D HowTo – making a new template for Cocos2D apps

For a new project, I’m learning Cocos2D, and for this I’m using Steffan Itterheim’s Kobold project.  It’s pretty cool.  You hit the Kobold2D Project Starter app, select a template to work with and a name for your app, and hit go…. it builds a basic Cocos2D app for you, ready and working, and formatted to compile for iPhone or iPad, and in many cases for OS-X compilation (not all Cocos2D features will work – YMMV).

So far, I’m finding Kobold2D (and Cocos2D) pretty nice.  But what I wanted to do was build a whole series of test apps that will provide the building blocks I need for future development.  Like… there’s no way in Cocos2D to make a text box that displays formatted HTML.  So what you need to do is use a UIWebView… but tied into Cocos2D somehow.  Kobold2D has a sample template that shows one way to do this, and I used that as a starting point, but it seems cludgy to me.

So I went looking and found CCUIViewWrapper, an extension for Cocos2D that seems to do pretty much what I want… just instantiate a UIWebView and build a wrapper around it and add the HTML code into it that you want.  I’ll probably write another post about that (cause it’s nice), but this post is because I want now to put a new template into the Kobold builder that includes all the extra stuff I want (and none of the Kobold stuff I don’t) and use this new template for my next building block explorations.

So I read Steffen’s “Creating a Kobold2D Template Project” page, and didn’t quite get it.  The nuggets are there, but it’s not a step-by-step, so I’m making one here, in case you’re looking for one.

1. Read his “Creating” page first.  Pay attention to the naming section.

2. Use his Kobold2D Project Starter app to start a new project.  Pick one that’s close to what you want.  Name it according to the rules in Step 1, like “_My-First-Attempt-Template_”.  Key: it starts with an underscore, and ends with “-Template_” and everything inside is just alphanumeric text and hyphens, nothing fancy.

[EDIT]   (A LATER NOTE) Also, I’ve found that any hyphen-separated parts of the name should be Capitalized.  Like “_My-second-attempt-Template_” may not work, whereas “_My-Second-Attempt-Template_” would.  I did this wrongly, and the template never showed up in the Kobold2D Project Starter menu!  [/END EDIT]

3. That should open you into Xcode with your new project started.  The first thing is to compile it with one of the simulators, like the ones you’re aiming for.  This is just to be sure it works.  It should.

4. Change the source codes to whatever you want.  Compile along the way, making sure it all works.  Add resources, etc.  Make sure everything you need is copied into the template folder so it doesn’t rely on outside things, unless that’s the way you want to roll.

5. When you’re satisfied, you’re done here.  Go to the Finder and find the the _My-First-Attempt-Template_ folder you’ve been working on.  Copy that entire folder over to the __Kobold2D__/templates/project folder.  That will allow Kobold2D to find and display it as one of it’s templates.

6.  Open the _My-First-Attempt-Template_.xcodeproj to see the Package contents (right click on it in Finder, choose “Show Package Contents”.  In this package, delete the “xcuserdata” folder (this is not needed, and will give the wrong scheme names in your new templated projects if it is not deleted).

7.  Add a new plain text file in the root of the _My-First-Attempt-Template_ folder called “_description_”.  Write a brief description of the template in this file.

8. Try it!  Run Kobold project starter and it should let you make a new project just the way you want it with your new template.  Test the new project thoroughly to see it works right.  It should.

9. Use your new template yourself, or share with everyone else by giving your code an MIT open source license and release it on github and tell Steffan about it.  If it’s useful, he says he’ll consider packaging it up with his templates too.