Timeline

How I prepare for talks

Among Jaimee Newberry’s fun daily video diary entries is an especially useful one on how she prepares for giving talks. Graham Lee offered his take on preparing for giving talks.

That got me thinking. What do I do? I’m more a Jaimee-Talker, but I don’t really do a single idea in a talk that often. I have a note in the Notes app with all my talk ideas where, every time I encounter a problem or question, and every time I e.g. find myself answering a question on Stack Overflow or at work, I make a note of it.

I try to group them by topic, and that usually quite naturally turns into a way too long talk outline. Then when it’s time to give a talk, I pick the choice bits out of one or more of these outlines, and make that my outline, sometimes changing the focus. E.g. once I had the mandate to add a missing beginners’ talk on Quartz to a conference, so I took the most basic, most practical graphics issues from my notes, prefixed them with a general tutorial on how the Quartz is organized and that was my initial outline.

Then I built a first rough slide deck based on those notes and just started holding the talk using Keynote, with the audio recording function on, in the privacy of my own home. Sometimes, once the talk has advanced a bit, I even (similar to Jaimee) set up my iPhone or iPad to record myself.

So, how does a talk “advance”? Well, it’s simple. First and foremost, I make notes for every slide about the things I’ve said. Also, at some points giving a talk, I will get stuck. Or I will repeat something I’ve already said earlier. Or I’ll explain something in words that would really need an illustration. At that point I drop into Keynote and either re-arrange the slides, or do a first rough illustration.

Once I’ve done this a few times, the talk will feel much more fluid, but will be running horribly long. So I try to do a full run-through without interruptions and time it. Once I have my time, I’ll try to find things I can cut and mercilessly cut them. Things that feel like a detour, or boring, or too trivial. Things that the intended target audience would know already. But sometimes I also realize that I haven’t explained something that needs explaining and add a slide.

Then I do the talk again. Rinse and repeat, until the timing and flow is right. When the slides have stopped moving and disappearing, and I’m happy with what’s in the talk, I’ll start refining the illustrations. Adding builds that reflect my description. Usually that on one hand forces me to go through these slides at “the speed of build”, but it also shortens my descriptions very much, so often it evens out.

If it doesn’t, I might have to cut some more slides, or find a way to simplify what is there to make it go faster.

As you can tell, this is an approach best suited to more technical talks. More “philosophical” talks sometimes can be analyzed enough that this approach works. Other times, they’re more like stories, making them harder to re-arrange and to cut out stuff. I generally still use the same approach, but it doesn’t work as reliably. What can I say, it’s a work in progress, and I’ll work at sucking less at the not-a-story-not-technical-either kind of talks as I can.

I haven’t mentioned the title yet. Usually, it comes at the end. I have a working title (e.g. Memory Management Fundamentals), and then look at what is actually in my talk and pick a better name (e.g. On graph paper and memory).

Sometimes, I need to provide a title when I sign up as a speaker. As I already have the notes, I’m usually pretty good at picking a title that works. Sometimes they let me change it afterwards. Sometimes they don’t, and I go for that title with a byline that narrows it down to what the new title would be. (Don’t put a different title on your first slide than is announced in the programme, attendees won’t find you)

One thing I sometimes do in the end is I record myself doing the final talk (with the iPhone camera or whatever) and watch myself doing it, watching out for how I look. Am I scratching my nose? Do I say “umm” a lot? Then I try to remember to turn that down.

How to install Windows 8.1 on a Mac

It is not quite trivial to buy Windows as a download and get it onto your Mac. I’ve found a workaround, but it takes a lot of time, and requires you to download about 7GB of data via the internet.

Disclaimer: I do not guarantee that these steps will work. They worked for me in late June 2015, YMMV. Do not blame me if you buy a download version of Windows and then can’t install it. Also, be sure to make a backup of your entire hard disk/SSD before you do this. You will be resizing partitions and doing other things that could lead to accidental loss of data.

The Problem:

  • The microsoftstore.com Windows 8 download is a small .exe file containing a downloader application that needs an already-installed Windows to work.
  • Macs these days don’t have a DVD drive, so you’d need to buy/borrow one to be able to use install DVDs mailed to you.
  • Boot Camp Assistant assumes a physical DVD or an ISO disk image, it obviously can’t run the .exe under MacOS.
  • I was unable to get the .exe downloader to run under CrossOver on MacOS.

My workaround:

  • Download the trial of Windows 8.1 for Enterprise as an ISO image from Microsoft (need to create an MS account which you will also later need to buy the download)
  • Use Boot Camp Assistant to install that onto an empty USB stick that is at least 4GB (not just the Apple-specific drivers, check the option for the full install partition). The stick will be formatted using Windows’ old FAT32 format, which both Mac and Windows can read and write.
  • ~100GB (at least 60) is a good size for the Windows partition to add to your internal hard disk/SSD.
  • Boot Camp will now churn a while and copy the files from the ISO on your USB stick, and will also download the newest hardware drivers from Apple and make sure those get installed as well. Time for breakfast.
  • When Boot Camp Assistant reboots, hold down the option key and select the “EFI Boot” entry to make sure you don’t end up back in MacOS.
  • You will find yourself in the standard Windows installer now. Follow its directions. On Retina Macs, it will be at a tiny 1:1 resolution. Bring a magnifying glass.
  • When asked where to install the Boot Camp partition, find the one named “BOOTCAMP” and select it. Remember what else it says (e.g. “Disk 1 Partition 4”).
  • If the Windows installer complains about the partition not being formatted as NTFS, Click the “Format” button underneath the list, but don’t do any repartitioning with the Windows tools, you’d only disturb the fairy dust that Boot Camp Assistant has applied and break booting back into MacOS.
  • Select the reformatted disk (which has now lost its “Bootcamp” name) and click “Next” to start installing the trial.
  • Make lunch while pretty colorful screens rotate through and Windows is set up for you in the background.
  • Run through the Boot Camp installer that runs in Windows after the standard Windows installer has finished.
  • Once you have a working trial install of Windows, buy the download .exe from microsoftstore.com, if you haven’t already. Unless they say they don’t, installers include both old-style 32-bit versions and the 64-bit versions needed for Macs, don’t worry.
  • Run the .exe you just bought while you’re running the Enterprise Windows Trial to create a proper ISO with your purchased Windows 8.1 on it.
  • Back up that Windows.iso and its license key somewhere safe.
  • Copy the Windows.iso onto the USB stick so you can get at it from MacOS.
  • Note down the Windows license key somewhere, you’ll need to type it in in a moment.
  • Boot back into MacOS and run Boot Camp Assistant a second time to remove the trial partition. (BCA doesn’t let you run it again on an existing partition, so you’ll have to nuke and recreate)
  • Run Boot Camp Assistant a 3rd time, this time using the new ISO, not the trial, to get the desired full Windows install. Remember to hold down the Alt key at startup to select “EFI Boot” or you’ll just end up back in MacOS.
  • When the standard Windows installer comes up, you’ll need to enter your Windows license key this time. From then on, the install will be identical to the trial install.
  • Your Yak is shaven clean as a baby’s bum.

