Playing around with new systems

Sep 18, 2010 22:51


I've recently been messing around with the Game Maker 8 system, to see what the state of play was for action-style games that are targeting non-programmers.

Short form: I was pretty impressed. I'm no longer really surprised that Iji and Spelunky could be written in it. But it's not a 'non-programming' system by any measure, other than that it tries to be discoverable.

In an effort to make more sense out of it, I took on a minor project with it to put it through its paces: Imperial Solitaire. Behind the cut, my development diary for it.
Imperial Solitaire: Dev Diary
Day 1
  • Download DM8 Lite to mess with. As a programmer, I start out skeptical; typically things that advertise themselves loudly as NO PROGRAMMING LEARNINGS REQUIRED!!1111!! are horrendously constrained things that only let you work inside the engine designer's cramped vision, which in turn usually has more to do with what he could come up with for an engine you could fit into a Windows Form than with what's actually a good idea. On the other hand, Iji and Spelunky were both written with this, so I have a more open mind than it sounds like.
  • Also grab a bunch of tutorials. Once it's installed, I notice the "Catch the Clown" tutorial looks like a weaker version of the Exploding Fruit demo that ships with the system; I toss the clown aside and work through the basic tutorial and about half of the scrolling shooter one.
  • I'm actually pretty happy with the basic engine; the event model is sensibly designed even in Simple mode and Advanced mode exposes some things that look like they'd be very handy indeed.

At this point, would I recommend it to someone wanting to do game development? Well, if they don't already know how to do everything that's exposed in simple mode, and what it means, just by looking at the interface, then I'd be comfortable saying they have no business writing their own engine unless they have "learn to write an engine" as their goal. A very good start.

That said, I'm a little skeptical of the NO PROGRAMMINGS REQUIRED pitch; even the simple mode involved doing programming, albeit very much at the level of, say, LEGO Mindstorms. Then again, that level of thought organization seems to be broader than traditional coding skill, so OK.
Day 2
  • Finish the scrolling shooter tutorial.
  • Notice there's an actual PDF manual. Grab it for perusal, since after the tutorials I have a lot of questions about how far I can push various things.
  • Get distracted by poster hunting in Iji.
  • Get distracted by Hero Core.
Day 3
  • Finish reading the manual, particularly with respect to GML. The PROGRAMMING OPTIONAL claims are feeling real hollow here; GML looks to be a close cousin indeed to JavaScript. Even without GML scripting the engine boasts prototype-based inheritance!
  • Resolve to develop a simple game on my own to put the system through its paces and see how it performs just as a media and physics library. Initial plan is to do a graphical version of Nethack's Sokoban levels, but I instead settle on a variant of "Acey-Deucey", the first game in Ahl's old book 101 BASIC Computer Games. Yeah, the one that didn't have Hunt the Wumpus in it. 12-year-old me was pretty disappointed.
  • There's a full set of playing card graphics already present in the shipped development system, so it's the work of an hour or two to write a set of scripts that will generate, shuffle, and render decks. I produce the Shufflematic as a simple proof of concept, and it goes quite smoothly. This is already more work than the Acey-Deucey implementation did; when it drew cards it selected each rank with equal probability, as if it were reshuffling the deck after every card appeared.
  • Since I've got shuffling working, and a complete deck simulated, I actually have a natural endpoint; if the player exhausts the deck without going bust, they win. Clever bidding will give them a chance to minimize losses and optimize their score within a constrained space. Since there will be 17 hands played, I rename this variant "Imperial Solitaire" as a nod to a certain fantasy series I'm fond of.
  • With a finite number of plays, it seems kind of dumb to just let them bet the minimum every time and still be guaranteed to not bust out. I write a little 25-line Python program to simulate a million games to see how many hands the player is likely to actually win; the answer works out to about 6.7 out of 17. With a starting bank of 10 units and a minimum bet of 1 unit, the player will likely survive to the end, but it'll be close. That's a decent start, though we might as well multiply all those numbers by 10 to look higher-stakes.

At this point, I'm pretty sold on the system as being generally solid. I'm not quite to the point where I'd be confident in it, but it's looking very much like I could end this little exercise saying "If you're doing 2D game development for windows, you should seriously consider just using Game Maker instead of rolling your own engine. Even if you're a programmer already." Wanting Mac/Linux support, or objecting in principle to paying for dev software, would both count as compelling reasons otherwise, and both are admittedly not uncommon. Even then, the Lite version may be worthwhile for prototyping.

