Mar 25 2010

Responding to the “iPhone SDK vs Windows Phone 7 Series SDK Challenge”

Tag: Code,ProgrammingAdam Wright @ 7:53 pm

Over at his blog, Shawn Burke is running a series on “iPhone SDK vs Windows Phone 7 Series SDK Challenge”. He takes examples from Apple’s iPhone SDK, and shows how to create them using the Windows Phone 7 SDK, taking care to crow about supposed advantages of the Microsoft approach. In this post, I figured I’d examine his first “Hello World” example, and see how accurate the result is.

Note beforehand that I’m not disputing the power of WPF and C#. Given the choice of C# of Objective C, I’d probably rather work with C#. However, these types of language/API comparisons are rarely useful, nearly always mistaken, and correcting the record seemed an interesting task.

The first problem is that the title is inaccurate – it’s “iPhone SDK Hello World Tutorial vs ad-hoc implementation in WP7 SDK”. To show this, he goes through the tutorial and shows the same result prepared in WP7, with the banner claim being “4 lines of Code for Windows Phone 7, 44 for iPhone”. This is, at best, disingenuous. In the following video, I make the iPhone “Hello World” application using exactly the same number of typed lines of code as Shawn’s blog post. It’s not monumentally fascinating, but might show some Interface Builder features that are not widely known.

He makes two other points I’ll call out before exploring why he might make these mistakes.

“I was surprised that the User Interface Designer in XCode doesn’t automatically create instance variables for me and wire them up to the corresponding elements”

As shown, you can have Interface Builder create instance variables you need them. Regarding the automatic generation of instance variables, this is, I suppose, a matter of opinion – but years of Windows Forms programming has taught me that automated generation of instance variables for all UI elements is a nightmare. Your namespace is cluttered with dozens of instances you never need to reference and just add noise to your code.

“10% of the code, 1 file instead of 4, it’s just much simpler”

As shown, the amount of code you have to write it identical. 1 file instead of 4 is just wrong – if you download his sample program, there are 2 XAML files and 2 C# files. Counting the NIB file and main.m files as part of the iPhone solution, there are 6. So it’s 4 vs 6 in terms of files in the project, but identical in terms of the number of files you need to edit (1 XAML and C# vs 1 NIB and M file).

Why make the errors?

Shawn based his comparison on the Apple Tutorial. Why doesn’t the iPhone “Hello World” tutorial do it my way? Because Apple tutorials teach you the “Apple way” of development; “Best practice iPhone development”, if you will. Cocoa is, for better or worse, as much a philosophy as an API. If you don’t buy into the MVC approach, if you don’t structure your code in a Cocoa friendly way, you’ll be able to develop – but you’ll find it painful. As in it’s products, Apple tries to guide developers into the “right” mindset. Therefore, a fairer comparison would have been “iPhone Hello World vs Best practice WP7 Hello World”.

This is not to say there aren’t real missing features from the iPhone development environment compared to the new Windows 7 setup. Largely, this is down to Apple being conservative with the runtime features they provide for the iPhone OS. Partially, they’re feeling their way as they go. More importantly, they’ve been working on relatively limited hardware. The latest iPhone OS still supports the original iPhone, which had only a 412Mhz ARM CPU with 128Mb of RAM. Windows 7 will mandate a minimum of an ARMv7 Cortex/Scorpion with 256Mb RAM, giving the OS and application runtime a minimum of twice the memory and compute resource to play with.

If we compare against Cocoa/Objective C for OS 10.6, we see a lot of features that are waiting to be ported to the iPhone: Blocks (i.e. lambda functions for C), garbage collection, and API improvements. Given the ever progressing iPhone hardware (and new iPad), I’m expecting these shiny developer tools for iPhone 4.0 – personally, I’m voting for blocks, though a lot of people would prefer garbage collection). I’m also expecting Apple to keep forward porting Application Kit features that are currently missing – Cocoa bindings being the big one. With these, Interface Builder for OS X can build the “Hello World” desktop app without ever writing a single line of code (in fact, by typing only “Hello World” and “Hello” at the keyboard).

As a cross platform developer, I’ll continue reading the series with interest. I do hope, however, for rather fairer comparisons in the future.

EDIT: Woops, first version claimed there are, in fact, no missing features in iPhone development. Now clear that I’m not under RDF influence.


Jun 01 2007