Note: In theory, it should be possible to run the .exe under the trial to directly install Windows 8.1 on top of the trial instead of generating the ISO, but I didn’t want to risk it somehow generating a mix of the trial and purchased Windows installs, or eliminating the Boot Camp-supplied drivers & programs, so I decided to nuke the trial once I had the ISO and start fresh. Whatever you do, generate and back up the ISO so you don’t need to request another trial from MS when you inevitably want to reinstall Windows at a later time, even if you then use the .exe and not Boot Camp for the second installation.

Thanks:Thanks to Sören for pointing me at the Windows trial version that made this possible.

Microsoft supports UIKit

iPhoneOnWindows

This week’s Build conference held a big surprise: Microsoft announced that they’ve built a UIKit compatibility layer for their various flavours of Windows.

Now I’m mainly a Mac developer and only hear of Windows things from friends and colleagues at the moment (the last time I did Windows work was around Windows XP), but my impression so far was that MS was frantically searching for a new API.

I don’t remember all occurrences, but I remember them announcing Silverlight, and .NET with WPF, and Windows RT that only supported the new APIs, and all sorts of things to then cancel them again.

So my impression as an outsider is that new APIs weren’t trustworthy and MS would always fall back to supporting their old API main-line that they carry around for compatibility reasons anyway.

Announcing UIKit and Android support actually makes a lot of sense in that context:

Although it appears to acknowledge that Windows Phone really didn’t take off, it does solve the catch-22 that MS found themselves in: Lack of apps. In an ideal case, they’ll now get all iOS apps Apple sells, plus the ones Apple rejected for silly reasons, plus those Android apps that iOS users long for.

If this gambit pays off, MS could leap-frog Apple *and* Android.

It also increases trust among developers who are sticking to ancient API: iOS and Android are the only modern APIs that Microsoft could implement that developers would confidently develop against after all these false starts, because even if MS dropped support for them, they’d still have the entire iOS/Android ecosystem to deploy against. So coding against UIKit for Windows Phone is a reasonably safe investment.

Swift

Of course, the elephant in the room here is Apple’s recent move to Swift. Now, given that Apple’s frameworks still all seem to be Objective-C internally (even WatchKit), I don’t think MS have missed the train. They might even pick up some Swift critics that are jumping Apple’s ship by supporting Objective-C.

But Swift damages the long-term beauty of MS’s “just call native Windows API from Objective-C” story. They will have to bridge their API to Swift (like Apple does with some of their C-based API right now), instead of getting people to use more and more classic Windows API in their Cocoa apps until the code won’t run on iOS anymore.

Still, that’s a small aesthetic niggle. MS already have a code-generator back-end that they can plug any parser onto, and Swift doesn’t appear to be a particularly difficult language to parse. In any event, parsers are easier than good code generation. For MS to create a Swift compiler is a solved problem, and I’d be surprised if they weren’t already working on it.

Of course, if MS had known about Swift when they started their UIKit for Windows, would they still have written it in Objective-C? Or would they have just written it in Swift with a bridging header?

So given the situation MS have managed to get themselves into, this sounds like it might be a viable solution to survive and, maybe, even come back from again. Still, it is an acknowledgement of how MS has fallen, that they need to implement a competitor’s API on their platform.

World of Warcraft

SomeRPGGame

World of Warcraft is probably the MMORPG that brought this type of game into the mainstream, and it’s still live and being played today.

So I thought I’d try it out. Luckily, a friend used to be a veritable WoW-fiend doing high-level raids, so I had a pro guiding me through the beginning, suggesting good races to pick etc.

WoW is great, and of course it’s an institution, but oddly, I found I did not enjoy it enough (compared to Star Trek Online, which I’m currently playing). Because that is rather weird, I thought I’d try to list the things I like and dislike about WoW, in the hope that it’ll make me more clear about what kinds of games I would like to make.

Mission duration

The thing that initially attracted me to STO was that it had story missions, which felt almost like episodes of a TV series. At least as far as I played, WoW’s missions are a lot shorter. Where in STO I play what feels like half an hour to finish a mission, from accepting it to getting the rewards, WoW favors shorter missions of a few minutes, meaning every time I get a tall un-moveable window containing a wall of text (“lore”) and a button to accept a mission or complete.

Even in STO (where it is at least moveable) I do not like mission windows. They take me out of the story, even though I enjoy the gratification of successfully levelling up. And it just feels hollow to get a big achievement for going from point A to point B.

While STO’s mission accept and completion dialogs are similar, they occur much less often, and one mission consists of several smaller quests in the WoW style. This gives them the opportunity to design the dialog before those missions as a real conversation, not just a monumental text dump. I guess it’s a matter of personal preference, where I fall on the side of conversations.

Beginner Help

Both WoW and STO have little help popups that introduce you to using the in-game UI. But like a lot in STO (which came later, so I’m really not blaming WoW for that), their implementation feels more like it would feel in a real computer program.

You can click all of them to either advance in the directions it gives you (which means it will pop up e.g. your inventory to show you how to equip a weapon), or close a single-popup instruction.

The WoW ones, on the other hand, have no obvious way to dismiss them (I tried all three mouse buttons), and at least in my case have the habit of covering mission rewards (and since the mission window is also immovable, if the mission description doesn’t scroll, there is no way for me to read the rest).

Also, the help in STO is tiered. You create a new character, it shows you every hint exactly once. In WoW, I repeatedly get reminded that I just received a new item and seem to be pretty much forced to equip it right then and there to get rid of the tutorial popups.

Moreover, after each mission, I get a large banner in the middle of the screen, telling me to press M to see the map. Even if I can see where to turn in the mission perfectly fine in the mini-map. Even if this is my 10th mission.

One mistake STO makes with help I don’t want to repeat is that popups contain static text and sometimes only point at fixed locations. So if I move an ability from the default spot in the tray, I just get help pointing at the tray, not the actual ability. Also, any keyboard shortcuts the docs mention indicate the default (they point that out, though) so do not reflect any changes I may have made to key bindings in the settings.

UI performance

I play on a Mac. STO’s Mac port is done using Cider, which means I essentially run a Windows emulator. Also, their UI feels like it is written like the game itself, i.e. it calls back to the server for confirmation a lot.

While this is correct for actual gameplay and mini-games, it means that on a slow or busy connection (whether on my side or theirs) a lot of the UI loses clicks, even for parts that aren’t timing-sensitive like the confirmation panels when ending a mission or moving between sectors.

