Category: games

2D Targeting for AI in Game Maker 8

After several weeks of effort, I have finally nailed an effective set of 2D targeting scripts for AI in Game Maker 8.

The story for this is worth telling sometime, but for now I’ll just be posting a video demo:

Source .gmk is available on Releases.

I’ll be refactoring this into a Game Maker Extension (.gex) soon as well, which will also be available along with full source.

4 quick GML coding tips

When writing scripts in Game Maker Language projects, I have come to realize a couple things that I want to share for anyone else who might be working on GML projects:

GML parsing is a bit loose. This makes the language fault tolerant, which is nice for newbie programmers who don’t need to get beaten up for not following strict syntax. But by enabling you to get away with imprecise syntax, it lets you get in to trouble that isn’t easy to detect.

Strict syntax is your friend, if you have it as an option in the language you’re using, I recommend following it as soon as you’re comfortable. Strive to get comfortable as quickly as possible. Unfortunately, GML does not have a strict mode…so I have the following tips to offer:

  1. Scripts (sometimes referred to as “programs” in the official Game Maker documentation) are supposed to begin and end with curly braces. The interpreter is forgiving if you don’t do this. But you should always do it.
  2. GML terminates statements with a semi-colon. The semi-colon is semi-optional, but I recommend using them wherever you intend a line of code to end, so that the interpreter doesn’t have to do extra work guessing that for you. Doing so will make it look like you know Pascal, C, or Java more than you know VB, which is enough reason to do it;) (Usually a statement is more or less the same thing as a line of code in your script file, but some structures may incorporate blocks of code, such as loops or branches.)
  3. Strings in GML can include line break characters (there’s no escaping with \n or using a character code like CRLF, like there is in most languages), so if you want to have a string with a line break in it, you simply hit the enter key and put a literal line break in your string. The interpreter handles this OK since the string is bounded by double or single quotes, but it’s still a weird thing about the language that they don’t really explain adequately in the documentation. If you’re not using semi-colons where you intend to end a line, it can get confusing to look at a multi-line string declaration that incorporates the line break as part of the string.
  4. It’s easy to not scope your variables appropriately without realizing it. GML allows global vars, and has two kinds of locality: locality with respect to an instance of an object, and locality with respect to a script. You shouldn’t use globals unless you really need to; according to the language doc they are slower to access than local variables. I haven’t noticed any difference that I can measure, but I’m sure that it is something that adds up, and at any rate proper scoping is a good habit to get into.When I refactored my project to pull drag-n-drop code out and replace it with scripts that were more re-usable, this caused some of my instance variables to turn into script variables. I had to go back and turn them into instance variables once I discovered that this had happened, and caused some issues with the way the code was executed by the interpreter.If you’re using variables in a script that were not declared in the object somewhere (normally the best place for this is in the object’s create() event), and you are declaring the variable in the script, but you want to make it an instance-local variable, you can do so. The code to do this is:

    obj_MyObject.MyLocalInstanceVar

    That dot between obj_MyObject and MyLocalInstanceVar is actually an operator. Knowing this is nifty, but I am not prepared to expound on why just yet.

Keep reading the language specification doc! Every time I go back to it and read, I pick up something I didn’t know, or refine something I thought I knew. One of the really nice things about GML is that it’s a small enough language that you can pick it up and do things with the basic features right away, without needing or being overwhelmed by all the other stuff that you’ll discover as you continue to progress as a developer. And there are enough built-in features in GML that you don’t have to spend a lot of time figuring out how to build sophisticated stuff out of primitives all by yourself.

The more I work in GML, the more respect and appreciation I gain for it. It is not the purest language, nor is it the most powerful, nor is the development environment as rich and sophisticated as a “serious” IDE like Visual Studio or Eclipse, but it is extremely accessible for a non-programmer to pick up and start working with and being effective quickly.

Yummy GameMaker Goodness…

Good technical documentation is a beautiful, beautiful thing. Almost as good as bug-free code.

Ultimate DdD to GML Converter

It occurred to me recently that my Actions could be easier to understand and debug if I refactored to convert as much of it from Drag-and-Drop actions into GML scripts. It’s a LOT easier to understand a script call to “Player_Eats_Fish” than it is to read a dozen or more DnD actions that do “Player Eats Fish” and figure out what they’re doing. Plus, you can call the scripts elsewhere if you need to.

So I started doing this, and realized that there were certain things that I didn’t know how to do. Reading the language reference in the GameMaker Help helped, but at times I still got confused… Then I googled and found this. UDnD2GML does a nice job of converting Drag and Drop actions into valid and correct GML. It’s actually written in GameMaker, too; that’s right, it’s a GameMaker project that converts GameMaker drag-n-drop actions into GML. Very slick! When you need to work out a bit of tricky syntax, or are dealing with some function you don’t use a whole lot, it’s indespensible.

Drag and Drop Icons and Their GML Equivalents for Version 7.0

Basically the same thing, only a big hypertext reference document. I liked it so much, I printed it to PDF format and am keeping it with my other GameMaker docs. Although this is for GML7, there doesn’t seem to be a whole lot that has changed in GML8. Could be a bit clearer in places, and incomplete in some regards (I had to use UDND2GML to figure out how to apply instance_destroy() to other; this document was silent on that point.)

Official GameMaker 8 Help File as a PDF

Not hard to find by any means, but if you don’t have it, it’s the best place to start. A lot nicer than searching through the Help Menu index.

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.

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?

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.

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.

GameMaker 8 bug in TestVariable action?

I ran into a bit of strangeness with my game project today. While testing a feature, I noticed something inconsistent in the way the program behaved. Upon investigation I discovered that the cause of the inconsistent behavior was that I used two different functions to do a comparison of a certain value in two different calculations, and these functions are not equivalent.

In GameMaker 8, there’s an Action called Test Expression, as well as an Action called Test Variable. It turns out that Test Variable isn’t so good when it comes to testing for equality, due to the way GameMaker handles typing of variables. For the most part, there are only two types of variables: strings and real (floating point) numbers. But in GameMaker 8 they also introduced a few new functions that return integer values. It turns out, if you use Test Variable to compare the value of a real number to the value of an integer to see if the two values are equal, Test Variable will never return true. However, if you use the Test Expression action to do the comparison, it will return true.

In most programming languages, it is impossible to directly compare an integer to a floating point number; you have to use type casting to convert one of the values and then do the comparison. Working with floating point math is tricky with computers, because of rounding errrors, where values are often +/-0.00…01 (whatever the precision is) off due to the way floating point math works. Yet, GameMaker does not display the full precision of the floating point number that is stored in a variable — it only shows the first two decimal places, and hides the rest. Thus, to GameMaker’s Test Variable action, the number 3, which might be returned by the irandom(n) function, is not equal to the real value 3.00.

Test Expression does get this right, though, and automatically accounts for the rounding error, and will consider int 3 to be equal to real 3.00(00…01).

Hopefully they’ll fix Test Variable in a future release. I have reported the issue to GameMaker’s bug tracking system.