Addendum to Things I learned at CodeRetreat

The most memorable moment for me was in the afternoon, when I spoiled a rant that Mark was about to launch into about a perceived problem he had with TDD “forcing” the programmer to code improperly by requiring them to expose inner members of classes that should properly be kept private.

Instantly, I blurted out, “So write the test method inside your class!” It was kindof a “from the mouth of babes” moment. I barely even thought before the words came out of my mouth. I wasn’t even sure if that was the right answer or not, but I guess it must have been, because the look on Mark’s face was priceless.

There were so many messages in that look: 1) that I was right with my guess; 2) that Mark had been stuck on this mental error for some time; 3) that it might’ve humbled him a little bit that he hadn’t seen it before.

I don’t mean to embarrass him by recounting this — if I thought this would, I’d never be using his real name. It wasn’t that I’d really shown him up — he’s got way more experience than I do, plenty of success under his belt, and he’s someone I like personally as well as look up to. But that was the first moment I felt like I was capable of making a tangible (if relatively tiny) contribution, that it wasn’t just a one-way knowledge transfer from the more experienced programmers at the event to me.

What made it a moment I’ll never forget was that I saw that I wasn’t the only person who gets mentally stuck in my own problems when it comes to programming. If a guy like Mark can still make a mistake like that once in a while, it makes me feel a lot better about doing it too, now and then.

But the bigger lesson is, it totally reinforced the value that we all get from being in the same room, talking to each other, making mistakes in front of each other, and learning from each other what lessons we might. With enough eyes, all bugs become shallow.

Things I learned at CodeRetreat

I went to a local CodeRetreat event hosted at Lean Dog, an agile development studio in downtown Cleveland. I had a great time, and learned a few things. There were a great many more things there to learn than I was able to learn, but that just means I’ll have an equally great time at the next one.

We broke the day up into 5 sessions, working in pairs on a test-driven development exercise. At the end of each exercise we deleted what we coded and paired with someone else and repeated the exercise. It was interesting to see both how different pairs would approach the problem, and how I approached the problem differently with each successive pairing. One of the interesting things I got out of this was how my own thought process and approach to solving the problem improved each time. Even though just 45 minutes had passed, each successive attempt was markedly better than the last. I’m intrigued by this and will be less reluctant to throw out code and start over in the future. I also gained greater appreciation for how important it is to pick good names for your variables, objects, properties, and methods. Good names really make it easier to think clearly about both the problem and your code.

I’ve heard of, and seen examples of, test driven development before, but never done it myself. I got an introduction to NUnit, which I’ll definitely be making greater use of in the future, courtesy of Mark W. Schumann of criticalresults.com. I got to pair with Jeff “cheezy” Morgan, who demonstrated some very keen insights on the essence of TDD, and gave me a little exposure to the Ruby language.

I’m really happy I went, and can’t wait to find more events like this to take part in. Lots of thanks to Corey Haines and everyone at Lean Dog for putting the event together.

A few things you should know about SEO

I have a brother. He started a business earlier this year, and recently asked me about Search Engine Optimization (SEO) for his web site.

I went to a two-day class on the topic earlier this year, which means I’m by no means an expert on the topic, but I’m a pretty good study and I’ve been using and following the world wide web since very nearly the beginning. I figured I should answer his question, and while I’m at it I figure it’ll make a decent blog post.

So, here’s a few things you should know about SEO:

SEO is not a goal; it is a means to an end.

Everyone wants to be number one. But being the top ranked search engine result, or even on the first page, isn’t really the whole point of SEO. Getting that good position on a search results list is something we do for something. We do it in order to drive traffic to our site.

Depending on the site in question, simply driving traffic to it may not be the goal either. What do you want that traffic to do once it arrives at your site? That depends on the purpose of your site. Being found is only the first step. What will you do once they’ve found you?

There’s a zillion reasons people put web sites up, but most of them boil down to making money at some point. How do you do that with your site? Is it through advertising? Subscriptions? E-commerce? Establishing relationships with customers? Gathering user data and selling it?

However you do it, most likely the more traffic your site gets, the more revenue you’ll take in. Ranking highly for popular search terms is a good and important means of driving traffic to your site, but it’s not the only thing you can do to achieve that.

Whatever you do, don’t lose sight of why you want the traffic in the first place.

SEO is but one means of driving traffic to your site