WoW on the other hand feels different. Buttons just behave like you’d expect them to, and if you click a button it triggers an action (the exception being if you accidentally right-click instead of left-click a button, in which case it highlights but then never does anything — it should just not highlight in the first place on a right click).

Icon design

The symbols in your tray in STO have a clean, “iconic” look, made up of simple glyphs and (after an update this year) following a system that makes it easy to tell apart the various groups of abilities and match up abilities with their icons.

WoW’s icons are less clean, more fancy, as you’d expect from a fantasy game. I think I’d get used to them if I played it some more, but they seem to be at the slightly less self-explanatory level STO’s were a year ago. WoW would benefit from an icon redesign, I think, but that’s a minor nitpick, but a big thing to keep in mind for one’s own game designs. Structure them like STO’s icons, even if I may choose a fancier style for a fantasy game.

Damage feedback

Especially STO spaceships make it kind of hard to detect when your character takes or deals damage. Since WoW mostly deals in living beings, they can provide much more obvious feedback about damage dealt or received, where your character shrinks back or similar to indicate you’re not doing too well. Such cues on the character models are much better than having to keep a health bar or “hull strength” indicator in peripheral vision.

In STO it often happens to me that my ship suddenly blows up because I didn’t pay attention to that bar and the damage model has not quite triggered yet and an enemy hits me with an especially strong shot. I do not enjoy One-shot-and-you’re-dead enemies in my games.

If I wanted to have an instant killer enemy for story reasons, I’d make sure there is a little cut scene before the fight starts where it demonstrates this weapon on an unsuspecting NPC, and also that the weapon has some sort of “I have you in my sights” indicator that gives me a chance to evade it.

Cool-downs

When I fight in WoW, my character is constantly complaining “cannot do that yet”, “I have no target”, “not enough manna”, “this ability isn’t ready yet”. While I like the use of audio for feedback like this, it doesn’t help my immersion that my character constantly talks to me.

This is exacerbated by some misfeatures of the UI, where e.g. it doesn’t auto-target the next enemy, so usually I press buttons to swing the sword and the first press kills the enemy, but I don’t realize it because the animation takes its sweet time to make the character fall over, so I hit again, and hear “I have no target”.

Also, cool-downs and “manna” (or whatever power is used) are displayed separately in the UI. In STO, they’re one thing. If there is not enough power, the button for an ability stays inactive. In WoW, the button becomes active, but the manna bar is empty, and I get “Not enough rage” or whatever.

Now mind you, I’m aware that battle in STO is more real-time, like in shooters (it’s an action-RPG after all) whereas WoW follows the conventions of strategy games, where you click your enemy and then they’re supposed to be fighting it out while you watch. It’s about who you pit against who and what abilities you decide to use, not as much about each individual shot.

So maybe I just need to cool it down. Let the game play that part.

Range of actions

The way you play STO is fairly keyboard-heavy. You can use the mouse like in WoW, but the tutorial generally tells you which keys to press.

So usually every interaction involves walking up to something until an action menu pops up or an ability becomes available, and then to trigger it.

WoW generally expects you to use the mouse. This leads to a weird dichotomy for me because my character is roughly near the object and I can click it with the mouse (“my hand is able to reach it”) but then my character complains “too far away”. Because I’m not yet in range.

There are indicators, mind you. The mouse cursor is B/W instead of color if you’re too far away, and your character tells you it needs to get closer, but again, it doesn’t help my immersion, so I’d probably go with the STO approach even though it means there are additional popups onscreen which WoW avoids.

The games already show lots of HUDs like mini-maps and ability trays and manna bars, though, so just one more doesn’t weigh as heavily to me as the break in immersion.

Polish

WoW is definitely the more polished game. I’ve had one Mac where it would crash on launch, but whenever I got WoW to run on a Mac, it was solid. STO on the other hand, has crashed a lot for me on the Mac.

Also, WoW’s progressive downloading in the background is great. It shows you in the progress bar how much you need to start playing at all, how much they recommend so you don’t have to wait, and how much to have to hit the network the least while playing. And it seems to take only a few megabytes to start playing. The graphic design of the Battle.net client is also quite nice looking.

STO’s launcher OTOH shows you 9 different progress indicators before you can start playing, and even a fresh download from the server still requires an 8GB patch afterwards. And the progress indicator graphics are very eighties and at least in the Mac port text overflows the progress bar’s boundaries.

They may both be using HTML behind the scenes for all I know, but only STO feels like a web site with CSS bugs.

Also, WoW’s buttons highlight and track properly and responsively, and feels like one application compared to STO’s three. And STO has glitches when switching levels where the level is drawn, and only then the load screen covers it, so you get a glimpse of every scene before you enter it. Not a very smooth transition.

WoW also has great in-game details, like rats and foxes running around for ambience, or little children coming up to you and asking you whether you really did all those things you did in the previous quest.

STO only has static characters standing in groups or on corners repeating the same phrase with your name filled in, like “It’s great to see you, Admiral” or “The Federation is doing its best to support you all here”. The infrastructure seems to be there, but I guess they can’t afford to script and implement that in most levels … ?

Trolls and griefers

I just had WoW spoiled by ending up in a cave where I was supposed to kill a spider queen that spawned about every 10 seconds. A few higher-level mages were camped out there and killing the spider as soon as it spawned, with a single shot from a distance.

The worst I’ve ever had happen to me in STO was one guy who kept moving his avatar in front of me and making it dance, or someone triggering a bomb next to me (which doesn’t have any effect beyond making a “poof” effect because outside designated PvP areas all players are on the same team). The solution? I switched to another instance, which is randomly assigned to each player, and identical to the one I was in before. It also takes along my mission progress. No onerous “moving my character to another realm”.

STO seems to generally be engineered to avoid conflict between players. Between players, there is not even collision detection. Most quests require you to trigger enemies, so you have the first chance to get them because your enemies can’t know when they’ll pop up and get in before you.

Also, most battle zones not only have more enemies than you could be expected to kill in a short timespan you’d need to troll someone, they also reduce the level of all characters in a certain area. So my Vice Admiral (60) fights on Nimbus III as Level 20, like everyone else, making it just as hard for the troll to kill the objective as for me. Chances are I’ll get a success in.

So…?

Both games are great, both games do the basics extremely well, both games have their strengths and weaknesses. And both games let me learn a bit about game design in MMORPGs.

Why the new MacBook is a success

RetinaMacBook12Corner

To those of you following me on Twitter, it hasn’t been a secret that I’ve been waiting for a small, portable Retina MacBook for quite a while. Yesterday, Apple announced one, and it looks to be a good one. Since I’ve heard a lot of nay-sayers, I thought I’d point out some things that people may overlook.