A route to the past: Magellan 2 (Part III)

Tag: Code,ProgrammingAdam Wright @ 7:58 pm

Right, we left off (a long while ago), having looked at the basic dungeon layout. The question was, how do we turn the geometry of a dungeon cell into a two dimensional map? Let’s look at a (badly, hand) drawn section of a dungeon wall. It’s got a floor, some obvious wall, and a little “hump” – some kind of rock, or bizarre architectural anomaly (it is a dungeon, after all).

Vector art image of dungeon geometry

We can see the raw triangles in 3D, and we’d like to get this down to a set of lines in 2D (we can draw lines very easily using the APIs available to us). To accomplish our goal, we’ll need to think about what we actually want to see on the map – showing the floor, and little lumps and bumps is not really useful information for people. The only real obstructions that they’ll want to see mapped are the extents of the dungeon – the walls.

How can we distinguish a wall from the geometry? Well, the distinguishing fact I used in my simple algorithm was that it’s vertical – everything within a certain tolerance of the vertical axis is a “wall”, and would appear on the map.

On this diagram, we see the tolerance region – all polygons that are upright enough to be contained within the triangle are going on the map. Let’s remove everything that’s outside the verticality acceptance region, and see what we’ve got left.

Tolerance region for wall verticality

Not bad – everything remaining looks pretty damn wall like to me. All we’ve now to do is turn this into a set of lines, discard the vertical components, and we have a reasonable 2D representation of the dungeon block we can use to map.

The final wall geometry

That’s pretty much it for Magellan 2 – once these line blocks are collected, they’re simply transformed (by some simple mathematics) to deal with the translation and rotation of the dungeon relative to the current viewpoint of your character. Rendering them to the screen is just a case of taking each line, transforming it, and then telling Decal “draw this line starting here and ending here”.

There are plenty of problems with this approach (some of which manifested themselves in the released version); however, this explains the basic concept (which was all I set out to do). One day, if there’s interest, I might write about these design faults, and the potential improvements that could be made.


Apr 11 2007

A route to the past: Magellan 2 (Part II)

Tag: Code,Mathematics,ProgrammingAdam Wright @ 11:29 am

Just to clear up some misconceptions, the point of this article is not to recreate the plugin, or repair it for the modern Asheron’s Call. The plan is to write a set of articles on how it was created, and why it (in general) worked. Those looking for a replacement would do well to visit http://www.flynn1179.me.uk/ac/?minimap and see the impressive looking work that Thorfinn Sigurdssen has been doing (Disclaimer: I have neither personally tested this, nor been contacted by the author).

Last time, we left off having made a series of educated guesses about how the dungeon system in AC works. From our observations, we’ve noted that every dungeon seems to be laid out in a giant 3d grid of cubes – assembled as if from lego bricks, prefabricated elements of dungeon.

AC Dungeon template

We can see the prototypical dungeon template above – each little cube is ready to be filled with a one of a choice of dungeon blocks by an eager designer. A template block might look as follows.

AC2 Dungeon cell

This one is taken from my Asherons’s Call 2 archives (so don’t go looking for it in game), but it illustrates the point. The player walks around on the interior (the complex looking set of triangles), and the rest of the cube is filled with virtual nothingness – in this fashion, we can make our big cubes look like caves, temples, whatever is needed (rather than a boring apartment block).

We could take four of the above dungeon elements (that we call dungeon cells), rotate them around and put them into adjoining cubes in the template to create a donut dungeon – a giant loop. Obviously, it’s up to the designer to ensure that there’s no corridor or tunnel that leads into an unfilled cube (and hence into the void).

This is all well and good, but now that we’ve made a plausible (and in this case, rather educated) guess at the dungeon structure, how does it help us? Our task is to draw a map of the walls of the dungeon, not big wireframe meshes stuck around the place! So, tune in next time to see a little bit of simple mathematics that will transform the above into something more useful for our purposes.


Mar 27 2007

A route to the past: Magellan 2

Tag: Code,ProgrammingAdam Wright @ 8:38 pm

It’s been a long time since I posted anything here, but as I only write when I have both time and something to say, it’s not that surprising. I’m moved to put fingers to keyboard today to discuss something I still get regular e-mails about – an old Decal plug-in, Magellan 2, for Asheron’s Call (for those who don’t recognise these terms, an older article series might be interesting).