And if you aren't already familiar with media programming? There's already no question - you should be looking into this as a development platform. That said, if you get good enough with this that you can do anything remotely nontrivial with GML? You are a programmer. Using what you learned in learning GML you'll be able to pick up Python in a weekend just by reading its official tutorial, and JavaScript will look like an old friend (though the bits where you have to deal with the browser Document Object Model are going to be a lot uglier than dealing with GM8's event hooks and libraries were).
Day 4
  • Actually set up this diary.
  • Organize the game logic's flow. There will be one object (obj_gamemaster) that controls the deck and the rendering thereof, and then other objects that handle the UI. The gamemaster object will also hold a game_state variable that indicates what kind of input, if any, it's waiting for. If it's not waiting for any input, it performs the necessary game computation (dealing, resolving bets, etc.) and then jumps the system to the next state. The title, and the game over screens (win or lose) will all be handled as separate "rooms".
  • Game State 0: Dealing the two cards at the start of a hand, then shifting to game state 1 (get player's bet).
    • I'm making an effort to keep scripts both self-contained and used minimally, so I have a "deck_init" script that generates and shuffles the deck, but the rest of the gamemaster's initialization is handled with the Mindstorms interface.
    • Make a neat little script to have the deck of unused cards shrink as the game progresses. That goes in the general board rendering code.
    • Throw together a quick little event handler that lets me step through a game with no deal forthcoming. Interactive test case in five "lines of code"; not shabby at all. (EDIT: I notice while wrapping up for the night that this is actually about half of Step 3's logic right here.)
  • Game State 1: Taking the player's bet.
    • Make a little button sprite. Details will be filled in by the object later.
    • Inheritance! Make a base object to represent all bet objects. Its children will set bet_value, but this object handles Draw and Mouse Press based on that value, communicating appropriately with the gamemaster object. I seem unable to copy a field from the button into the obj_gamemaster object with the set-variable token, so I have to skip out to GML to manage that. That's kind of a letdown, since communicating with the controller object seems like a pretty reasonable thing for a novice to want to do. (EDIT: It turns out this is possible after all; you need to do the set variable action, do it on "self" - in this case, the subclass of base_bet - and then assign to obj_gamemaster.bet. Objection withdrawn.)
    • Make five bet buttons that use it as a parent object and have only two unique components: a keyboard listener for their value and a create event that initializes said value for the base object's functions. The keyboard events all basically emit a mouse-click event on self; I find I have to break out to GML to actually do this because event_perform() doesn't seem to have a corresponding action token. I grouse a little at this, too, though event_perform() is a sufficiently unusual thing that I suppose it makes sense to keep it a super-advanced thing. It doesn't seem like it would be intrinsically too hard to make a form-filler, though, especially since "process parental event" is a token already.
  • Reading through the manual some more, I discover the set_application_title() function, which seems to do something I'd wanted to do for the Shufflematic application; I'd worked around it then simply by renaming the .gmk file. Still, it's nice to know this exists.
  • Add some more test code to obj_gamemaster, allowing one bet to be made and displaying the result in a window corner. This also shows that the table rendering code correctly flips the center card once a bet is made.

As you can see, most of my complaints today are actually that I had to go out and use GML for things I feel I shouldn't have to. This is sort of interesting; it may be that I'm approaching going to GML the way an Inform 7 programmer would approach having to drop into Inform 6.

There are places where I could see a good software engineer wanting to generalize more than this seemed to allow; in particular, the five subclassed instances of base_button might have easily been programmatically generated, but to really do that right they'd also need to be able to programatically wire up their event triggers. I don't believe that's possible in GM8; the closest you can get is an object that polls the key state in its step event and that's not really a great design either.
Day 5
  • While gearing up and reviewing were I'd been, I noticed that Game State 0 was completely superfluous; the variables it was supposed to initialize are actually handled entirely by the Create event for the gamemaster object, and the transition from state 3 back to state 1. We can drop state 0, so we do.
  • Mess around a bit with the Bet buttons so that they are only actually visible during game state 1, and only if the bet they provide is a legal value. As the player goes broke, the buttons vanish until they win enough stake back to make those bets.
  • Game State 2: Evaluating results.
    • This is pretty straightforward in principle; we need an expression to see if we've won, then we adjust the score appropriately and set up some kind of result message.
    • That expression is tricky, though. AND tests are not too rough in the Mindstorms system, but OR tests are hopeless. Your only hope is Test Expression, but even then you're better off with a script. So I use one - but only to see if we won. The rest is done with Mindstorms code, and while it's kinda lengthy, it's not too rough. The "Exit Event" action makes for a useful break routine.
    • Tests quickly demonstrate that I blew it when computing deck ranks; Aces are supposed to be high, which required quite a bit more code in the winning_hand() script. Not hard, but kind of forehead-slapping.
  • Game State 3: Hand results.
    • The plan is to wait for input, then transition to a win or loss screen - or just go to the next hand if there isn't a win or loss on tap.
    • We don't have the win or loss screens at this point, but the basic wait-for-input stuff is actually mostly already done from our State 0 test code before.
  • Add some extra rooms for representing win and loss, and give them the option to replay or quit.
  • At this point we have a basically playable game, so we start testing.
  • Fix a bug where you could make bets using the keyboard that you couldn't do with the mouse, which would let you go into the negative cash levels.
  • By making our cash level be our score, a lot of the code is dramatically simplified, and this also lets us more easily transport score between rooms.
  • Allow generic mouse clicks to move to the next round. The game is fully playable using only the mouse now.

Not a lot to say about my work today. I dug the room transition options, I guess, but that does boil down to chrome. Text rendering continues to look Kind Of Weird; I should do something about that, especially since it doesn't really seem to be an issue when I put fancy text in the backgrounds. That said, at this point GM8 is just an invisible tool.
Day 6

Miscellaneous polish.
  • Mouse buttons for Yes and No on the win/loss screens.
  • Title screen.
  • Help text with F1.

I suppose I could have also created a custom icon for it, and its own load screen, but this was never intended to be a seriously published work or anything so it seems kind of superfluous. I might add that later if I get the Pro version, but for now I think we can put this project to bed.
Conclusions

This was pretty educational in terms of getting a grip on the corners of the system. I didn't come close to exhausting what it can do but with the familiarity I had with it I can make my judgements on it now.
  • If you aren't a skilled developer already, this is an excellent system to work in. It's got a surprisingly good engine paradigm - if you move on from GM8 to some other development system, you'll have picked up good habits from GM8. It's got a lot of training wheels when you're just starting out, but it'll grow with you too. It's got a very active user community. Stuff you build with it is very easy to distribute. And if you go Pro with it, it's way cheaper than, say, a Flash development kit.
  • If you've done some programming but don't have much experience with games, you should at least look into this. Writing an engine is Work, and if you go this route, along the way you'll have something you can show off and test and tune. Also, above the "teaches good habits" and "grows with you" points above; it'll likely stay out of your way, and if you find it isn't, the odds are quite good that it's right about how your code should be organized.
  • If you're already experienced in 2D game programming, there's not a whole lot here you haven't seen, and the reasons to not use this system are more likely to actually swing the pendulum the other way. I'll get into those below. You might still want to poke at the free version to see what it's about, and it could be useful as an initial prototyping tool.

If you're planning on rolling your own, you'll also need to be able to meet or beat the basics of what GM8 gives you "for free". To wit:
  • Animated sprites with adjustable center points, and game objects that can share them or change them on the fly.
  • Event-based game architecture that let your game interact safely with the OS.
  • Not mandatory, but probably always a good idea; an ability to replace event handlers piecemeal or wholesale.
  • Frame rate throttling, and an ability to tell if you're overloading the system.
  • Fire and forget sound mixer that can handle sound effects and music without much interference.
  • Collision detection; most serious games will custom hitboxes as well, as bounding box and pixel-perfect are both very rarely actually the right answer.
  • Viewport control; the screen will generally be much smaller than the playfield, and you'll need to handle this sensibly.
  • Resource bundling. You don't have to cram everything into the EXE the way Game Maker does, but you'll probably at least want the equivalent of ZipFS or other data agglomeration systems to avoid wasting disk space on FAT32 or whatever.

That's a lot of work, so if you don't have a bunch of that already handy, using GM8 means you have a bunch of work already done for you. So, why wouldn't you use it? There are a few reasons.
  • It costs money. It's not uncommon for a dev to insist on a $0 overhead on dev tools, especially for prototypes (though the Lite version may still be handy there.)
  • No native support for advanced sound formats, noticably MP3 and Ogg Vorbis. Thanks to limited support for extension DLLs, there are ways around this: Hero Core uses FMOD, while Spelunky uses an extension called "Supersound". This could be problematic in general, though, because...
  • It's not cross-platform. The system is Windows-only right now and while a Mac version seems to be in the works, it doesn't look like there's parity, and things like Supersound might not port. If you want to target Linux you're out of luck, so going full tri-platform means you'll have to roll your own.
  • It looks like most resources are going to be loaded into memory all at once at game start. If your game is large enough that it should really be using resource overlays, you may have some trouble. I think this is still possible, but I think it only works in the Pro edition so I can't evaluate it.

Those are enough that (given my own background) I probably would not personally use GM8 for anything beyond toy projects; but I know enough about the general area to know a good product when I see it, and this is a good product. Kudos to Yoyo Games.

games, development

Previous post Next post
Up