Are you the target audience?

The new device is named “MacBook” and priced in the $1500 price range. Also, the old MacBook Air in the < $1000 price bracket is still available. This makes sense. The MacBook Air moved into the entry-level price bracket a couple years ago. Like with other Mac models, a Retina variant can't be made at that price profitably. So they'll keep the old variant for the price-conscious, as a way to attract new users who will then hopefully later upgrade to a more expensive model, or stay on at the low end. So the people looking for a cheaper (but not the cheapest) Mac are one target of this new machine. Another main feature was that it's slim and ultra-portable. So if you would be fine lugging around a 15 incher, you're definitely not the target audience. If you're looking for a powerful Mac to run scientific simulations or build large programs using Xcode, you already have the 13 inch Retina MacBook Pro. It is only slightly larger and packs the power and extensibility you need. So why the heck would Apple build a machine identical to those existing ones?

The new MacBook is the future replacement of the MacBook Air 11″. If you wouldn’t have bought that machine, why’d you be surprised that this machine at the top end of the price bracket is not for you? It sells like sliced bread, so there obviously are people who want a machine like that.

That ‘single’ port

I’ve seen many people complain about that single USB-C port. But when I look at my and friends’ usage patterns on the MacBook Air 11″, it turns out that most of the time you don’t use a port. Either you’re traveling, on a train or plane with it (if you didn’t, you’d probably be fine with a larger machine), in which case you wouldn’t have anyplace to plug it in anyway.

Or you’re at work, or in your apartment, in which case you’re stationary. So you probably already have an external display that provides power *and* serves as an Ethernet adapter and USB hub, or some other dock, around which your wired ethernet connection or clunky devices that you’d need USB ports for are arranged.

In that situation, only having a single USB-C plug to attach is actually the most convenient solution.

And since USB-C is an industry standard, there’s no doubt that USB keys with C-plugs are only a matter of time. At worst, you may carry along a tiny plug adapter for attaching a colleague’s old USB storage sticks, probably smaller than a 30pin to Lightning adapter. And you won’t even have to pay the Apple Premium(tm), because lots of third-parties will probably be making these, too.

And they did leave in the combined headphone/mic jack, which is probably the only other port I’d use with any regularity, and which might actually be needed while something else is plugged in.

That M-processor

The MacBook Air has never been known for being the high-end machine of the product line. The biggest of the new MacBook’s CPUs Turbo Boosts up to 2.9GHz. That’s faster than the old entry-level ones, but not quite as fast as the old i7 variant. But neither machine is problematic for the entry-level crowd they will eventually be serving. You can write text and e-mails, you can browse the web, you can watch full HD movies. Heck, Photoshop will not be super-fast but probably be fine, and while Xcode may take some time, it will still run and get the job done. That’s not a change from before.

That Webcam

The Webcam is only 480p. That’s not much. Then again, if you’re calling home, you probably know what your kids or parents look like, and you’ll be able to make out whether the facial expression meant that phrase was irony or serious. That’s really all video calls are for. If you’re at a hotel, picture quality will probably be reduced to horrible macroblocks anyway, due to the slow internet. And very likely, you already own an iPhone or iPad, so you can always use their camera.

And if you actually want to take video, you’re likely using an external camera anyway, and not your webcam, which picks up the vibrations from your typing and has a limited angle that requires you adjust your screen.

Non-clicky trackpad

This easily had me worried. I’ve never been able to make touch-to-click work on old trackpads. I always caused clicks at the start of quickly moving the mouse, accidentally trashing or moving files in the process. However, with force-touch, this might work out. If it can detect the difference in pressure, it might have a decent threshold between a strong touch or a soft click. I haven’t actually used one yet, but all the hardware for this to work seems to be present.

The new power supply

I’ve had some issues with my MacBook Air 11″‘s power supply. My cable usually goes sideways off the hotel bed, so the plug being angled backwards means it bends off right after the plug. The rubber sleeve on the cable usually starts fraying and breaking after a while. Since the cable is attached permanently to the power supply, that made for some expensive replacements.

In addition, the MagSafe connector kept unplugging when I didn’t want it to. Oddly, when someone actually stepped on the cable, the sudden force would cause the lightweight MacBook to spin around first, so its back was facing in the direction of the cable. This in turn meant that the L-shaped MagSafe plug now functioned as a hook and would not unplug. In short, MagSafe never worked for me on that machine (It’s fine on my old 15″ MBP, because that weighs enough).

As far as I can tell from Apple’s web site, the new power supply is like an iPhone power bug. There is a separate USB-C cable with plugs on both ends now. The USB cable has a straight, not angled plug. As such, not only would it not get bent when the cable goes off sideways, someone pulling on it would also no longer turn it into a fishing hook. It’s much more likely that it’d unplug under force now than before. And if it doesn’t, it won’t be any worse than before for me.

Now if this power supply and these connectors make their way to the larger MacBooks, the lack of MagSafe may become an issue. But for this device? Not for me.

The Retina Display

If I read Apple’s web site right, the new MacBook has a 2304×1440 screen. At traditional scale factors, that would make it 1152×720@2x or 1536×960@1.5x. That first resolution would be a show-stopper for me. Back when the 11″ MacBook Air came out, most applications did not expect a new Mac to have a screen as small as 768. Lots of windows didn’t fit onscreen, with the “OK” buttons at the bottom ending up offscreen. 48pt less is worse, and will probably cause that problem again.

You can’t run a 12″ screen at 2304×1440 either. The menu bar would be tiny. You’d spend all day bent over the tiny laptop and ruin your back. However, the 1.5x resolution would be fine for me. The screen is a bit larger, so this should end up only slightly smaller than the old 11″ MacBook Air.

Is it ideal to run this device at 1.5x? No. Is it an improvement over the old non-Retina? Yes. More space to work with, and more pixels for text rendering.

I can’t say for sure that these resolutions would be available, though. Apple’s documentation mentions 2304×1440 at 226ppi, and then a number of “Scaled” resolutions which are really weird sizes like 1280×800. I presume these are just the additional resolutions like you’d find them under “Scaled” in the “Displays” System Preference pane, and that we’ll still have the 1x, 1.5x and 2x switches like we have on current Retina Macs.

That Keyboard

In general, I like better keyboards, and as a fast but not very precise typist laud the idea of a more stable key cap. The only issue I have with this one is that the new single-assembly butterfly mechanism seems to be using a thinner piece of material (and apparently plastic) as a hinge/joint of sorts. Usually that means that, after some wear and tear, this thinner piece will break. That would mean this device is engineered to break.

The verdict