Consider — and make use of — all methods that you can:

  1. internet advertising
  2. traditional media advertising (print, radio, tv, billboards)
  3. direct marketing (mailers, pamphlets, brochures, flyers, business cards)
  4. word of mouth
  5. other sites linking to you
  6. linking to yourself from elsewhere

Optimization is relative to the search term

People talk about “optimizing my site for search engines” and there are indeed a few technical things you can do with your site that will make it friendlier to search engines in general — and I’ll be getting to those.

But when you talk about SEO, you really are talking about optimizing for a specific term (or list of terms), not generically “optimizing your site.”

People searching for your site specifically are likely to find it very easily, even if they don’t know your domain name. Search any website for “csanyk.com”, for example, and you’re pretty much guaranteed that this website will be high on the list. Search for my name, and you’ll also find this site pretty high up on the list of results. Search for “IT consulting” or “Web Design” or something generic, and well, I’m sure I don’t rank so well. Another example: Last year, I created a class on Cascading Stylesheets called “Streetwise CSS”; if you search for that specific term, “streetwise css”, I’m highly visible. But if you’re just searching for CSS, I’m not as visible in the crowd of good resources on CSS that you’ll find when you google for the term “css”.

It’s easy to be found if you’re unique

The reason for that is simple: unique terms on the web don’t have to compete with a million other web pages because they’re unique. If there are 10 results on the first page, and you’re the only person who happens to be using that particular term in the entire internet, well guess what? You win by default. No contest.

Optimizing for a unique term is easy. It’s also a great idea. If you have one specific term, such as your name, that you can get out there through branding and marketing, people will start searching for that term and they’ll find you easily. But, the catch with unique terms for SEO is that since they’re unique, that means no one else is using them, and if no one else is using them, that’s probably because no one else knows them.

So one of the tricks of SEO is having a unique name or other term that could be used by people to search, but isn’t being used yet. Invent a good name that no one knows yet, make sure that you are on the top result for it on all the search engines, and then go about making it known. Youtube. Flickr. Pixlr.

You need to be where they’re looking

Having a unique, easy to find search term will rank you high on a search engine’s results for that specific term, but if no one’s searching for that term, it’s not going to boost your traffic. Cornering the search results market on a specific, unique term is not all there is to SEO. Far from it. You also need to try to get a piece of the action from very common search terms. SEO for a unique term is easy and valuable because it enables you to stand out from the crowd.

Ranking high in search engine results for very common search terms is much harder, but it’s even more valuable because it puts you in a prominent position in front of the crowd of people searching for that term, and the easiest way to draw a crowd to your site is to position it in the middle of a crowd to start with. It’s hard because there’s not just a crowd of searchers — there’s a crowd of sites looking to be found. And there’s only perhaps 10 results on the first page of most search engines, which they’re all competing for. Still, it’s worth competing for those high-ranking results for common terms, because so many people are searching for them.

To put it another way, looking for you is very different from searching for what you do, what you are, or what you want to be known for.

Learn to think like someone who’s searching for whatever it is you want to be found for.

You have to do some marketing research, use common sense, psychology, and come up with lists of terms that people who need your site are likely to be searching for. Figure out those words, and optimize for them, and your site will rank highly for people who need you. Set up Google Analytics on your site and you’ll be able to see the search terms people used to find your site. Look at that list, and start filling in blanks. Figure out synonyms, regional terms, alternate spellings for what you want to be known for. Let your list seed a brainstorm so you can come up with other terms that people might be searching on, but not finding you. Then optimize your site so that the next time someone searches for that term, they do.

Learn to think like a Search Engine Rank Algorithm (and a Web Crawler, too)

This is where your technical specialists come in. Whoever’s designing, building, and maintaining your web site should be taking care of this for you. But you need to know at least something about this, so you can talk to your technical people.

Understanding how a web crawler works isn’t difficult. A web crawler is a program that goes out on the web and downloads pages and follows links. That’s how search engines obtain the content that they index and rank. That’s about all you need to know. Knowing this, you now understand the importance of making the information on your website accessible to the web crawler.

There are ways of building web sites that make it easier or more difficult for web crawlers to find everything. Valid, standards compliant, well-structured HTML that does not abuse or misuse tags is what you want.

No one quite knows for sure how search engines rank sites for specific search terms — it’s a tightly guarded secret, and it’s constantly being changed and tweaked as the internet evolves and as SEO experts learn how to game the system. We can guess, and we have some pretty good knowledge about what matters to ranking algorithms.

