It lives!

Night Snake

Programming-Rattle-Python celebrates development success outside his evil castle lair

Et voila, a map editor was born. It took a couple of hours longer than I expected, but I got a tad carried away with the odd extra feature or two as well as bumping into the unexpected.

Fortunately, I had the help of Programming Python (who, as you’ll note, is actually a rattlesnake, but he has python capabilities thanks to some nifty genetics) otherwise it would have taken even longer.

As a Cocoa beginner, some things that I thought would be easy turned out to be a little more challenging – and not because they were hard, but because they were different to the way I’d done things under Win32. Take mouseMoved() events. Turns out, you also need to specifically enable these babies and you need to be the first responder or jack shit happens. Thus, this:

- (void)mouseMoved:(NSEvent *)event
	NSPoint nsEventPoint = [event locationInWindow];
	Vector2 eventPoint(
		GLEngine::GetInstance()->GetScreenHeight() - nsEventPoint.y);

Without this:

[[self window] setAcceptsMouseMovedEvents:YES];
[[self window] makeFirstResponder:self];

Equals “is it beer time, yet?”. If I was totally honest about how long those two lines took to write, we could all have a little cry. Then there was the NSSavePanel. What tripped me up here was not that it was complex to use (it wasn’t, I had it up (ooerrrr) about 2 minutes after finding it in the documentation), but that I had to extract a filename out of the darn thing that fopen() would use.

[savePanel beginSheetModalForWindow:window completionHandler:^(NSInteger result)
    if (result == NSFileHandlingPanelOKButton) 
        // Close panel before doing anything:
        [savePanel orderOut:self]; 
        g_pMapEditor->SetFileName([[[savePanel URL] path] fileSystemRepresentation]);

That innocuous little line that calls the SetFileName() function in my map editor class took a whole whopping hour to solve at about 7AM yesterday, and I think we can all agree that 7AM is an inappropriate time to be programming at all let alone suffering over something that should be unbelievably easy. Still, now I know, so it will be easy for my other projects.

The final thing that really kicked me around was scrolling a NSOpenGLView using scrollbars on a window. I use OpenGL to provide my 2D display since I stole the whole engine, give or take a poke here and a twiddle there, from the iPhone game. Plus, I have a decent library of functions for drawing stuff. Mere words cannot describe how frustrating this bit was: it’s one of those things that you either know, or you do not. Looking it up isn’t enormously helpful either as you have to draw from many examples to finally get working code particularly as everyone’s individual problem was slightly different: some were scrolling 3D views, some wanted scrolling to adjust the display beyond scrolling, others wanted a window resize to scale the image and so it goes. Ultimately, it involved taking offset information from the NSScrollView:

NSRect clipViewRect = [[scrollView contentView] bounds];
const float leftOffset = clipViewRect.origin.x;
const float topOffset = clipViewRect.origin.y;

And feeding that into the glOrtho() call correctly later on after clearing the colour buffer:

glOrtho(leftOffset, leftOffset + viewPortWidth, 
	topOffset + viewPortHeight, topOffset, 
	-1.0f, 1.0f);

It’s always amusing to note that the final answer is actually bloody obvious when you see it. I still have an annoying problem where the vertical scrollbar scrolls “upside down” because I insist on being an awkward bastard and specifying that -1.0f in the glOrtho() call above: it makes the origin top-left rather than bottom-left. This is because it’s what I am used to and I pay the price all the darn time. Perhaps it’s time to let the bottom-left-ness of OpenGL to wash over me…

Still, the final spanner almost wrenched from the application’s cogs and gears, I was creating levels!

Map Editor Demo

Temporary graphics a-go-go! Still, I remember when it was all fields around here.

Obviously these are not the game’s graphics. These are some random blocks I knocked up in Seashore, a free open-source art package. I’d eat an entire nest of ants if I could get Paint.NET on the Mac. As much as I appreciate the fact that I have a free art package that’s fine for the odd cut-out-type-thing, this was the best I could do in thirty annoying, frustrating minutes. It’s based on GIMP, I understand, which is probably why it has more issues than I did when I was a teenager in the 80s. It’s almost as if someone specifically set out to irritate the hell out users. Perhaps I should dust off the wallet and actually consider purchasing something in order for Cobra Art to thrive as it deserves to.

The editor is workable now in that as of last night I’ve successfully created a level with it and loaded it into the iPhone game. There is still much to do, though:

  • Better block choice with visual representation
  • Operation IDs from a nice drop-down combo
  • Neater UI and on-map display of game-play flags and operation IDs
  • Show animating blocks on the main display
  • Entity placement and behaviour specifying (still manual at the moment)
  • Parallax editing: those radio buttons you see are in the GNDN1 category

All in, a day or two over the coming month will yield a pretty good editor, I reckon. Now, if I can just find a victim volunteer to use it, all will be well! And let’s face it, we’ve all learnt something about scheduling today: add at least 50% to every estimate you make and you’ll still be wrong.

On the bright side, it’s pub lunch day today for no reason other than the day begins with a “W” and the weather is excellent. Still, I can bask with a pint knowing that the update report for May won’t look nearly as grim as April’s, eh?.

1 Goes Nowhere, Does Nothing. From Star Trek. Yes, that’s right, Star Trek. Honestly, this is a developer’s blog, what did you expect?

This entry was posted in My iPhone game and tagged , , , , , . Bookmark the permalink.