In my not so humble opinion, people who are complaining are not real Scotsmen… err … not the target audience for this machine. You can still get one of the others, even non-Retina MacBook Airs on their way out. The features Apple cut or compromised on are the ones that will least affect the typical user. It’s a good machine. I’ll probably buy one once I’ve answered that final, all-important question:

… Space Grey or Gold?

Death to Booleans!

DeathToBooleans

One of the most annoying aspects of most C-descended languages is that function calls become kind of unreadable when they have more than a single boolean parameter. The calls start looking like:

    OpenFile( "/etc/passwd", true, true, false );

and you have no idea what effect each boolean actually has. Sometimes people solve this by naming all parameters in the function name, but of course that doesn’t permit adding more optional parameters to a function later, because you’d have to change the name:

    OpenFilePathEditableSaveSavingAllowNetworkURLs( "/etc/passwd", true, true, false );

A disciplined programmer will solve this by adding an enum and using that instead of the booleans:

    enum FileEditability { kReadOnly, kEditable }
    enum FileSafeSaveability { kSafeSave, kOverwriteInPlace }
    enum FileAllowNetworkURLs { kFileURLsOnly, kAllowNetworkURLs };
    void    OpenFile( const char* path, enum FileEditability fe, enum FileSafeSaveability fs, enum FileAllowNetworkURLs fu );

Or maybe just make all booleans a “flags” bitfield:

    enum
    {
        kEditable = (1 << 0),
        kSafeSave = (1 << 1),
        kAllowNetworkURLs = (1 << 2)
    }
    typedef uint32_t FileOpenFlags;
    void    OpenFile( const char* path, FileOpenFlags inFlags );

But that requires the foresight to never use a single boolean. And of course the actual discipline.

Wouldn't it be nice if C had a special provision for naming booleans? My first thought was allowing to specify enums in-line for parameters:

    void OpenFile( const char* path, enum { kReadOnly, kEditable } inReadOnly );

But to be convenient, this would require some rather too-clever scoping rules. It'd be easy to make the enum available to all callers when they directly call the function, but what about cases where you want to store the value in a variable? Maybe we could do C++-style scope resolution and allow saying OpenFile::kReadOnly ?

Would be a nice way to make it easy to name parameters, but not really readable.

I guess that's why other languages have named parameters instead. Avoids all those issues. So...

The boolean is dead! Long live the boolean! (as long as you have named parameters to label them with)

Using Jekyll for static web site building on a Mac

JekyllWithBeaker

Martin Pilkington occasionally mentioned the Jekyll static web site builder in his tweets, so when I wanted to start a new web site, I thought I’d give it a try, as I’ve been uncomfortable with having to back up WordPress sites in separate steps to get both the database and the image and movie assets.

Installing Jekyll

Make sure you have Xcode installed and its command line tools. Then just open Terminal and type:

sudo gem install jekyll

Creating a new site

To create a site, do

jenkins new example.com

This creates a folder named example.com in the current directory to hold the files for the new site.