Here’s where words “count” most to a ranking algorithm:

  1. the site domain name
  2. the title element
  3. heading elements

This does not mean you should load these areas with words you hope people will search on! Search engines are wise to this and will penalize you for it. The ranking algorithm has a built-in diminishing return for putting too many “hot words” on your page. Choose a domain name wisely, and go for uniqueness (since every common word is already in use or very expensive) and branding. Use the title and heading elements in your html to make good, effective titles and headings. Make them good and effective titles and headings for humans first, but give thought to the machines that will visit your site, analyze its contents, and then rank them for the search terms that those humans will be using to find you.

Avoid “hiding” your content where search engines won’t be able to find it:

  1. behind a login
  2. inside of flash objects that aren’t properly accessible
  3. in images without proper descriptive text

Ranking algorithms also care about how popular your site is and how important your site is. They also care about how popular and important the sites are that link to you. Just how exactly this is determined is difficult to know, but generally speaking, if other, high quality, popular, important web sites link to you, that will help boost you in search results. The more the better. But this is also very hard to accomplish. It’s probable that being popular with social networking sites will help boost your search ranking, but also drive a lot of traffic to your site through the users of those social networks outright. So make it easy for people visiting your site to Like you on facebook, to Tweet about something they found on your site, or to find your personal profile on LinkedIn, or whatever. There are social bookmarking plug-ins for most popular web content management and blogging systems (WordPress, Drupal, Blogger, etc.) that can do this for you. Giving your visitors reasons to Like and link to you is up to you.

Enough of these will give you some boost in your ranking. But links from social networking sites are also “cheap” and easy to game the system with, so it may be that the ranking algorithm takes this into account, or will soon. The maintainers of these algorithms are constantly changing the rules to keep ahead of SEO opportunists who are looking for ways to game the system.

Build a Good Site and SEO almost takes care of itself

Really, if you’re doing things right, you almost don’t even need to think about SEO. A good site is one that provides value to its visitors and gives them reasons to come back. This should be fairly obvious to anyone. You need content that is fresh, constantly updated. You need information that is highly valuable or entertaining. You need engaging things for people to do.

Have a strategy. Why does your site exist? What is its purpose? How well is it achieving its goals? Measure and monitor everything you can about the site and analyze it.

Not all web sites need to be YouTube or Facebook. You don’t have to be giant or mega-popular or have brilliant, cutting edge technology or an idea no one has ever thought of before to be useful or popular with your market.

If all your site needs to be is a brochure and a means for customers to find you, then provide useful information for customers and prospective customers. Give customers accounts that they can use to log in and conduct business with you — placing orders, paying bills, asking questions, providing feedback to you, Liking you.

If people visit your site frequently, they will link to it, tell friends about it, and this will build your traffic and search engines will rank your site higher as a result.

Don’t attract a crowd only to have them find an incomplete or crappy web site!

Design crossroads

So in Boobie Teeth 0.15, I created a surface for my ocean. The way I designed it, if you breach the surface of the water, gravity takes hold of you and you fall back into the ocean. Beneath the surface, no gravity.

I didn’t realize it until I played for a while, but if you breach the surface and wiggle the controls, the input seems to give you extra momentum, which can keep you above the water indefinitely. This wasn’t what I desired, but I wondered whether I should do anything about it. Should I consider it a glitch? Should I leave it in, and let the player discover it? Gamers like to discover things like this, and it’s kindof fun, if useless, to fly about over the waves. But if I leave it in, I should give it some purpose.

I have to think about it for 0.16. Maybe something will come to me. Maybe if you fly about enough, you can get someplace secret.

I don’t like when I design something and it doesn’t work the way I conceived it in the beginning, but sometimes I like the surprise. Even when I do like the surprise, I like to figure out what went wrong and figure out how to make it work the way I originally intended. Maybe I’ll keep it in mind for later.

So I figured out a way to fix the problem, it was easy enough: just set the controls to be disabled when you’re above the water. This causes your above-surface trajectory to become purely ballistic, but at the expense of not being able to control your direction at all. Conceivably this could cause you to leap out of the water, only to be doomed by your trajectory to land right on a big fish that will eat you when you plunge back into the water.

That seems so much less fun than being able to fly out of the water for as long as you care to wiggle the stick. On the other hand, I don’t want there to be a cheap, easy way of avoiding danger indefinitely.

