Boobie Teeth 0.17, CBNA SmartLight, and Google Translation

I’ve spent the last few days getting back into the Boobie Teeth project, trying to figure out how to do a couple things that have had me stuck for longer than I’d care to admit. I’m far from giving up, but I have come to the conclusion that hacking away at the problem isn’t going to be as fruitful as reading up on the problem.

At any rate, here’s a video of what I managed to pack in to today’s release, 0.17:

The major accomplishment for this release was the addition of a transparent gradient in the foreground, which enhances the background gradient that gives the illusion of diminishing sunlight at depth. For now this is just a cosmetic feature, although I already have ideas for tying it into the gameplay.

The other thing I worked with in this release, but dropped for now, is to implement some basic AI. I want the fish to get hungry and start chasing down prey. This is a lot harder than I thought it would be, owing to limitations of GameMaker’s instance handling. My usual approach of coding a little bit and seeing what I get, then coding a bit more once I’m sure what I already have done is working hasn’t gotten me very far. I’ll be researching and studying until I figure out an approach that works.

While researching, I came across a beautiful video of some lighting effects done in GameMaker which blow my simple foreground gradient away completely:

I noticed of course that the video appeared to come from French-speaking authors, but that didn’t dissuade me from tracking down the package that enables these effects and downloading it.

Let me just take a moment to say that I am absolutely amazed by the quality of google’s translation service from French to English. Seriously, click this link and you’d hardly even know that you’re on a French site. This impresses me even more than the lighting effects. If you happen to spot a mistake in translation you can hover over text and see the original, and provide feedback to google directly through the site that they’re translating for you. The translation is extremely fast, almost real-time, too.

It’s going to take me some time to work my way through the examples and tutorials and translating the documentation, but if I can get this SmartLight to work with my game project, it’s going to be well worth it, and make the game look way better than I had originally planned. I really want to get some AI going in my game though, so it’ll probably be a while before I get into re-doing the lighting effects.

Still more reflections from CodeRetreat

I’ve had some decent response to the posts about CodeRetreat. I had some more thoughts come to me in the days following, mostly on pair programming, but no time to write it until now. Here’s a brain dump:

Assert(Two_Heads>1);

This was my first opportunity to try it out, and I instantly liked pair programming. Much of my frustration in trying to learn how to program has come from trying to learn in isolation, getting stuck, and having no one to go to for help. Pairing means you have someone right there who you can talk to, and who can also catch mistakes that you might not have caught until much later.

Be Likeable

I think pairing is a great idea, but with the caveat that it requires you to like your partner. Establishing rapport is critical. I would say that if you are trying to program with someone and have yet to click on a personal level, it might be a good idea to stop trying to program and start trying to connect. Find some way to do this. Play a game that fosters working together with a common goal, like Jenga. If you can’t connect, then it might well be better to not try to pair up, or even not try to program together at all. Divorce is greater than the sum of its parting.

There’s only so much you can do about your partner, but you can do a lot to be likeable. Don’t focus immediately on the problem, but on the partner first. Smile. Be cheerful and enthusiastic. Remember names. Listen. Avoid negativity. Try out your partner’s ideas. When you think something, explain why you think it. When you want to try something, explain why you want to do it and what you hope to accomplish. Then don’t spend a lot more time talking about it — do it. What works becomes a lot more apparent at runtime than any other time, and the quicker you get there the better.

Assert(IsEqual(Life.Spice, Variety));

That’s not to say that you should never pair up with someone who has a very different style from yours. Very often that is precisely the type of person who you should be looking to pair with, because their differences will be the things that you learn from. Still, someone who you can communicate with easily is a must. You’re not going to enjoy learning from seeing a different style if the person demonstrating it is incapable of explaining it in a way that you can understand. Programming style is not the same thing as personality.

If you don’t get along well, or have very different styles, there’s a risk of ego clashes. Frankly, there’s always going to be a risk of ego clashes. Fortunately, this did not come up at CodeRetreat — the people who attended were there because they wanted to be there, which I think makes a huge difference. If your partner isn’t at least pair-curious, if not outright interested, they’re apt not to be a very good partner.

Swing your partner

Much like… uh… square dancing, pairing is even better if you can do it with more people. Try to find more people to pair with. Put on a snazzy shirt, go to bars, wear a lot of jewelry, buy someone a drink, and ask them if they code. See where that leads.

Good pairings are unequal

Intuition suggests the best pairing combinations are unequal. The value two great programmers contribute to a pair is not as great as the value created by pairing a great programmer with an average programmer. The great-great pair may be more productive, but the great-average pair will produce another great programmer in time.

Pairing isn’t just about mentoring and learning, it’s also about collaboration, error catching, and creativity. But mentoring and learning is a hugely valuable part of it — in most cases, probably more valuable than the resulting product.

Dance like no one’s watching, Code like your repository is /dev/null

Being willing to give things a try is a huge factor to pair success. I think what made CodeRetreat so easygoing was that it was deliberately structured to be coding without consequences. We threw out what we’d written at the end of each session, so there was no goal of getting it done, no stake in one person’s approach “winning”.

In the real world, there are consequences. But if you can, try to structure the project workflow in such a way that you can code as though there were no consequences. Be willing to take risks and experiment. Don’t just stick with what you know; grow.

If the established code base is getting in the way of this, don’t be afraid to cut it. From working on numerous development projects over the past five years, I’ve learned that the actual coding takes hardly any time at all, relative to the rest of the project. Requirements gathering, design, and testing all take considerably more time in my shop. Therefore, starting over rewriting code should not be intimidating.

In fact, going back over 20 years, to the bad old days when operating systems didn’t have protected memory and applications didn’t have automatic data recovery, in every instance I can think of when I was writing something and lost it, whether it was prose or code, the re-write was always faster and the results better. So don’t be afraid to take a clean-slate approach at times.

Start over

If CodeRetreat had taught me only one thing, it would have been that it’s not just OK to start over sometimes, sometimes it’s quite helpful. Too often, though, we attach value to code that has already been written and are reluctant to throw it out. Even if it was written as a short term stopgap, if it basically works no one wants to let you throw it out. “Reusable” code is something of a mantra in a lot of shops, as well it should — rewriting the same thing over and over again sucks. But if it wasn’t the right code to begin with, reusing code is about as appealing as reusing toilet paper. Before you try to re-use code, be sure that it is in fact re-usable.

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.