Open the folder and in it the _config.yml file. Change the entry title: to what you want to call your new site, and url: to your domain name (in our above example, http://example.com). Feel free to change what few other settings there are, but you don’t need to.

Two neat _config.yml tips:

  1. You can leave entries empty, e.g. the email: or github_username:, and they will just disappear, including their icons.
  2. You can make files and folders that Jekyll would usually skip (like .htaccess) by adding an entry like: include: [.htaccess, .well-known, _foo.xml]. You can also exclude files from copying/processing this way, e.g. exclude: Readme.md.

Testing the site

Jekyll includes its own web server. Simply type

cd example.com
jekyll serve

the site is now available under http://localhost:4000. The server will automatically watch for changes to the folder and re-build the site. If you still need to manually trigger a rebuild (e.g. to deploy your site without launching the server), just use

jekyll build

Adding your own pages

Like WordPress, Jekyll has pages and blog posts. Any file that doesn’t start with an underscore is considered as a page. Be it index.html or about.md. Let’s edit about.md to describe our site, not Jekyll. Open it in a text editor.

The file starts with a section like this:

---
layout: page
title: About
permalink: /about/
---

called the “front matter”, followed by regular Markdown, as you’d expect from a .md file. This section specifies the info that Jekyll needs about the page, and tells Jekyll to substitute placeholders in the file. You can leave this section empty, just its presence tells Jekyll to process the file. So it’s easy to create a new page. You can also make up your own settings here, if you want.

The ones in this example are standard ones Jekyll knows out of the box:

layout: specifies that the file _layouts/page.html should be wrapped around this file, and this file’s contents should be inserted where that file says ||contents~~. This is how Jekyll applies themes and shows navigation on each page.

permalink specifies the address at which the page will end up in the generated web site. So in our example, you’d find this page at http://example.com/about/ instead of at http://example.com/about.html.

title: is actually just a variable used by the _layouts/default.html template. Any variable you define can be used on the page by writing e.g. || page.title ~~. So if you added a line temperature: 40 Centigrade you could put it on the page as || page.temperature ~~.

Other interesting variables are categories, tags and published.

Blogging with Jekyll

Jekyll offers special blogging support. Mainly this just involves saving pages into the _posts folder and prefixing the file names with an ISO date, e.g. 2015-01-30-My First Post.md. But it also has special functions to make it easier to link between posts in a stable fashion, and to generate lists of posts with teaser text etc. The Official Jekyll docs on blogging cover this well.

Importing from WordPress

Jekyll has support for importing from WordPress. First, install the importer:

sudo gem install jekyll-import
sudo gem install sequel
sudo gem install unidecode
sudo gem install htmlentities
sudo gem install mysql2

and then do what Jekyll’s WordPress Importer docs say.

Handling keypresses in Cocoa games

WASDKeys

At first blush, Keyboard event handling for games in Cocoa seems easy: You add -acceptsFirstResponder and -becomeFirstResponder overrides to your custom game map view, then override -moveUp:, -moveDown:, -moveLeft: and -moveRight: to handle the arrow keys.

However, if you play a game like that, you’ll notice one big difference to most other games: It only ever accepts one keypress at a time. So if you’re holding down the up arrow key to have your character run forward, then quickly press the right arrow key to sidestep and obstacle, your character will stop in its tracks, as if you had released the up arrow key.

This makes sense for text entry, where you might accidentally still be holding down one character while another finger presses the next, but for a game this is annoying. You want to be able to chord arbitrary key combinations together.

I found a clever solution for game keyboard handling on the CocoaDev Wiki, but it’s a bit old and incomplete, so I thought I’d provide an updated technique:

The solution is to keep track of which key is down yourself. Override -keyDown and -keyUp to keep track of which keys are being held down. I’m using a C++ unordered_set for that, but an Objective-C NSIndexSet would work just as well:

@interface ICGMapView : NSView
{
	std::unordered_set<unichar>	pressedKeys;
}

@end

and in the implementation:

-(void)	keyDown:(NSEvent *)theEvent
{
	NSString	*	pressedKeyString = theEvent.charactersIgnoringModifiers;
	unichar			pressedKey = (pressedKeyString.length > 0) ? [pressedKeyString characterAtIndex: 0] : 0;
	if( pressedKey )
		pressedKeys.insert( pressedKey );
}


-(void)	keyUp:(NSEvent *)theEvent
{
	NSString	*	pressedKeyString = theEvent.charactersIgnoringModifiers;
	unichar			pressedKey = (pressedKeyString.length > 0) ? [pressedKeyString characterAtIndex: 0] : 0;
	if( pressedKey )
	{
		auto foundKey = pressedKeys.find( pressedKey );
		if( foundKey != pressedKeys.end() )
			pressedKeys.erase(foundKey);
	}
}

Of course, you’ll also want to react to modifier keys, and like most games, you will want to treat them not as modifiers in a shortcut, but as regular keys, so people can press Command to fire, or so. That’s basically the same, just that you override -flagsChanged: and that there are no standard character constants for the modifier keys. So let’s just define our own:

// We need key codes under which to save the modifiers in our "keys pressed"
//	table. We must pick characters that are unlikely to be on any real keyboard.
//	So we pick the Unicode glyphs that correspond to the symbols on these keys.
enum
{
	ICGShiftFunctionKey			= 0x21E7,	// -> NSShiftKeyMask
	ICGAlphaShiftFunctionKey	= 0x21EA,	// -> NSAlphaShiftKeyMask
	ICGAlternateFunctionKey		= 0x2325,	// -> NSAlternateKeyMask
	ICGControlFunctionKey		= 0x2303,	// -> NSControlKeyMask
	ICGCommandFunctionKey		= 0x2318	// -> NSCommandKeyMask
};

-(void)	flagsChanged: (NSEvent *)theEvent
{
	if( theEvent.modifierFlags & NSShiftKeyMask )
	{
		pressedKeys.insert( ICGShiftFunctionKey );
	}
	else
	{
		auto foundKey = pressedKeys.find( ICGShiftFunctionKey );
		if( foundKey != pressedKeys.end() )
			pressedKeys.erase(foundKey);
	}

	if( theEvent.modifierFlags & NSAlphaShiftKeyMask )
	{
		pressedKeys.insert( ICGAlphaShiftFunctionKey );
	}
	else
	{
		auto foundKey = pressedKeys.find( ICGAlphaShiftFunctionKey );
		if( foundKey != pressedKeys.end() )
			pressedKeys.erase(foundKey);
	}

	if( theEvent.modifierFlags & NSControlKeyMask )
	{
		pressedKeys.insert( ICGControlFunctionKey );
	}
	else
	{
		auto foundKey = pressedKeys.find( ICGControlFunctionKey );
		if( foundKey != pressedKeys.end() )
			pressedKeys.erase(foundKey);
	}

	if( theEvent.modifierFlags & NSCommandKeyMask )
	{
		pressedKeys.insert( ICGCommandFunctionKey );
	}
	else
	{
		auto foundKey = pressedKeys.find( ICGCommandFunctionKey );
		if( foundKey != pressedKeys.end() )
			pressedKeys.erase(foundKey);
	}

	if( theEvent.modifierFlags & NSAlternateKeyMask )
	{
		pressedKeys.insert( ICGAlternateFunctionKey );
	}
	else
	{
		auto foundKey = pressedKeys.find( ICGAlternateFunctionKey );
		if( foundKey != pressedKeys.end() )
			pressedKeys.erase(foundKey);
	}
}

An alternative would be to just enlarge the numeric type used to store keys in your unordered_set. Instead of two-byte unichar values, you’d just pick uint32_t, and then define the constants as values that are out of range for an actual unichar, like 0xffff1234. If you’re using NSIndexSet, you’re lucky, it uses NSInteger, which is already larger.

Then add an NSTimer to your class that periodically checks whether there are any keys pressed, and if they are, reacts to them:

-(void) dispatchPressedKeys: (NSTimer*)sender
{
	BOOL	shiftKeyDown = pressedKeys.find(ICGShiftFunctionKey) != pressedKeys.end();
	for( unichar pressedKey : pressedKeys )
	{
		switch( pressedKey )
		{
			case 'w':
				[self moveUp: self fast: shiftKeyDown];
				break;
			...
		}
	}
}

Since your timer is polling at an interval here, and you can’t make that interval too fast because it’s the rate at which key repeats will be sent, it is theoretically possible that you would lose keypresses whose duration is shorter than your timer interval. To avoid that, you could store a struct in an array instead of just the keypress in a set. This struct would remember when the key was originally pressed down, and when the last key event was sent out.

That way, when the user begins holding down a key, you’d immediately trigger processing of this key once, and make note of when that happened. From then on, your -dispatchPressedKeys: method would check whether it’s been long enough since the last time it processed that particular key, and would send key repeats for each key that is due. As a bonus, when a key is released, you could also notify yourself of that.

You could even create “key event” objects of some sort to hand into your engine.

Adding Lua 5.2 to your application

LuaPlanetsInSpace

Note: The code in here is adapted from an actual project, however I’ve not yet had time to verify it doesn’t have typos. Google search results are just overflowing with info on old Lua versions that I wanted to dump this to the web now in the hopes of being at least vaguely helpful.

Lua is a really cool, clean little programming language that is easy to embed in your applications. Not only is it under a permissive license, it’s ANSI C.

However, recent updates have made most of the documentation about it on the web a bit outdated, so I thought I’d drop this quick tutorial on how to add Lua to your application and do some of the typical inter-operation things with it that you’d want to do when hosting scripts in your application.

Building Lua

Building Lua is very easy. After getting the source code (I’m using the unoffical Git repository from LuaDist on Github), you duplicate the file lua/src/luaconf.h.orig under the name lua/src/luaconf.h. Then you point Terminal at Lua’s folder and do

make macosx

(Or if you’re not on a Mac, use the appropriate platform name here, you can see available ones by just calling make without parameters in that folder)

This will churn a short moment, and then you’ll have a liblua.a file. Add that to your Xcode project (or equivalent) so it gets linked in, and make sure the header search paths include the lua/src/ folder. That’s it, now you can use Lua in your application.

If you’re using Xcode, I recommend you just add an aggregate target named “liblua.a” to your project and give it a shell script build phase like the following:

Liblua build phase for Xcode

Liblua build phase for Xcode

cd ${PROJECT_DIR}/lua/src/
if [ ! -f luaconf.h ]; then
    cp luaconf.h.orig luaconf.h
fi
make macosx

By specifying ${PROJECT_DIRECTORY}/lua/src/lua.h as the input file and ${PROJECT_DIRECTORY}/lua/src/liblua.a, Xcode will take care to not unnecessarily rebuild Lua if you make your application depend on this target.

Running a Lua script

To use Lua, you include the following headers:

#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"

(If you’re using C++, be sure to wrap them in extern "C" or you’ll get link errors) Then you can simply compile the following code to initialize a Lua context and run a script from a text file:

lua_State *L = luaL_newstate();	// Create a context.
luaL_openlibs(L);	// Load Lua standard library.

// Load the file:
int s = luaL_loadfile( L, "/path/to/file.lua" );

if( s == 0 )
{
	// Run it, with 0 params, accepting an arbitrary number of return values.
	//	Last 0 is error handler Lua function's stack index, or 0 to ignore.
	s = lua_pcall(L, 0, LUA_MULTRET, 0);
}

// Was an error? Get error message off the stack and print it out:
if( s != 0 )
{
	printf("Error: %s\n", lua_tostring(L, -1) );
	lua_pop(L, 1); // Remove error message from stack.
}
	
lua_close(L);	// Dispose of the script context.

The script file would contain something like:

-- this is a comment
io.write("Hello world, from ",_VERSION,"!\n")

Calling from Lua into C

Now you can run a file full of commands. But how do you have it call back into your application? There’s a special call for that, lua_register, which creates a new function that actually wraps a special C function. You call it like this:

// Create a C-backed Lua function, myavg():
lua_register( L, "myavg", foo );	// Create a global named "myavg" and stash an unnamed function with C function "foo" as its implementation in it.

to register a C function named foo as a Lua function named myavg. The actual function would look like this:

// An example C function that we call from Lua:
static int foo (lua_State *L)
{
	int n = lua_gettop(L);    /* number of arguments */
	lua_Number sum = 0;
	int i;
	for (i = 1; i <= n; i++)
	{
		if (!lua_isnumber(L, i))
		{
			lua_pushstring(L, "incorrect argument");
			lua_error(L);
		}
		sum += lua_tonumber(L, i);
	}
	lua_pushnumber(L, sum/n);        /* first result */
	lua_pushnumber(L, sum);         /* second result */
	return 2;                   /* number of results */
}

This example function loops over all parameters that have been passed (using lua_isnumber to check they’re numbers, and lua_tonumber to actually retrieve them as ints), which may be a variable number, adds and averages them, and then pushes two return values on the stack (the average and the sum), and returns the number of return values it gave.

Functions in Lua and other oddities

You could now call it like:

io.write( "Average is: ", myavg(1,2,3,4,5) )

from Lua. The funny thing here is, in Lua, there are no functions in the traditional sense. It’s a prototype-based programming language, so all functions are closures/blocks/lambdas, and can be treated just like any value, like an integer or a string. To declare a function, lua_register simply creates a global variable named myavg and sticks such a function object in it.

When you declare a function in Lua, it’s also really just a shorthand for an assignment statement. So to run a function declared in a Lua file, like:

function main( magicNumber )
    io.write("Main was called with magicNumber ", magicNumber, "!")
end

you first have to execute it, which will create the global named main and stick a function in it. Only now do you look up the function object from that global and call it, again using lua_pcall like here:

lua_getglobal(L,"main");
if( lua_type(L, -1) == LUA_TNIL )
    return; // Function doesn't exist in script.
lua_pushinteger(L,5);
s = lua_pcall(L, 1, LUA_MULTRET, 0);	// Tell Lua to expect 1 param & run it.

The 2nd parameter to lua_pcall tells it how many parameters to expect.

Creating Lua objects from C

Objects are likewise just tables (i.e. key-value dictionaries) where ivars are just values, and methods are functions stored as values. So, to create a new object with methods implemented in C, you do:

// Create a C-backed Lua object:
lua_newtable( L );	// Create a new object & push it on the stack.
	
// Define mymath.durchschnitt() for averaging numbers:
lua_pushcfunction( L, foo );	// Create an (unnamed) function with C function "foo" as the implementation.
lua_setfield( L, -2, "durchschnitt" );	// Pop the function off the back of the stack and into the object (-2 == penultimate object on stack) using the key "durchschnitt" (i.e. method name).
lua_setglobal( L, "mymath" );	// Pop the object off the stack into a global named "mymath".

To call this, function, you do it analogous to before, just that you first use lua_getglobal( L, "mymath" ) to push the object on the stack, then lua_getfield to actually push the “durchschnitt” function stored under that key in the object.

Since functions are closures/blocks/lambdas, they can also capture variables (“upvalues”). To set those, you use lua_pushcclosure instead of lua_pushcfunction and pass the number of values you pushed on the stack to capture as the last parameter. E.g. if you wanted to pass along a pointer to an object in your program that the session object wraps, instead of stashing it in an ivar, you could capture it like:

// Define session.write() for sending a reply back to the client:
lua_pushlightuserdata( L, sessionPtr );	// Create a value wrapping a pointer to a C++ object (this would be dangerous if we let the script run longer than the object was around).
lua_pushcclosure( L, session_write, 1 );// Create an (unnamed) function with C function "session_write" as the implementation and one associated value (think "captured variable", our userdata on the back of the stack).
lua_setfield( L, -2, "write" );	// Pop the function value off the back of the stack and into the object (-2 == penultimate object on stack) using the key "write" (i.e. method name).
lua_setglobal( L, "session" );	// Pop the object off the stack into a global named "session".

and inside the session_write function, you’d retrieve it again like:

	session*	sessionPtr = (session*) lua_touserdata( L, lua_upvalueindex(1) );

Overriding Lua’s getters and setters with C

And finally, what if you wanted to have properties on this object that, when set, actually call into your C code? You install a metatable on your object, which contains a __newindex (setter) and __index (getter) function:

        // Set up our 'session' table:
        lua_newtable( luaState );   // Create object to hold session.
        lua_newtable( luaState );   // Create metatable of object to hold session.
        lua_pushlightuserdata( luaState, myUserData );
        lua_pushcclosure( luaState, get_variable_c_func, 1 );    // Wrap our C function in Lua.
        lua_setfield( luaState, -2, "__index" ); // Put the Lua-wrapped C function in the metatable as "__index".
        lua_pushlightuserdata( luaState, myUserData );
        lua_pushcclosure( luaState, set_variable_c_func, 1 );    // Wrap our C function in Lua.
        lua_setfield( luaState, -2, "__newindex" ); // Put the Lua-wrapped C function in the metatable as "__newindex".
        lua_setmetatable( luaState, -2 );   // Associate metatable with object holding me.

        lua_setglobal( luaState, "session" );    // Put the object holding session into a Lua global named "session".

Where, like before, myUserData is some pointer to whatever data you need to access to do your work in the getter/setter (like the actual C struct this Lua object stands for) and get_variable_c_func and set_variable_c_func are the C functions that you provide that get called to retrieve, and add/change instance variables of the session object.

Note that get_variable_c_func will receive 2 Lua parameters on the stack: The ‘session’ table itself, and the name of the instance variable you’re supposed to get. You return this value as the only return value. set_variable_c_func gets a third parameter, the value to assign to the variable, but obviously doesn’t return anything.

Dynamically providing your own globals

Sometimes you want to dynamically expose objects in your application to a script. One easy way to do that is to make them global variables. In our examples above, we did so by manually registering a new global with a table. But if you have lots of objects or they might change often, you don’t want to do that.

Luckily, Lua keeps all its globals in an invisible table named “_G”, which you can put on the stack using lua_pushglobaltable(L). Now, you can create a meta-table with an __index fallback function for that as well. The key your callback gets will be the name of the global, which you can use to look up the object and dynamically generate and push a table for this object.

Note: In the code above, we called lua_setglobal() in the end, which pushed our table off the stack and stuffed it in the “_G” table. Since we’re not doing that here, be sure to do a lua_pop( L, 1 ) to remove the globals table from the stack again. Otherwise, your call to lua_pcall() will try to call that table and give the error “attempt to call a table value”.

And now you know all you need to call Lua from C, and have Lua call your C functions back.

I want to make an MMORPG…

A demo session of the eleven chat client

I hear that’s the thing beginning programmers say to game developers. One of those naïve things people want to do who don’t know any better. But while I agree it’s an illusion to think we, as beginners, and a single person, could just write out the next World of Warcraft, I can totally understand why one would want to do it.

The reason why MMORPGs are near-impossible to pull off is the same reason that makes them so interesting: They’re a big honkin’ fun challenge. They combine all the fun tech and its problems. And they’re fun to use and well regarded as well. Think about the challenges:

  • Graphics and animation – often even on low-end machines, often in 3D, with bone meshes, inverse kinematics, several detail levels of models and customizable weapons, avatars etc.
     
  • User interfaces – often completely custom written on top of low-level 3D engines.
     
  • Maths – figuring out how leveling needs to work, how different weapons interact, but also pathfinding, and graph theory for the NPCs’ limited “AI”.
     
  • Social and economic science Managing interaction between players to encourage fun, discourage trolls and griefers, and balance gameplay between beginners and hardcore gamers or at least keep them from interfering with each other’s enjoyment. Often also involving trading systems.
     
  • Networking – Including load-balancing of lots of users, accounting for input lag, streaming level data and video.
     
  • Security – In addition to traditional hackers, you’ve got lots of players and script kiddies who are fans and are just trying to game the system a little for personal benefit.
     
  • Storytelling and content-creation – Non-sequential stories depending on user decisions, and lots of other content overlapping with graphics and animation to keep players coming back, and to bridge the gaps between story missions.
     
  • Databases – Includes storing all user information with good performance under heavy load and with transactional integrity even on sudden disconnects (e.g. so you don’t “pay” for an item and then don’t receive it).

I think the only thing from computing you don’t need to know how to do for an MMORPG is how to build hardware dongles and write their drivers.

And you want to build one?

Well, yes and no. I wouldn’t really want to run an MMORPG. I also already have a job. And I suck at 3D modeling. But a bunch of these problems are intriguing and fun to think about, so I’m tinkering with ideas, writing little test projects that implement this or that part that one would need for such a game. I’ve also been reading a lot of stuff on Stack Exchange’s GameDev sub-section, for example a question on how one calculates the leveling of characters.

So you might just see me blog a little more about game design in the future. Or this may be the first and only post I’ll do about this topic before I lose interest, who knows.

So what have you made so far?

Having played a couple hundred hours of Star Trek Online, I realized that a lot of the program felt like a graphical client talking to an IRC server that had a bot that ran the actual game logic. So the networking layer is what I wanted to start with. I’m not sticking to any IRC specification, but simply started implementing a modular chat server that is kinda similar to IRC, and has chatrooms (which are useful for separating maps and their communications overhead), and of course user accounts with blocking mechanisms.

The advantage of this approach is that, even if I don’t ever make a game that uses this, it may be useful to other people who are looking for some sort of networking layer, be it for chat, or for some other social program. And at the very least it let me practice sockets and is allowing me to learn how to use TLS to encrypt a connection.

Where will it go from there?

Well, the basic idea is to then build the “bot” that actually implements the game. It will live in chat rooms, one for each map (i.e. a city, planet or whatever) and let you connect to one. Once in a chatroom, it will send you all the data you need to get started.

In the case of a graphical game that would be models, level maps etc. as well as pending messages you may have (e.g. “crafting operation completed” or “spell prepared” etc., but also remind you of mission rewards you need to accept or present a mission introduction you haven’t confirmed as read yet). It will also send status about the player, like inventory, cooldowns of abilities you’ve recently used etc. and update you about changes in any of these, and inform you of nearby enemies and allies and what they’re doing (to you?).

You can now send commands to this bot, which include character movements, casting a spell, firing a weapon or whatever.

So, oddly, all of this feels a lot like it can be implemented fairly elegantly and simply as sort of an IRC/e-mail hybrid with read receipts. And this can all be done without needing to have a client, nor any graphics. Heck, you could test this by writing an ASCII client that looks like NetHack.

The game map

The game is streamed, so it might not be the best idea to download the entire map at once. Especially if you want to be able to maybe have large or endless maps, or maps that can be re-used for different purposes. You’d want to be able to only load those parts of maps that the user visits for this mission.

So the obvious approach so far seems to be to just split the map up into tiles that have relative locations to each other and then load the tiles surrounding your player’s location, and when the player moves load additional ones so you never run out. This can be a 2D tiled map to start with, but can easily be expanded into cubes that can also be stacked vertically.

To simplify, I’ll probably have only a 2D coordinate inside each tile. The vertical coordinate for a player or NPC inside its particular tile-cube will then simply be decided by the ground level underneath it. Since we can connect the tiles arbitrarily, stairs would still be possible to make. Just create a tile with the stair model at its end:

StairsOnTileMapExample

The player will seem to walk up the stairs because the ground level rises. If we now connect the left edge of the tile to the tile one level up, the user will easily walk up one level. The only downside of this approach is that a character won’t be able to hide under the stairs.

Another advantage of using such tiles is that they can be used for collision testing. You can just block an entire tile from being stood on.

That wasn’t too hard … ?

Well, this is still missing any item management, interaction, mission objective enforcement, combat or pathfinding mechanisms, so it’s far from a game, but yeah, it’s probably what I will try to implement after the chat server is finished. Or maybe I’ll just — oh look a butterfly.