There may be another way. I might just need to find a way of making the simulated gravity increase each step of the game engine until it can’t be resisted. Then you could still wiggle, and might be able to gain a little bit of extra effort air while out of the water, and affect where you will splash down somewhat, likely enough to evade big fish near the surface. I’ll have to play with it and see. Sometimes this experimentation ends up being fruitless, other times I can figure out something useful and understand the tool or the model better than I did. Usually the experimentation is time consuming. But generally, it’s worthwhile.

Any time I run into a design crossroads like this, I think the solution is easy: it’s like Yogi Berra said: “When you hit a fork in the road, take it.” Keep all interesting variants, and make them configurable options. Play through the different options and keep them for as long as they make for interesting play. Some options may make it into the final game as official options, some may be used as hidden easter eggs, others may end up disabled. But keeping the options around as long as possible makes for a more agile course through the development process.

Boobie Teeth: preview video

I just captured a video of Boobie Teeth 0.15, the latest build. It’s up on YouTube.

GameMaker community forum gripe

Ok, I realize that GameMaker isn’t a hard core developer environment. It does serve a purpose though: to provide a more accessible means for aspiring game designers who are not primarily programmers to be able to give life to their ideas. This is a truly noble purpose, in my view and I will never say anything bad about GameMaker’s technical limitations as long as they’re limitations which must exist in order to achieve that goal.

That said, I am really starting to get frustrated with the GameMaker community. Not its members, mind you — the handful of interactions that I’ve had with GamMaker devs have been helpful and positive. But what is really driving me nuts in the community forums is the way people will post links to filehosting sites, and the link is dead because it’s a few months later. This is totally counterproductive to the goal of making a game dev environment that’s welcoming and forgiving to newbie programmers and non-techie types.

The forum thread is there, the tantalizing discussion about how awesome a solution is to just the exact problem I needed to solve is there, but the .gmk or .gex file that would make my day is gone. And not enough discussion around the gaping hole to figure out what the solution was that was demonstrated in the downloadable file.

But it’s not just an everyday occurrence. It’s damn near mandatory. And super frustrating.

.gmk files *usually* take up very little space, and if you don’t need all the resources embedded to create a full-fledged game, you can make *extremely* lean .gmk files that can provide a reference implementation of your nifty solution…. AND, we live in an age where 2TB hard drives cost under $100.

So, WTF? The GameMaker community would be so much better serving its users if it provided permanent hosting space so that discussion threads could remain relevant.

I really don’t understand it, I mean if you go to yoyogames they have graphic and sound resource packs that you can download. They’re of poor quality, and searching for anything in them is atrocious, but they at least have links that still point to extant resources. They even host all the games that people submit to the site.

Clearly they have the technology, why are they not using it in this way?

Fixed that bug

Haha, I figured out what was causing that bug I ran into the other day.

While reading the GameMaker documentation, I read that the order in which objects are drawn is determined by their Depth, and inferred that it is not just the *drawing* order but the construction order when a new room is instantiated. (In GameMaker, Depth is a property that all Objects have, which helps determined which Object is drawn “on top” when their sprites overlap.)

I happened to have my Fish objects at a higher depth than the Player, because if the Player was overlapping the Fish, I wanted the Player to be “on top” so that the Player would always be visible. As an unintended consequence, the Fish objects got drawn and created first, and since Fish.size depends on the value of Player.size, and so were throwing exceptions when the Player did not yet exist.

For some reason this bug was always latent in my game project, but it only manifested after I added a Background to the Room, which is a bit odd. I am guessing that a Background has an extremely high depth so that it appears “behind” everything else in the room, but why it seems to trigger the creation order bug is mysterious to me.

What’s more, I am also confused as to why one of the things I tried to prevent the error did not work. In the Fish.Create() event, I added a check to make sure that the Player object exists before assigning a value to Fish.size that is based on Player.size. If !Player.exists, Fish.size is set to a safe value that is not based on Player.size. Yet, for some reason, the check was successfully able to determine that Player existed for purposes of Player.exists() check, but yet was not able to get the value of Player.size in order to calculate a randomized value for Fish.size. Apparently, the Player object exists at this point but its size attribute does not, or perhaps contains an undefined value.

Figuring this out was rather tricky and it never would have occurred to me had I not been thinking about this bug when I happened to be reading about how the Depth property determines drawing order. Hopefully this writeup will help some other GameMaker developer avoid making a similar mistake.

