Keywords: game, game_source
[2007-1116: Article updated. Scroll to bottom for update.]

Download That Darn Saw... if you dare!

Recently I was trying to think up some good gameplay mechanics for a game that would have been far more tasteless than this one ended up being. My train of thought led to the classic electric "Operation!" game -- you know, the one with the tweezers and the buzzer -- and I started pondering how that might be simulated in BYOND. Soon I recalled that I'd seen some Flash games that came about as close to a video-game version of Operation as you could hope to get, at least until the day that touch-sensitive screens become common. In these games, the mouse pointer itself acted as your character, and the goal was simply to get from one end of a maze to the other without touching any obstacles. Could BYOND do this? Yes, it could! And here's That Darn Saw to show you how, in six ten-second levels of watered-down terror.

The MouseEntered() proc, which can be defined for any atom in DM, is the key. If you look at the Reference, you'll see a pretty heavy warning: "Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Defining it on only the objects that require it reduces overhead." This "extra communication" is between Dream Seeker (the client that's showing you the game) and Dream Daemon (the server that's managing the game).

I figured this wouldn't be an issue for That Darn Saw, because it would be the kind of game that a single player runs on his own computer. I was mostly right, but there was a hangup. In Level 5, it turned out that passing over the field of non-deadly holes ended up making the exit take a second or more to realize that the mouse pointer had entered it! It appears that the MouseEntered() calls actually queue up to be executed over successive ticks. The solution is simple, though: when the spikes retract, each hole gets mouse_opacity set to 0, so the mouse ignores it altogether.

MouseEntered() aside, what else might interest you in the source code? How about:

* If your understanding of object subclasses and inheritance is rusty, you can browse through the level asset objects. There are four workhorses in this game: entrance, exit, key, and obstacle. Each one comes with a few handy "toggle switches" (careful, one of them is deadly) and when those aren't enough, you can still probably get what you need with just a little customization.

* Really, I mean just a little customization. Here's the most complex customization in the whole game:

    sign //level 4
icon_state = "sign1"
var/jibbly = 0
var/xmod = SIGN_XMOD

jibbly = 1
spawn Jibble()

. = ..()
icon_state = pick(list("sign1", "sign2", "sign3", "sign4"))
pixel_x = rand(-8, 8)
jibbly = 0
xmod = SIGN_XMOD

//move the sign back and forth
pixel_x += xmod
if(pixel_x >= MAX_SIGN_PIXELX)
xmod = -xmod
else if(pixel_x <= -MAX_SIGN_PIXELX)
pixel_x = -MAX_SIGN_PIXELX
xmod = -xmod


(Can you spot the very-unlikely-to-happen, but still theoretically possible, problem with this code? Here's a hint: what if SIGN_DELAY was 5 seconds instead of one tick?)

* There's a handy "readout" class for displaying numbers on the screen. It's a problem that many have solved before and it probably didn't need to be solved again, but nevertheless I'm throwing it in free of charge, just to be a sport.

* Notice that this game barely uses the player's mob at all! The mouse provides all your input, and the pointer is your avatar. The player does have a mob, but it's invisible and mostly just sits around waiting to be moved from level to level. In fact, for what little behavior I did program into the mob, almost all could just as easily have been put into the client instead. There's nothing wrong with mobs, but it's good to keep in mind that you don't always need all the features of a mob -- after all, a mob is basically just an obj that has a client attached to it, so in some games (for example, puzzle games and card games) it makes sense to put a lot of your code into the client and the objs.

* If you hate source code and everything associated with it, you can still use (and modify) the icons. They're not fancy, but every time you don't have to draw an icon from scratch, it's like adding minutes to your life.

Thanks to Shadowdarke and IainPeregrine for their input and technical know-how!

* * * * * * * * * * * * * * *

UPDATE 2007-1116: Maybe I was too enthusiastic about my little game! In the comments, some readers have spotted a few noteworthy flaws. Garthor notes "On most of the levels, typing ".mouse-over Exit" into the input bar will trigger MouseEntered() on the Exit turf, which will make you instantly win," and also that moving obstacles won't kill you (i.e., MouseEntered() won't be triggered) if your pointer is holding still and the obstacle runs into you, instead of vice versa. And Ss4toby notes "If you click and drag you dont enter a turf (can use this to cheat)."

Of these, I'd say that the moving-obstacles problem is the worst from my perspective -- "worst" meaning both the most serious flaw, and probably the most difficult to fix. I'll plan to update the game to remove the flaws I can; in the meantime, see the comments for Garthor's and Ss4toby's additional observations. Thanks for the education, guys!
I remember making something like this a long time ago. I noticed that it has the same problems that I encountered. Namely, the use of .mouse-over to easily cheat, and moving obstacles not "killing" you if you don't move your mouse.

The first problem is easy to (adequately) solve: just keep track of which turf the player is pointing at (a good use for their mob), and only allow it to move one turf at a time.

The second... not so much. It may be possible using GetPixel() (which was not available when I made my version of this), but it certainly wouldn't be an easy fix.
Well, how do you like them apples? I wrote the game and had two people look it over, and none of us spotted the moving-obstacles trick. I'll have to try it out when I get home, and amend the article accordingly (with proper credit to you).

I don't understand the part about cheating with .mouse-over, though... can you elucidate?
I found a small problem myself. If you click and drag you dont enter a turf(can use this to cheat). Just make the same thing enter does happen for mousedrag. Besides that it was pretty fun, but sometimes hard to understand(the fortune cookie one messed me up, didnt realize I had to go to the cookie).
On most of the levels, typing ".mouse-over Exit" into the input bar will trigger MouseEntered() on the Exit turf, which will make you instantly win.