Archive for the 'Objective C' category

SWFSheet – create sprite sheets from SWFs

[EDIT: Just released a beta of SWFSheet 1.1 here: http://www.bit-101.com/blog/?p=2948]
[EDIT: Version 1.1 final released: http://www.bit-101.com/blog/?p=2977]

SWFSheet is a program I created in most of a day back in late December. I finally polished it up this week and it’s now ready for release. The idea is to take an animation created in Flash, and generate a sprite sheet from it. A sprite sheet, for those of you who may not be familiar, is a single large bitmap containing several frames of an animation, usually layed out in a grid. These can be loaded in very efficiently by games, and each frame shown to recreate the animation.

I had the idea for this program while attempting to port some Flash stuff to the iPhone. And later while making other mobile games, I found that Flash was still the best tool to create animations. It has a powerful time line, easy to use drawing tools, tweens, 3D, and of course, powerful scripting with ActionScript. However, getting a nice looking Flash animation into a sprite sheet that could be used with cocos2d on the iPhone/iPad or with XNA for Windows Phone 7 was not so easy. I did it by hand a couple of times, and it wasn’t very fun. Thus, SWFSheet was born.

SWFSheet is an AIR application and has been tested on Windows and Mac. You create your SWF however you want. Flash CS5 or earlier, Flash Builder, or anything else that outputs a SWF. It doesn’t matter how it’s created. Then you load the SWF into SWFSheet.

swfsheet screenshot

Immediately, you’ll see the live loaded SWF running in the upper left panel. The program will then capture an image of the SWF on each frame for the number of frames you have specified (default 15) and arrange them in a grid on the bitmap. Once that is done, it will then animate this bitmap using the same techniques you would use to animate a sprite sheet in a real game. This is seen in the lower left panel. You can adjust how many frames you want to capture to make sure you get your whole animation and have it loop smoothly. And you can adjust the frame of exactly how much area is captured in each frame, to maximize space on the bitmap. If there is not enough space to capture all frames, you can choose a larger bitmap. After any changes, you need to click “Capture” to re-capture the frames based on the new settings.

Often when scripting animations, you will have various transformations or other changes happening in an onEnterFrame type of loop. This can sometimes cause a glitch, as the first frame is captured before the first enterFrame handler fires, and thus does not have the initial transformations applied. There is a “Skip first frame” checkbox which handles this situation. There are also options for smoothing, which may or may not make any difference in a specific animation, and for transparency. By default, a loaded in SWF will have a transparent background, but you can override this to make an opaque bitmap with any color background you want. And you can change the preview frame rate – of course this doesn’t change the bitmap at all, but can give you an idea what your animation will look like at your target frame rate.

Note that there are a limited number of sized of bitmaps. Sprite sheets can almost always take advantage of extra efficiency when created in power-of-two sized squares – 64×64, 128×128, 256×256, etc. Thus, these are the only choices. A future version may make possible custom sizes if enough people ask for it.

Here’s the AIR installer:

SWFSheet Installer

And here are some test files to get started with:

Test Files

Enjoy!

ps. Another tool you might be interested in is Mike Jones’ Sprite Sheet Maker, which is more geared to making sprite sheets from a series of separate image files. Similar outcome, different use cases, depending on what kind of input you are starting from.

76 responses so far

Good bye 2010

As usual, it’s time to make my year end post. I’ll keep it relatively brief.

A few changes this year. This spring, I got kind of fed up with Apple, their control-happy policies, and the general direction they are heading. After 3 years of being 100% Mac, I switched back to Windows. It is an action that I not only do not regret the tiniest bit, but as Apple continues to evolve in the same direction, I’m happier than ever that I switched when I did. This is not to say that I’ve abandoned all iOS development and have thrown away my Mac. I still own two Apple computers. Both are plugged in and booted up and ready for action at all time. I have an iPhone, and iPad, an iPod Touch and a 5G iPod. They aren’t going anywhere. But the machine I open up in the morning and use all day long is my Sony Vaio, and I’m very happy with it. I’m not shoving it down your throat. If you’re happy with Apple, far be it from me to try to change your mind. I’m OK, you’re OK, right?

Around the same time I switched back to Windows, I also came into the ownership of a Google Nexus One. It took a while to really get used to it, as it’s definitely not the polished experience that the iPhone is. But I forced myself to stick with it for a week or so and really started to love it. From my viewpoint, the main difference was that it was MY phone, not Steve Jobs’. I could do pretty much whatever I wanted with it. Change the lock screen, change the task switcher, add memory, change the battery, put my icons where I want them, install unsigned apps, have live gadgets on the home screen, etc. etc. Once I got used to it, the iPhone just seemed unbearably sterile. Unfortunately, the model I had was a T-Mobile version, so I couldn’t get 3G on it with my AT&T sim. I suffered with Edge for a several months, but finally the wifi connection and even the Edge connection started getting really flaky. One day in September, just couldn’t connect to anything, so it was back to the iPhone.

Coming back to the iPhone, I have to admit, I really did appreciate the slickness of the UI. But I didn’t fall back in love with it. To be honest, I knew it was only a stopgap until the new Windows Phones came out. I got a Samsung Focus as soon as they came out and I absolutely love it. It is without a doubt the best phone I’ve owned. Note – it’s far from perfect. It’s a v1 product and it shows in many ways. But regardless of all that, there is so much RIGHT about what Microsoft did with it. I’m really excited to see where it goes in the coming years. I don’t expect it to overtake or even match Android or iOS any time in the near future, if at all, and I don’t really care. As long as I can continue to own one and see it improve, I’m a happy camper.

As for mobile development, I didn’t do much at all most of the year. But this autumn and winter I worked on one major and one minor iOS projects at Infrared5. After being away from Objective-C for so long, it was pretty bizarre trying to get back into it. It took a couple of days before it stopped feeling like I was typing with my toes, but eventually I got back in the groove. I played with Android dev briefly, but never really dove into it that much. But in October, I got my hands dirty with Windows Phone dev, with both XNA and Silverlight, and it has blown me away. I might even say it’s revitalized me as a developer. For a large part of the year I was on a very tough, frustrating project. It wore me down quite a bit. But with Visual Studio and C#, it’s like starting from scratch – in a good way! All the excitement without the learning curve. After many years of Flash development, writing ActionScript is almost second nature to me. But after just a couple of months in Visual Studio, I feel like I’m more at home with C# than I ever was with ActionScript. It’s a very, very similar language. If you took AS3 and removed all the little things that annoy or distract you and pull you out of the “flow” of coding, and replaced them with a whole bunch of little things that just work exactly the way you would expect them to, you’d have C#. And if you took Flash Builder and … no, that’s just not going to work. There’s no comparing Eclipse to Visual Studio.

Speaking of IDEs, after working in VS for a few months, and then going back to XCode… it really dawned on me just how bizarre an IDE that really is. I’m really trying not to bash any particular technology, but I can’t help feeling like XCode was designed on an anti-matter planet in an alternate universe by some bizarre aliens on really strong acid. I’m not even talking about the language – just the IDE. I sometimes find it hard to believe that it was created by and for programmers. I know it’s not “wrong”, just different. Most IDEs are relatively similar, like most western human languages are pretty similar. I may not speak Spanish, but I can see it and read the words even if I don’t know their meaning, and can catch a bit of a hint of what’s being said. Same with most IDEs – you can quickly find your way around them for the most part. But diving into XCode is like being dropped in an Asian or Middle Eastern country where everything just looks like random scratchings or scribbles to your unfamiliar eye. That’s what XCode is like – just a completely foreign programming paradigm. Again, not saying it’s bad or wrong. You live with it long enough and you become fluent in it. But boy is it different.

Also in the summer I got into Processing quite a bit. Far more than I ever had before. I’ve kind of drifted from it again, but it was a great experience. I’m sure I’ll drift back around to it again before long. This largely came about from my conference session for 2010, “Programming Art”, in which I covered a bunch of different tools and languages for creating algorithmic and generative art, including Context Free Art, Structure Synth, Processing, the Hype Framework, and others. I also really enjoyed getting my head around Structure Synth, and got a bit revived on it just recently with the newly released integrated raytracer. Fun stuff!

On a personal basis, it was a year of health. I ran over 1000 miles, lost a good deal of weight, and reverted the trend of my blood sugar and blood pressure, which were edging into borderline problem areas. I think I also did more travelling this year than I have in any previous years, with trips to San Francisco, Minneapolis, Kortrijk Belgium, Toronto, Japan, back to San Francisco, and Edmonton.

Well so much for keeping in brief. In summary, it was a year of trying new things and going back to old things, learning new platforms and languages. Going forward, I don’t think it’s possible, at least not for me, to be a “Flash Developer”, or an “iPhone Developer” or be stuck in any single platform. Now more than ever, there is just too much diversity and you have to have a foot in every camp. If someone needs a game or an app these days, they can’t really just release a single version of it. They’re going to need an iPhone version, and Android version, eventually a Windows Phone version, and some kind of web presence with it. Are you going to just ask for one slice of that pie? Are they going to farm out their app to 4-5 different shops, one for each platform? As a company at the very least, you need to be able to do it all. Ideally as a developer as well, you need to be able to do as many of those as possible. I know that’s where Adobe is trying to be strong with the iPhone and Android packagers for Flash. I’m still not convinced those are the solutions for most projects though. Native will always win.

As for 2011, I assume the fist good chunk of the year I’ll be doing a lot more WP7 dev. And since the XNA codebase is 99% the same for WP7, Windows, and XBox games, I look forward to releasing some stuff for Windows desktop and XBox as well. I’m sure I’ll also play with the new Mac App Store stuff, and more iOS stuff too. The WP7 game I’m working on now will definitely need an iOS port. But who knows where I’ll go from there?

8 responses so far

Another year…

Dec 31 2009 Published by under ActionScript, Flash, General, iPhone, Objective C, Technology

For the past few years, I’ve posted a review of the previous year and a look to the coming year. So, I’ll do it again.

2009 was a very interesting year. Like this year, last year I had a whole bunch of unused vacation time at the end of the year, so took a couple of weeks off over Christmas. I decided to dive into Objective-C and iPhone programming. Little did I know how much that would dominate the next year, both in terms of my personal projects and work projects at Infrared5. One of the very first things I did was a little game called “Falling Balls”. A stupid little thing where you tilt the phone right and left to avoid … well … falling balls. It was just a silly thing I did in about 1.5 days, mostly to get a handle on the language and writing games in Objective-C. Unbelievably, the game rose to be the number one free application on the iTunes store. I put some ads in it and the cash started pouring in. I mean, more money than I could believe. Of course, it had its peak and eventually slid down the chart and made less money, but even now, it’s doing amazingly well in terms of ad revenue.

Hitting it big like that was a blessing and a curse. All I had to do, I figured, was do a handful of apps like that a year, and I could retire rich, buy an island somewhere and … ok, back to reality. Seems I wasn’t the only one who got the idea of making it big in the app store. I released a bunch of other apps – some free with ads, some paid, some lite/full version, etc. All told, the total amount I’ve made via all my other apps is equivalent to about what I currently make in a single day on Falling Balls. So, I’ve pretty much given up on striking it big AGAIN with iPhone apps, but will continue to give the occasional tweak to Falling Balls to keep it active.

At Infrared5 as well, we hitched up to the iPhone bandwagon. It wasn’t hard. All we had to do is say that we did iPhone stuff and after that pretty much everyone coming to us wanted us to do iPhone apps for them. I did one Flex job early in the year, but since then it’s been pretty much flat out iPhone projects for clients.

A lot of people have actually been upset with me for “abandoning” Flash here. I’m not even going to defend myself on that one. I pretty much did abandon Flash for quite a while there. I can’t say I’m diving back into it both feet at the moment, but I did get pretty burnt out on the iPhone stuff as well. Still working on iPhone stuff at work, but don’t have any ongoing personal iPhone projects at the moment, or any solid plans for any. I love the platform and hardware and capabilities and even got to love the language. But I hate the business model and publishing stranglehold that Apple has on it. In Flash I can bang out a SWF, put it on my site, blog or tweet about it, and in minutes, the whole world can see it. With the iPhone, I have to submit it, wait some unspecified amount of weeks with no feedback or anyone to communicate with, to see if it is approved or not. If not, no real recourse. Just fix it and put it back into the queue. It’s awful.

So what now? Back to Flash? Possibly. As you may have noticed, I had a whole game programming thing going on there a few months ago. Did a whole bunch of research on game architecture, applying it all to Flash games, spoke about game architecture at Flash on the Beach, and promised a game framework/toolkit “Asobu” that I was working on. Not sure what really happened with that.

In fact, for about the last month or so, I’ve hardly done any coding at all in my own spare time. Of course, I’ve been doing plenty at work, and that’s going fine. But usually when I get home, I have some personal stuff I’m working on – a game, some generative art, some experiments, components, a book, or whatever. But lately, I don’t know. I just get home, eat, relax, read some, hang out with the family, light up the wood stove and relax. I’m not particularly worried about it, and you shouldn’t be either. I think my mind just needs some time to recharge. I’ve been going at this pretty hard core since 2001 anyway. Consider I’m on a mini-personal-sabbatical. You might have noticed the dearth of posts here in the last several weeks. In fact, this is the first post I’ve done this month. I’m not going to make any promises about how I’ll now kick everything back into gear and get going on stuff again, but I have no doubt I’ll get fired up again sometime soon. I’ve learned to trust my instincts. They’ve done well for me thus far, and right now they are telling me to chill out. 🙂

One thing that I’ve given a lot of attention to in the last few months is running. I started up the Couch to 5K program to get in shape at the end of last August, and now I’m running 5 days a week. I’m completely addicted. Reading lots of running magazines and books and sites. Naturally, I’m getting all geeky about it with GPS and heart rate monitoring and tracking applications, etc. In fact, it has taken over my other, “personal” blog at http://www.keithpeters.org. If you are ever in doubt as to whether or not I’m alive, you can always check there and see what’s up.

But I haven’t been totally code free. In fact, I have actually been doing some ActionScript projects, particularly over this little vacation I’ve been taking. Tying in with the running, I started parsing the raw output of my Garmin Forerunner 305 GPS running watch – parsing the XML and graphing it out in interactive 3D. So much better than any of the apps that map the route on a google map and give you a 2D chart underneath it showing speed, elevation and heart rate. I plan to continue working on that over the next few weeks and have something to show. Also, I revived a cool project I’d started a long while back using the Flash 10 sound synth stuff. Been working on that actively the last couple of days. I actually started getting very excited about the possibilities of that, so that may be the next major thing you see coming out of this place.

What about overall 2010 plans? Can’t really say just yet. At work, we are starting in on a very major, and very … unique project that would possibly be done in Unity 3D. So I may be diving into some C# work for that. And beyond the Flash projects I just mentioned, I’m really interested in learning some other experimental technologies. I started playing with Structure Synth a while back, which is very interesting. A whole new take on programming. Hard to wrap your head around the syntax at first, but produces some stunning pics. I also want to dive more into some things like NodeBox, Context Free, ToolBox, Processing, and Open Frameworks.

Beyond that, like I said, just going with my intuition. And I intuit that 2010 will be a good year.

7 responses so far

Frameworks vs. Toolkits

Aug 20 2009 Published by under ActionScript, Flash, Objective C

Today on Twitter, Robert Penner posted a couple of really interesting links…

http://theshyam.com/2009/08/is-inheritance-overrated-needed-even/

and

http://code.google.com/p/noop/wiki/ProposalForComposition

This got me in a researchy mood about inheritance vs. composition, and I dug up this great series of interviews with Erich Gamma (one of the original Design Patterns Gang of Four):

http://www.artima.com/lejava/articles/gammadp.html

http://www.artima.com/lejava/articles/reuse.html

http://www.artima.com/lejava/articles/designprinciples.html

Actually, the last one had the info I was more looking for, but the first two are chock full of interesting data and viewpoints. This post is about some of the data in the second article on flexibility and reuse. Gamma talks about three levels of code reuse:

1. Reuse of “classes: class libraries, containers, maybe some class “teams” like container/iterator.”

2. Design patterns.

3. Frameworks.

He goes into a lot of the pitfalls of frameworks. A lot of this really rung true to me.

A key challenge in framework development is how to preserve stability over time. The more miles a framework gets the better you understand how you should have built it in the first place. Therefore you would like to tweak and improve it. However, since your framework is heavily used you are highly constrained in what you can change.

And near the end of the article he talks about “frameworkitis”:

Frameworks abstract and provide higher level default functionality. To do so the framework needs to be in control. This loss of control can lead to what is sometimes called frameworkitis.

Frameworkitis is the disease that a framework wants to do too much for you or it does it in a way that you don’t want but you can’t change it. It’s fun to get all this functionality for free, but it hurts when the free functionality gets in the way. But you are now tied into the framework. To get the desired behavior you start to fight against the framework. And at this point you often start to lose, because it’s difficult to bend the framework in a direction it didn’t anticipate.

That really hit home. This is one of the big reasons I don’t dive into Flex more. Yes, you get a whole lot of functionality for free, but who has not fought against the Flex Framework?

I’ve also felt this quite a bit in the cocos2d framework for iPhone. Don’t get me wrong, it’s fantastic in terms of the free functionality you get, and I can’t think of a better way to get started in 2d iPhone game building, but eventually you do wind up trying to bend it to do something it didn’t anticipate. I spent half a day yesterday doing just that.

And although I’m not working with it personally, I think that some of the projects my company is working on are running into the same general thing with Unity3D.

Recently I’ve been doing and researching a lot about game development on both the iPhone and in Flash. So I’ve looked into some of the game frameworks that have sprung up for Flash, like flixel and the PushButton Engine. I looked more into flixel then PBE, but I can’t claim to know much about either one. But what turned me off about both of them was that very same fear of eventually getting a case of frameworkitis. If you look at the features of both, they contain a laundry list of items such as tile maps, physics, particles, rendering engines, pathfinding, AI, collision engines, sound and asset management, on and on.

While I’m sure this will get you up and running quick, I feel like before long, you’re going to be fighting against it in some way or other. PBE markets itself by saying you can build “modular pieces of gameplay instead of monolithic applications” and integrate your own libraries easily, so that may not be that bad. But Gamma also says, in the same article:

Because the bigger the framework becomes, the greater the chances that it will want to do too much, the bigger the learning curves become, and the more difficult it becomes to maintain it.

My feeling is that these frameworks just try to do too much.

I’ve been slowly working on making my own game framework – abstracting out pieces of commonly used functionality, making them reusable, and packaging them together. One strong feeling I’ve had about it though, was that I wanted it to be lightweight, and every piece be optional. After reading this article, I discovered that what I really wanted to build was a game toolkit. A toolkit would just be a set of building blocks that you can use as you see fit. Gamma has this to say:

Toolkits do not attempt to take control for you and they therefore do not suffer from frameworkitis.

With toolkits you create and call toolkit objects and register listeners to react to events. You’re in control. Frameworks try to be in control and tell you when to do what. A toolkit gives you the building blocks but leaves it up to you to be in control.

Also, if we do frameworks, we try to make them small frameworks. We prefer many small frameworks over one heavyweight framework.

If you really want to take the risk of doing frameworks, you want to have small and focused frameworks that you can also probably make optional. If you really want to, you can use the framework, but you can also use the toolkit. That’s a good position that avoids this frameworkitis problem, where you get really frustrated because you have to use the framework. Ideally I’d like to have a toolbox of smaller frameworks where I can pick and choose, so that I can pay the framework costs as I go.

This all made a whole lot of sense to me and gave me a lot more direction on where I want to go with my frame… er… toolkit. 🙂

Anyway, even if that all doesn’t interest you, read the three articles above. Fantastic insights to be had.

34 responses so far

iPhone Dev: The Honeymoon is Over.

Aug 01 2009 Published by under Flash, iPhone, Objective C

Last December, I had a bunch of unused vacation time and took a couple weeks off, stayed at home, and learned me some iPhone dev. I submitted my first iPhone application in January and I was hooked. I now have six apps / games in the store (not counting full/lite versions as different), making close to an app per month.

Those are my personal apps. At my job at Infrared5, we are also flooded with iPhone development. I’ve been flat out on iPhone games there for a couple months, and scheduled for another two months forward.

It got to the point where I hadn’t coded a line of AS3 in 2-3 months, and was seriously wondering if I would ever get back to it. But something snapped in the last week or so. I guess I’ve become somewhat disillusioned with the whole iPhone dev game.

So the iPhone App store is just over a year old, which means it’s twice as old as it was when I first got in. And it’s changed a lot. One of my first games, Falling Balls, unexpectedly took off and rose to be the #1 free application. I put some ads in it from AdMob, and was stunned at how much money it was making. Even now, almost 7 months later, it continues to lay a nice golden egg for me every day. I have NO complaints there. The only problem is, it’s like winning at gambling. Once you get a taste of it, you can’t stop, even if you never win again. All of the rest of the apps I’ve released have barely done anything. Not even remotely made up for the amount of time I’ve put into them. I’ve done lite versions and full versions, ads and paid versions, done all the promotion steps, everything everyone says to do. Bug Out! has done the best so far, and is doing OK, but only a tiny fraction of what Falling Balls did.

Now, it is very easy to say that my other apps weren’t very good, and I won’t argue that, but come one… Falling Balls? A stick figure that runs back and forth and gets squished by balls? It literally took me a weekend to make, as a brand new iPhone developer, and only part of that weekend. I guess it has some kind of zany viral appeal, but that’s pretty hard to reliably duplicate.

Also, while that viral appeal is a factor, I think it has more to do with the changing landscape of the app store. In December, when I started learning, there were 13,000 apps there. In January, when I submitted Falling Balls, there were around 17,000. Now there are well over 60,000. As for selling apps, the average prices for apps and games are steadily decreasing, games being lower and more steadily decreasing, with an average of less than $1.50. Even top studios are releasing high end, polished, professional games for $0.99. How can a single do-it-all-yourself developer compete? So I’ve pretty much given up on selling apps in the store.

What remains is releasing free apps with advertising. After all, it worked with Falling Balls. But even the free games market is totally saturated. There are close to 15,000 free games and applications in the store right now. That’s more than the total number of applications that were there when started. If you don’t get in the top 100, you aren’t going to get enough downloads to get enough ad traffic to matter. Of course, if you DO get in the top 100, you could be in for a rocket ride. And there’s the whole gambling / addiction thing again. Chasing that thrill of a big hit.

The problem is, it stops being fun. When I was doing Flash stuff for myself, I was almost always doing stuff with no concept of making money. I was just making cool stuff that I found to be fun. Once you get a taste of profits though, it’s hard not to be in it for the money.

Note, that I’m talking about being a single developer. I still think there is money in doing iPhone apps for the bigger companies who can afford teams of people, and tons of advertising and promotion, and forge whatever allegiances with whatever demons you need to forge allegiances with to get your app featured in the iTunes store, which is like a golden ticket. So I’m not saying the app store is dead, merely that the gold rush days are over, and now it’s big business like anything other market. As a single developer, I won’t deny that you still might win the lottery, but I’m done chasing that dream.

I’m still going to refine and develop Falling Balls, as it’s still in the top 100 games, still making money for me, and with some cool new updates, could go even higher again. I have an update waiting for approval that brings different difficulty levels and should be out in the next few days.

I’m sure I’ll also continue to keep my foot in the door with other applications or games here and there. I love the Objective-C language, and have learned so much from diving deep into it for so long. I’m sure it’s made me a better developer overall. But any apps I do from here on out, will be purely for my own enjoyment. And technically, there is a lot of enjoyment to be had in creating things that use multitouch and accelerometer. It opens up all kinds of possibilities for creative, artistic apps.

But I’m also going back to Flash, and in fact, have started creating a brand new Flash game. I’m having fun getting back into AS3 after such a long hiatus. Pretty rusty though. 🙂 I’m also realizing some of the things I really missed about the Flash Platform as a whole. I think the biggest thing is the immediacy of it. I can code up something cool, upload it to my server, blog or twitter it, and instantaneously, thousands of people will be able to see it. No waiting. No arbitrary judgement of whether or not my SWF meets certain criteria.

Compare that to the app store approval and waiting game. When I started submitting stuff, it was an average of 3 days for approval. Now it is up to 12-14 days. That’s because app store submissions have about tripled in that time. And if waiting times are getting longer AND submissions are getting higher, that backlog is only going to continue to grow and grow. If I banged out a new iPhone application right now, nobody would see it til much later this month.

The approval process itself is getting a really bad reputation for reasons beyond the wait, as well. One is the arbitrariness of it. So many horror stories. Apps getting rejected for certain reasons, while another similar app with the same “problem” gets approved. Some developers have said that if you get rejected, just immediately resubmit with no changes. Chances are you’ll get a different reviewer who won’t be looking at the same thing the other one was looking at. Or one that’s in a better mood, or at the end of his shift and wants to go home. Or maybe it’s like airport security, where every nth app gets pulled aside and gone over thoroughly. Then there are the apps rejected with no reason given, and the apps which are simply kept in limbo for months, never approved or disapproved. And this week’s scandal with the Google stuff.

Actually, I’ll be the devil’s advocate on that one, and say Apple has the right to reject an app that competes with their own built in apps. They’ve made that explicitly known from the start anyway. But as for the other stuff, I don’t feel like Apple is being intentionally malicious in the delays and rejections, just that the app store has grown larger than they planned for, and they are struggling with the whole process. But it makes for a really bad developer experience. If you do get a rejection, you could be looking at over a month for app approval. That’s ridiculous. And the fact that it’s just a black box is doubly frustrating. You just submit and wait an unknown amount of time. No prediction on how long the wait is going to be. No feedback on where it is in the queue, nobody you can talk to to speed things up or find out what’s happening. If you get rejected, there’s no appeal process. You fix it and put it back into the black box for however long. Again, I don’t think it’s malicious, but it sucks big time. Luckily, in all my submissions, I’ve had only two rejections, which were valid items and easily fixed.

Well, that’s the end of my rant. By the way, all the stats I’ve mentioned here are from this page:

http://148apps.biz/app-store-metrics/?mpage

I can’t vouch for all the stats, but most seem correct except their submission wait times. I have not personally seen a drop off in wait times in the last month, only an increase.

34 responses so far

Skinning UIKit (iPhone) Sliders

Jul 26 2009 Published by under iPhone, Objective C

In my recently released app, Wire Draw (which you can read more about here) I wanted to create a color picker to allow the users to choose the colors of lines. Unfortunately there isn’t a color picker control in UIKit. I did find one on line, with full code on how to implement it, but that was a full screen affair and I just wanted something that would fit nicely into the existing settings UI. I finally decided on RGB sliders, which are easy enough to implement, but not very visual. I wanted the user to know instantly which was the red, green, or blue slider. I finally came up with what you see here:

I’m not saying it’s perfect, but it worked pretty well for me.

Skinning the sliders wasn’t the most obvious thing in the world to do, and I’m not sure I’ve seen any other apps that do it (I’m sure there are), so I thought I’d share what I learned.

First of all, create your slider. You can create and position it in code, or do it through Interface Builder. If you do the latter, make sure you create an IBOutlet for it and make the connection to that outlet in IB so that your code has access to the slider. All the skinning is done via code. We’ll assume your slider is named “slider”.

If you select the slider in Interface Builder and look at the Attributes Inspector, you will see two dropdowns for Min Image and Max Image. These allow you to put little pictures to the left or right of the slider. Say you were making a volume control. On the right, at maximum volume, you might want an icon that showed a little speaker with sound waves coming out. On the left, zero volume, you might want a speaker with no sound waves, or maybe even an “x” through it. That’s pretty simple, but is not what I’m talking about when I say skinning. Again, to skin the actual slider itself, you need to leave IB and write some code.

The methods that affect the appearance of the slider are:

setThumbImage:forState:
setMinimumTrackImage:forState:
setMaximumTrackImage:forState:

Let’s start with the thumb. This is the button that you press and move back and forth. Create a new image to use for this. I recommend you use a transparent png file, around 24×24 pixels. Here’s what I made for my red slider:

redthumb

Add that to your projects. Then add the following line of code, somewhere where it will run early and once, such as viewDidLoad of the view controller where the slider is located.

[slider setThumbImage:[UIImage imageNamed:@"redThumb.png"] forState:UIControlStateNormal];

This tells the slider to use the specified image as the thumb in the normal state. Actually, if you only specify the normal state, it will be used for all states. If that works for you, that’s all you have to do. If you want a different thumb to show when the user is pressing it (not that they’ll be able to see much of it with their finger over it), add another line with the other image and UIControlStateHighlighted for the state. You can also specify another image for UIControlStateDisabled. There are other UI Control States, but I’m not sure any of the others apply to a slider, so those are the three you’ll most likely be using.

But say we just stick to the normal state as above. We run the app and we get this:

slider_01

Hmmm… well, thumb skinning was successful, but we lost the rest of the slider! It seems that slider skinning is an all or nothing proposition. So let’s get to work on the tracks. As you saw, we have methods to set the minimum and maximum track images. But what does that mean exactly?

Simply put, the minimum track image is the image of the track that appears to the left of the thumb, and the maximum track image is what appears to the right of the thumb. Again, these have states that work just like the thumb image. Let’s just use normal for now, which covers all states.

I made a red track image which looks like this in it’s raw form:

redTrack

I also made a black one you can see here:

blackTrack

The red track will be the minimum image and the black track will be the maximum image, which will give you the effect you can see in the final screenshot at the beginning of this post. But you’ll notice that these track images are very small. That’s fine because they will be stretched to fill the entire space from the edge of the slider to the thumb. This is great if your track image is a solid fill rectangle with no shadows or anything. But let’s see what happens if it’s not, like the ones we are using. You can already probably figure out how to apply these images, but I’ll give you the code anyway:

[slider setThumbImage:[UIImage imageNamed:@"redThumb.png"] forState:UIControlStateNormal];
[slider setMinimumTrackImage:[UIImage imageNamed:@"redTrack.png"] forState:UIControlStateNormal];
[slider setMaximumTrackImage:[UIImage imageNamed:@"blackTrack.png"] forState:UIControlStateNormal];

Run that and we get this:

slider_02

Ouch. Yeah, it stretched them all right, along with the curved corners and shadows. Now, if you’ve come from the Flash world, you’re thinking, “Scale9!!! Use Scale9!” And right you are! There is an distant cousin of Scale9 in UIKit, called a “stretchable image”. You can create a stretchable image by taking a regular UIImage and calling the method, “stretchableImageWithLeftCapWidth:topCapHeight:” on it. This creates a new UIImage which can be stretched while not distorting the edges and corners, just like Scale9 in Flash. However, I said it’s a distant cousin, and it really is quite distant. Although they has the same end effect, stretchable images are defined quite differently. As you see, we only pass in two parameters: leftCapWidth and topCapHeight. What about the right and bottom? Well, those are kind of dynamic. Here’s how it works:

The leftCapWidth is the margin on the left side of the image that will not be stretched. The right cap width (although there is no actual variable named that) is the remaining width, minus one pixel. Alright, that’s not very clear. We need a drawing.

stretchable

Ignoring the topCapHeight for now (which you can do by setting it to zero), we see we have an image that is 21 pixels wide. If we set the leftCapWidth to 10, that means the first 10 pixels will not be stretched. What will be stretched is the next single pixel. Only that pixel and nothing more, and it’s always just one pixel. Finally, everything to the right of that single pixel will not be stretched. So, in the above example, the image is 21 pixels wide. The leftCapWidth is 10, then there is one stretchy pixel. That leaves the right 10 pixels as not stretchable, which would be your right cap width, if such a variable existed.

Note that while my example is symmetrical, it doesn’t have to be. If I had made the leftCapWidth 5, then the right portion would have been 15 (21 – 5 – 1). Or if the whole image was only 20 pixels and leftCapWidth 10, the right portion would be 9 (20 – 10 – 1). Again, the stretchable area is always 1 pixel, so I don’t think it’s too easy to stretch a gradient like you can do in Scale9 in Flash (not that it usually works out too well anyway). If you are into formulas, the width of the right portion is total width – leftCapWidth – 1.

The topCapHeight works exactly the same way, but we don’t need it here. Let’s put this into action. Rather than massively nested brackets, we’ll create a reference to the two stretchable images.

[slider setThumbImage:[UIImage imageNamed:@"redThumb.png"] forState:UIControlStateNormal];

UIImage *minTrackImage = [[UIImage imageNamed:@"redTrack.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:0];
[slider setMinimumTrackImage:minTrackImage forState:UIControlStateNormal];

UIImage *maxTrackImage = [[UIImage imageNamed:@"blackTrack.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:0];
[slider setMaximumTrackImage:maxTrackImage forState:UIControlStateNormal];

And that give you this:

slider_03

Yay!

Note that in this case, I could have made the right edge of the red track perfectly square, and chopped it off at 11 pixels. This would mean that the first 10 pixels would not stretch, the next (and final) pixel would stretch the rest of the distance, and nothing would be left over on the right side. Either way would work here, because the right edge of the track is hidden under the thumb. The inverse could be done for the black track.

Well, that’s all folks. Hope this makes a short part of your day a bit easier some time in the future. 🙂

11 responses so far

Falling Balls rewrite

Jul 19 2009 Published by under iPhone, Objective C

This is what I’ve been up to:

http://wickedpissahgames.com/?p=131

One response so far

Memory Allocation for the budding Objective-C programmer

Jul 10 2009 Published by under iPhone, Objective C

… or, “How I Learned to Stop Worrying and Love malloc”

OK, here’s a scenario:

You have a whole crapload of ints, or floats, or even CGPoints or CGRects. You need to hang onto these things and use them later. Hopefully you are not even considering making a whole crapload of variables to store them in, i.e. myNumber0, myNumber1, myNumber2, etc. If that even crossed your mind, close the browser, turn off the computer, go straight to the book store and pick up the first Programming for Dummies book you can find.

No, of course you immediately thought, “Array!” Good! Now, in Objective-C we have NSArrays and NSMutableArrays. NSArrays have to be initialized with all their content and cannot thereafter change. NSMutableArrays can have things added, removed, and altered at any time. Say you go for the mutable species, and say you want to use it to store a bunch of ints. I guarantee your first attempt would look something like this:

NSMutableArray *myArray = [[NSMutableArray alloc] initWithCapacity:10];
[myArray addObject:0];
[myArray addObject:1];
[myArray addObject:2];
[myArray addObject:3];
[myArray addObject:4];
[myArray addObject:5];
[myArray addObject:6];
[myArray addObject:7];
[myArray addObject:8];
[myArray addObject:9];

And as you run your app, it’s going to crash. Hard.

Or say you try to add some points:

[myArray addObject:CGPointMake(100, 100)];

Now you are going to get an error like: “incompatible type for argument 1 of ‘addObject'” Why? because ints are not objects. They are primitive types. In Objective-C, an object is something that extends NSObject.

An int is not an object, but I believe will get interpreted as a pointer. And when it tries to read the “objects” at memory locations 0 through 10, it doesn’t find what it’s looking for.

CGPoints and CGRects are also not objects. They are structs. A struct is essentially a chunk of memory that can hold multiple values of multiple types. A CGPoint holds two floats. In fact, you can see the actual definition by Command-clicking on CGPoint in XCode:

struct CGPoint {
  CGFloat x;
  CGFloat y;
};
typedef struct CGPoint CGPoint;

(CGFloat is just a typedef for float.)

A struct is not an NSObject so you get an error.

One solution would be to wrap the int in an object. Objective-C has a NSNumber object for this purpose. So you change the code to something like this:

[myArray addObject:[NSNumber numberWithInt:0]];
[myArray addObject:[NSNumber numberWithInt:1]];
[myArray addObject:[NSNumber numberWithInt:2]];
//etc.

Now, when you want to get those ints back, you do something like this:

myInt = [[myArray objectAtIndex:0] intValue];

I don’t know about you, but that’s an awful lot of overhead for saving and reading a list of integers.

But let’s look at structs. There is no “NSPoint” or “NSRect” so you’d have to create your own class that extends NSObject, wraps up a point or a rectangle, makes it accessible as a public var or a property, and use that in your array. So you get something perhaps like this:

[myArray addObject:[MyRectObject objectWithRect:CGRectMake(0, 0, 100, 100)]];

and similarly wicked verbose code to retrieve the value. And not only is does it take up finger resources to type all that, it takes CPU and memory resources to create all those extra objects, and access them via various methods, not to mention the fact that you’re going through high level “objectAtIndex” methods in the array class itself.

So let’s look at a much simpler way to do it. Enter malloc.

malloc means memory allocation. It’s a very low level, core C function that lets you directly allocate a chunk of raw memory and use it how you want. Powerful stuff. Blah blah blah great power, blah blah blah responsibility. In other words, you have the power to seriously crash your computer/iDevice. And you probably will. So get over it. It’s not going to melt or explode. But you may have to reboot it every once in a while until you learn the ropes.

Basically, you call malloc as a function, passing in how many bytes of memory you would like. The system reserves that chunk of memory for you and hands you back a pointer to it. You should cast this data as a pointer to the type of data you are storing in it. Like so:

int *myInts = malloc(numberofbytestoallocate);

So how many bytes should you allocate? Well, it depends on how many “things” you want to store in there, and how big those “things” are. The first part you probably know, the second you probably don’t. Luckily there’s a sizeof function that will figure that out for you. So you do something like this if you are storing 10 integers:

int *myInts = malloc(sizeof(int) * 10);

Or if you are storing 50 CGPoints:

CGPoint *myPoints = malloc(sizeof(CGPoint) * 50);

You get the point. Or the 50 points. (I crack myself up sometimes!)

Now, you can access that chunk of memory with bracket notation:

myInts[0] = 10;
myInts[1] = 20;
myInts[2] = 30;
myInts[3] = 40;
// etc.

Or:

someNumber = myInts[8];

Very simple, very low level, very efficient. Also, very dangerous. If you suddenly decide to say something like:

myInts[99] = 50;

and you only allocated enough space for 10 ints, you have no protection whatsoever. Your program is going to go to whatever location myInts[99] happens to land on and write the int value 50 there, with no regard for any consequences. You’re not going to get a compiler error. You’re not even going to get a runtime error that politely tells you are attempting to access an element of an array that is out of bounds, so sorry for the inconvenience. No, it’s just going to do exactly what you tell it to and claim it was just following orders. Generally, this means your app is going to crash and burn, fast and hard, with no explanation at all. So don’t do it. OK, you’re going to do it. But after a few times, you’ll realize what you did and you’ll do it much less often.

Generally this means that you are going to keep an extra int or two around to serve as indexes. Maybe one to indicate the maximum amount of values you CAN store in the array, and one to indicate how many values actually ARE in there. For example:


#define MAX_THINGS 100
int *things = malloc(sizeof(int) * MAX_THINGS);
int numThings = 10;
for(int i = 0; i < numThings; i++) { things[i] = i; }[/c] You don't want MAX_THINGS to change, so that's a good candidate for #define. numThings could change so we'll leave that as an int. Here, since we are only setting the first 10 out of 100 things, the other 90 will have garbage values. You're totally safe to read and write them, but don't expect them to have any meaningful value until you set them. The last thing to mention is to clean up after yourself. You asked for a chunk of memory, and the system was nice enough to give it to you. Actually, it just lent it to you. When you are done, give it back so someone else can use it. Do this using the free function: [c]free(myInts);[/c] Where you do this is wherever it makes sense. If you are just using the array as a local variable in a method, free it up as soon as you are done using it. If it's a instance variable of a class, free it in the dealloc method. That's the bare bones of malloc. There might be other things you want to look up. For instance, what if you ask for a big chunk of memory and the system can't allocate it. Generally 10 ints or 50 CGPoints won't be a problem, but you might want to look at what happens if malloc fails, to make sure you guard against that. So happy mallocing, happy crashing. Once you get the hang of it, it's a pretty cool feeling to have that kind of fine level of control over the memory your program is using, especially if you are coming from the ActionScript world, where memory management is a secret black box that occasional posts by Grant Skinner gives you some shadowy concept of what's going on in there. With C and malloc, you know, because you are calling the shots.

20 responses so far

XCode tips

Jul 08 2009 Published by under iPhone, Objective C

[Note, XCode 3.2 did away with the Errors and Warnings Smart Group. 🙁 Its functionality is now moved to the Build Results Window. I’ll probably write an update to this whole setup soon.]

After a few months of working with XCode, I’m starting to fine tune my set up to make it easier to code, compile and debug. A couple of tips for today on dealing with compile errors. Say you compile and you have an error in your code. Don’t laugh. It could happen. With the default setup, you’ll get something like this:

xcode-1

At first those little bubbles seem kind of neat, but after a while, you will hate them. They persist after you fix an error, til the next build, unless you double click on them, and it’s like driving with a bug on the windshield. So first thing we do is turn them off.

xcode-2

Now, you’ll still get the red x, which you can click on to see the bubble if you want. But we’ll soon see something better.

xcode-3

The next problem is, what if the error(s) isn’t in the file that is currently shown in the editor? You see down in the lower right corner that your build failed with one error, but where is it? Well, you can click that message, which opens the Builds Results window.

xcode-4

You see this shows and describes the error in the top part of the window, and opens the file in the file itself in the bottom. So no need for the bubbles anymore. A few things I don’t like about this though. Most of all, I already have an editor window open. I don’t like having this other floating window with another editor. The other thing is that the top window shows not just errors and warnings, but the whole build process, so if you have a few errors, you kind of have to pick them out in a long list of other messages. It’s not too hard, but I’ve found yet a better way. The Errors and Warnings Smart Group. Set this to open up automatically any time you have errors or warnings:

xcode-5

Now, if you have errors, they will appear in that group, that group will be selected, and in the details window at the top of your editor, you will get a list of all errors and warnings, and nothing else. Click on any error and it will open up in your main editor window. Furthermore, you can look at the group itself to see which files have errors. In this case it’s just one error in the App Delegate file, but if there were problems in multiple files, they would all be listed in the smart group, and you can click on a file in that group to just see the errors in that particular file.

xcode-6

The final thing I do is change the position of this smart group. By default it is placed way down under Targets and Executables. In this simple example, which only has a single class, it’s no problem, but when your classes group and resources group contain a whole bunch of items, and those are expanded, the Errors and Warnings group will be way down out of sight. But when it’s selected, the whole Groups and Files panel will scroll down to show it, and when you’re done you have to scroll up again to get back to your files. A minor thing, but what I do is just drag the Errors and Warnings group up to the top.

xcode-7

Following the settings image above, it will automatically if you have no errors or warnings, so it’s never in the way, but opens up and is selected and above everything else when you DO have problems. Right where you want it.

So some minor tweaks, but I find it streamlines development quite a bit. You have errors, they show up in a list at the top details panel right away, with the list of files in the top left. Click on an error and the file is displayed, right at the particular error. No nasty bubbles in your way.

9 responses so far

Objective-C Memory Management tip o' the day

Jul 04 2009 Published by under iPhone, Objective C

Still getting used to this whole memory management thing. I thought I had it pretty much squared away, but just ran into a spot where I got complacent and let a bunch get by me.

I’ve been working mostly with cocos2d, where most of the objects are created with a static “node” or “spriteWith…” type methods, which return an autoreleased instance of the class you want.

mySprite = [Sprite spriteWithFile:@"some.png"];
myScene = [SomeScene node];

Since these autoreleased, you need to immediately do something that’s going to retain them if you want to keep them around. In most cases, with something like a sprite, you are adding the sprite as a child of another object, which retains the sprite that is added. In some cases, you might be adding it to an array, which also retains it. In these cases, that’s usually all you want to do, because then when you remove it from the parent or the array, or release the array or whatever, the instance is released and dealloc’ed.

mySprite = [Sprite spriteWithFile:@"some.png"]; // autorelease
[myScene addChild:mySprite]; // retains mySprite
... later ...
[myScene removeChild:mySprite]; // releases mySprite. retainCount reaches 0, and it's dealloced

Of course, if you want the sprite to stick around after removing it from the parent, retain it explicitly. Also, if you are NOT immediately adding the autoreleased object to something that will retain it, you will need to explicitly retain it:

mySprite = [[Sprite spriteWithFile:@"some.png"] retain];

Now it will stick around, so you can add it to a parent object later. But remember, when you remove it from the parent, it will still have a retainCount of 1, so when you are really done with it, you’ll need to give it one more release:

[mySprite release];

So this brings me to where I messed up. Again, I got really used to these autoreleased objects. But then I created several “regular” objects for my model, using alloc/init, and added these to an array. I was stuck in autorelease mode, so I was doing something like this:

myModelObject = [[ModelObject alloc] init];
[modelArray addObject:myModelObject];

Of course, when you alloc something, it gets a retain count of 1. This is not autoreleased. Adding it to the array, retains it again. Later, I was removing the object from the array, thinking that was the end of that. But it still had a retain count of 1. I wound up with a bunch of model objects never getting dealloced. Worse, these model objects were holding a reference to the view (I know, I know, questionable architecture to say the least), so even after the view (which was a cocos2d sprite) was removed from its parent, it was still being retained by the model and was sticking around, eating up not only memory, but running animations behind the scenes. The solution was simple:

myModelObject = [[ModelObject alloc] init];
[modelArray addObject:myModelObject];
[myModelObject release]

You’re safe to release it here, because the array is retaining it.

Now, this wasn’t some blinding realization. As soon as I saw the alloc/init without a release, it was a “duh!” moment. Found these in several places, cleaned them up and got a stellar performance boost. (Now I’m going to clean up that model/view connection.)

Anyway, not really sure what the point of this is. Just one of those things where you’re happy to find something big that really helps your app and you want to share it with someone. My wife and daughter didn’t really care. 🙂

10 responses so far

Older posts »