The main function of Magellan 2 was as a dungeon mapping system – it would automatically generate real-time wireframe overviews of any dungeon as you walked around it. There’s nothing particularly amazing about it; indeed, retrospectively, a lot of how it worked was naive at best and bad at worst. However, a lot of people seemed to like it, and I still get about an email a fortnight asking for source code & technical information. So far, I’ve been sending out the code about once every 3 months, to give each person a chance to repair the code and publish something, alas to no avail. Hence, I figure it’s time to publish something more general and see what people can create.

Magellan 2 mapping screenshot

Now, Magellan 2 did more than just map dungeons but the additional functionality (place search etc) is pretty trivial data management and nothing we’re interested in. We’ll be focusing on the map generation, but I’m not going to write this as a detailed set of technical specifications – more as a journey of creation suitable for all who are interested. Hopefully the information contained within, plus additional downloadable material will give people everything they need to recreate the work, if they want to.

Phase One : The problem

What we want: To create a client integrated real time usable map display of any dungeon a player wanders into, something that will help them both find their way around and allow them to explore the full depth of the dungeon (no more missed turns!).

What we we know: We have two data files, “cell.dat” and “portal.dat”, which form an archive of many thousands of smaller files. We also have some vague idea of how the AC client software deals with the problem – we know that when we enter a new dungeon, some data is downloaded and the “cell.dat” file gets larger. We also know, from our many years of dungeon crawling, that dungeons are very “modular” in design – they seem to be built out of standard components, reused many times within the dungeons.

What we can do: We can read the files contained in the cell.dat and portal.dat archive files. We can also, via Decal, draw onto the players screen, and find out their location and orientation in the world.

The challenge is set! Over the next few articles, we’ll see what we can create.


Aug 08 2006

Continued (2): Simple concurrent evaluation strategies in mainstream languages

Tag: Code,Computer Science,ProgrammingAdam Wright @ 3:35 pm

OK, so we’ve all been busily tapping away at our keyboards trying to implement the rough design we came up with last time. Let’s have a look at one way of doing it (this is just one way; there are obviously many different methods).

    public class CallByFuture<T>
    {
        public delegate T CallResult();

        public static implicit operator T(CallByFuture<T> instance)
        {
            return instance.Result();
        }

        public static T operator ~(CallByFuture<T> instance)
        {
            return instance.Result();
        }

        private System.Threading.Thread workerThread;
        private T result;

        public CallByFuture(CallResult func)
        {
            workerThread = new System.Threading.Thread(delegate(object state) {
                ((CallByFuture<T>)state).result = func();
            });

            workerThread.Start(this);
        }

        public T Result()
        {
            workerThread.Join();

            return result;
        }
    }

The implementation has tried to stay as close to the design goals as possible; we have a generic class, parameterised by the return type of a delegate which the user will create (either implicitly through an existing function, or explicitly with an anonymous method). The construction spins up a thread which evaluates this delegate, and gives the result back to the enclosing CallByFuture class to be made public via a Result method which will block until the answer is available. For syntactic sugar, we allow the unary bitwise NOT operator as a shortcut to the Result method (so rather than a call to the result type T expressed by the CallByFuture being t.Result().Foo, we have simply (~t).Blah.

The use of operator~ as an “easy conversion” might seem rather strange – after all, the language supports explicit type conversion operators natively. It does not, however, support having both an implicit and explicit conversion operators for the same type; the people who actually read the code will have noticed the implicit conversion snuck in at the top of the class.

The implicit conversion is very useful – it allows you to use a CallByFuture in most cases you want a T without any additional syntax. However. I would personally probably flag its inclusion as “controversial ” in a code review mainly due to the excessive “magic” behind the conversion of complex types – an innocuous usage of a variable might entail a complex evaluation behind the scene (rather than the virtual no-op of just reference passing you were expecting) – it might even throw an exception. In our case, the worst that can happen is that it must wait until the result is evaluated (any exceptions will be thrown on the CallByFuture thread, and we’ll discuss them later). Total worst case, the evaluation locks because the CallByFuture delegate never completes.

Our implementation rules stated we wanted something we could “drop in” to existing programs, and the implicit conversion certainly aids in that so next time, we’ll look at mitigating the problems it raises as well as some usage examples to prove this really does work.

[Edit: Woops - forgot to actually include operator~]


« Previous PageNext Page »