BunnyBots

I was over at my parents house for Christmas. When I was a kid, my mom kept a bunch of my old school assignments and things up in the attic. I had hoped that I’d be able to go up there and find some of the old game ideas that I had drawn when I was in first and second grade, but unfortunately it seems within the last ten years she went and got rid of a lot of that stuff, and turned the rest of it into some scrapbooks. Unfortunately, it appears that most of my old ideas were lost, other than to my memory.

There was just one thing that I did find among all of that stuff, which might have been a video game concept. The strange thing is, this one I have no memory of making. The drawing is of BunnyBots, which looks a bit like Lemmings, only with bunny robots. That field war machines and artillery pieces, apparently. They fire carrot missiles at each other and drop easter egg bombs and have tunneling equipment for digging rabbit holes. Gameplay evidently resembled a 2-player PvP 2D horizontal scrolling RTS.

Mind you, this was probably drawn in 1982-3, long before Lemmings or real-time strategy existed.

I dunno when or if I’ll ever turn this concept into a game, but here’s a scan I made of the drawing:

BunnyBots

Original drawing for BunnyBots videogame concept. Click Image to enlarge.

?! >:/

Something very weird going on in my GameMaker project…

I have two Object classes: Player and Enemy.

Player
{ Create() {size = 2}
}

Enemy
{ Create() {size = random_range(0.5, Player.size*3)}
}

This code was working fine up until today. Technically, I should be checking to see if Player exists before I try to use Player.size, but I set things up so that Player always exists and was created before any Enemy instances, so it never threw an exception. I understood the risks and tested it and it never had a problem.

Today I created a background image for the room where the game takes place, and added it to the room. All of a sudden now, the Enemy.Create() event is throwing an exception at Player.size because it is an unknown variable.

I scratch my head a bit and try to figure out why…

Was there actually a fortuitous timing condition prior to adding the background that caused the Player instance to be created before the Enemy instances when the room was being constructed? I try removing the background, but the game still throws the exception. I try creating a new room, adding the background to it, then the player, then the enemies, in that order, and it still throws the exception.

OK, let’s be more careful, and check to see if Player exists when in Enemy.Create(), then.

Enemy.Create()
{
If instance_count(Player)>0
{
size = random_range(0.5,(Player.size*3))
}
}

Game STILL throws an exception trying to access a non existent Player.size variable.

OK, did my game project somehow get corrupted? I roll back and test, things are working, then re-implement the background, and the bug is back again.

Does a room with a background image somehow conflict with Player.size? I run the built in variable name checker, no conflicts.

Hmm, what if there’s a name conflict anyway? I try renaming the size variable to foo. Still throws the exception. I try deleting the variable and adding a new variable that performs the same function. No better.

I run the game, Ignore all the thrown exceptions, and then once all the Enemy instances are created the game works. Clear level, next level is fine, no errors.

Alright, last thing: I pull size out of the Player object and make it global. Surely if Enemy isn’t capable of peering in to Player’s public variables (GameMaker doesn’t seem to have a distinction between public and private object properties, at any rate — everything is public for sake of simplicity for newbie programmers) but what the hey, let’s try it. Add the global.Player_size variable, attempt to access it in Enemy.Create(), still throws the exception.

To quote Moss from The IT Crowd, “What the ever-flipping flip?”

Player.size most certainly exists, why can Enemy no longer access it?

Update: To troubleshoot further, I created a new gamemaker project and made it as simple as possible. I created two sprites, two objects, a room, and a background. With the objects, I assigned a variable in the create() event, and tied the value of object0’s variable to the value of object1. Then added both to a room, then ran the game. No error. Then added the background to the room. Again, no error. So, it doesn’t look like this is a bug in GameMaker, then. Something must be messed up with my game project, and it’s up to me to sort through and figure out what it is, then.

Boobie Teeth

I’ve made enough progress with my first game project that I’m releasing a build to the public.

Boobie Teeth is a game I designed as a six-year-old in 1980-1981. The title derives from the term “Booby Trap”. The game is about a voracious fish with jaws like a steel bear trap. Swim around and eat all the fish that are smaller than you. The more fish you eat, the more you grow. The other fish will eat smaller fish too and will grow as they eat also.

This is a very early non-feature-complete alpha build that demonstrates the core play mechanics. Built with GameMaker Pro 8.

Download it on the Releases page.