We're Walking And We're Walking

by Ron Gilbert
Jan 25, 2015

Don't be misled by this video looking like a nearly finished point & click adventure game, there is still a lot of work to do. TODO: Insert smiley face.

My goal last week was to get the foundation of the Actor system in and working. Second only to the Room class, it is one of the workhorses of the engine and will drive the movement and animation of every character in the game.

Here is the Squirrel code...

// Called when the player clicks
function clickedAt(x,y)
{
    detective.walkTo(x,y);
}

detective <- Actor("DetectiveFemale")
detective.at(160,50);

Obviously there is a lot going on behind the scenes in the c code of the Actor class.

Being able to display and manage images is something that's been in my engine since day one, but for Thimbleweed Park we need to be able to play animations that are more than just cycling through frames. The Actor class has to manage not only walking, but reaches, gestures and various special animations. It needs to understand the direction the actor is facing and if they are talking, so all the game scripter needs to do say something like...

selectedActor.playAnimation("wave");

...and everything else is handled for her. This class got a lot of use (and overuse) in the SCUMM system. If anything had more than a two-state animation it became an actor, even if was a smashing crate, a boulder or a swinging rope.

Last week, Gary and I started looking at tools that would work well with 2D bitmap graphics and could also do layers that could be turned on and off at runtime.

Of all the suggestions we got (thank you for those), Aseprite seemed like a good choice, so we spent last week putting it through it's paces. We also built some of the animations purely in Photoshop to get a feel of that process and we'll probably use a combination of the two, with larger (in pixels) and simpler animations just using Photoshop.

Art pipeline has always been important to me, mostly because I'm lazy. I don't want to have to hand export animations when they change, I like to be able to type 'munge_art.sh' and have it go though all the art and animations files, convert anything that changed and build spritesheets.  Once you start doing stuff by hand, you introduce the human element. I like just pushing a button. More time to read Twitter.

So part of last weeks exploration was getting that process figured out. Aseprite has a nice command line tool that will pull animation apart files and dump the frames and layers into a folder, then my script invokes TexturePacker and out come packed spritesheetswith duplicate frames removed.

If we find another editor we like (or an artist has tool they feel more comfortable working in), and the file format can be pulled apart by the munge script, it should work in our pipeline. Although, there are benefits to standardizing tools, so we can't go crazy, but the flexibility is good and other reason game code shouldn't read editor formats directly. Always try and use a run-time format that can be converted to from multiple sources.  The exceptions are very standardized formats like .png or .jpg.

Onward!

After getting the engine to load the animations, the next step was playing them while taking into account the direction the actor was facing. I wrote some hacked code to respond to the arrow keys and spacebar to change direction and start and stop walking. Everything was coming together swimmingly.

Now I just need to get someone walking around the screen.  Another quick hack and I'd call the walkTo() function when the mouse was clicked.

My first thought after seeing the result was, "Hey, this is amazing!". That was followed by, "Hey, something is wrong. This doesn't feel right."

I spent a good 10 minutes clicking around the screen watching her move. Something was wrong. It didn't feel like the old SCUMM games.

Time to power up SCUMMVM and take a look at Maniac Mansion.

It hit me after the first click. SCUMM actors move twice as far in the horizontal than in the vertical. It gives the actor's movement this fake sense of perspective.

I went back and changed my code to look at the primary axis of movement, set the actor's speed based on that and then adjust the step distance of the other axis accordingly. I timed how long it took Dave to walk from one side of the screen to the other, then adjusted the detective's walk accordingly. I don't remember if Gary and I spent any time tinkering with the walk speed of the Maniac Mansion characters, but it feels good.

The other issue is that my code does most of the internal calculations in floating point (just as fast as an int in 2015, pure witchcraft in 1987), so the detective moves very smoothly, often stopping on sub-pixels. Modern hardware makes this easy and it looks really slick, but it lacks "authenticity". It's was an easy fix, but I might turn it into a user selectable option in the final game.

So there you go... another Thimbleweed Park weekly milestone checked off.

Next week Gary and I are going to focus on game design, but I also want to get started on the Room structure and setting up objects.  After that, I'll move onto getting a first pass of the verb UI.  By the end of Feb, I hope to have a mini playable adventure game all driven by scripting.

It is strange how much of this process reminds me of getting SCUMM up and running the first time.



Strawberry - Jan 25, 2015 at 19:12
Looking good!

Miguel - Jan 25, 2015 at 19:44
I really love that kind of weekly information about what (and how) are you doing.

ABC - Jan 25, 2015 at 21:13
I love these posts. I would have imagined that the development of the engine would be much slower. I guess this is what happens when you've already done this kind of stuff a few times.
Also... please... no subpixels.... they are horrible!

Brian Ruff - Jan 25, 2015 at 21:55
A "smooth operator" option would be great.  It would be great to able to switch back and forth. I want to see Maniac Mansion with the same level of smoothness now. Doesn't affect the feel of the story at all IMHO.

longuist - Jan 26, 2015 at 04:20
I second this. Good idea to have this "authenticity" operator. Full Pixel (is this what it was in Monkey Island?) should be standard IMHO, for enthusiasts the ultra blocky c64 Style as option. And of course the criminally smooth floating point movement, making it 3 options in total. Thanks for your sense for details!

longuist - Jan 26, 2015 at 04:20
I second this. Good idea to have this "authenticity" operator. Full Pixel (is this what it was in Monkey Island?) should be standard IMHO, for enthusiasts the ultra blocky c64 Style as option. And of course the criminally smooth floating point movement, making it 3 options in total. Thanks for your sense for details!

longuist - Jan 26, 2015 at 04:48
How did that happen? Sekrit question was wrong (timeout), but still published it? Sorry for the spam. Just want to add, as we have the future now (2015) i think in the future future (2016) the smooth option should be the default. (Which is the first thing i will change in the options :)

Derrick Reisdorf - Jan 25, 2015 at 22:49
Seeing this code talk makes me want to finish some of my personal projects I never finished.

Linus - Jan 26, 2015 at 00:02
So you are writing the whole engine from scratch? Somehow I was under impression that You had most of the code already handy. Was that only the low-level stuff?

Ron Gilbert - Jan 26, 2015 at 01:30
No, it's not from scratch, I have a library of code that handles low-level stuff like rendering images, managing memory, rendering fonts, etc. But there is a lot more "glue" that is need to make an adventure game.  As the post said, I have a pretty powerful lib for rending images, but it doesn't do more than simple animation, not at the level an adventure would need, so that's what I'm doing now.Walking a actor around the screen is filled with complexity, like path finding, clipping, etc. That is what I'm writing now.

enthusi - Jan 26, 2015 at 03:33
Are you implementing walking-boxes with pre-calced matrix again? Or real-time pathfinding to allow more easily for moving obstacles?
On c64 the actors were moving a full char (8 pixels, or 4 double-wide pixels actually) horizontally to allow for the column-based masking.
I always wondered why MM and ZMK (on C64) hat that jerky scrolling though the C64 had pixel-wise hardware-register-scrolling. Only much later I learned about the pains of sprite-masking in software :)

MarcusG - Jan 26, 2015 at 02:31
This is lovely. It's great to have you guys talking so freely about the development process.
It's a refreshing change to the sugarcoated PR blah-blah of other many dev blogs.

Roberto C - Jan 26, 2015 at 02:37
I agree, it is really interesting Ron to see these weekly updates. As a developer I love the insights into the working process, tool and language choice, etc... Maybe I'll copy it someday to write my own game :D

Momomomo888 - Jan 26, 2015 at 02:57
Glad to see that pesky DetectiveFemale moving around :P

A question about the animation to engine pipeline. Looking at the atlas, it's obvious that you have your character fractioned. Right now head+body, but I suppose it's expected other "cuts" to save on texture memory. Are you storing the relative position of each body part when exporting from aesprite to rebuild the animation later? How it's going to be the animation format, something like scumm AKOS? plain xml?

I usually do this via a custom flash exporter to XML, to then rebuild the animation on Unity's native anim format... I save relative pos of each body parts to the character hotspot point (usually at the character feet), number of frames showing, fps and stuff like that. For some anims I store the hotspot position too, as I change it. The resulted anim curves needs cleaning though.

And about pathfinding... MM and Thimbleweed Park have this kind of horizontal rooms, where you could even avoid pathfinding if you wanted to... but, seeing that you have already mentionend it... are you planning on walking boxes? a room editor?

Rooms, scripts, actors... *ahh* adventure game engines makes me feel so fuzzy xDDDDD

Patoland - Jan 26, 2015 at 05:34
Hi Ron, this series of articles are just a dream! As Enthusi has asked above, i really wonder if you can give as some details about the system you're using to move the characters.  Are you going with the walking-boxes as in the old times or are you favoring a path metod? Whatever the answer is, maybe you could be so kind to explain it on detail, as you did with the Puzzle Dependency Charts. Please, please?
Thank you so much!

Tomimt - Jan 26, 2015 at 06:00
Keep these kind of post rolling Ron. These offer a very interesting glimpse on the developement.

Dave - Jan 26, 2015 at 06:42
Yay! Nice to see the proper traditional mouse cursor - can't wait until it starts blinking tho ;)

Dienes - Jan 26, 2015 at 06:51
The animations feel very good, just like the classics.

But I have to say the vertical movement animation is a bit weird... It seems to be more fluid than the horizontal one, plus those overly wavy arms just appear too "dancy" :)

Gary Winnick - Jan 26, 2015 at 12:48
At this point everything we're running are just test animations with some
exaggerations- we're also looking to determine how much we'll mimic
the original Maniac style and will also be fine tuning that as development progresses.

-Gary

Yuri Brunetto - Jan 27, 2015 at 06:54
This animations has been make in Aseprite?

Janski - Jan 28, 2015 at 08:45
That's what I thought. This is kind of Irish overtly jolly elf style if walking.

Janski - Jan 28, 2015 at 08:51
Oops, wrong place for a reply.

JB - Jan 30, 2015 at 12:36
Exactly what I thought when I saw it. It doesn't seem to fit the character/style, unless she's supposed to be dancing or just walking weird...

Yuri Brunetto - Jan 26, 2015 at 07:19
Bravo! Really nice stuff.

But Ron, I have a question about the music you and Garry used in the Thimbleweed Park trailer. It's a music from some artist or you guys created the music?

Thanks!

Peter Campbell - Jan 26, 2015 at 09:57
Steve Kirk composed the music for the trailer and is going to be doing the music for the game.  He's also worked with Ron before on the mobile puzzle game Scurvy Scallywags.

Yuri Brunetto - Jan 26, 2015 at 10:17
Ohh, cool! Thanks for answering.

LichiMan - Jan 26, 2015 at 07:21
The blog is getting better and better :)

I really like the front and back animations. They are so smooth and work great, but I miss some frames in the side animation. I miss the second step. Also there's two frames where the arm is in the same straight position that makes some flicker animation instead of the smooth one that front and back animations have. Maybe this is the way Gary wanted to do it, so it feels like in MM, but when I saw it for the first time, it grabbed my attention.

Anyway, it's starting to look great.

Poker - Jan 26, 2015 at 07:26
Would it be possible to be able to channel frustration by clicking the character furiously?

Being stuck for several days surely is part of a proper adventure game experience (was in the 90's at least). I'm okay with that, but it would be nice if I could share the pain with the character.

longuist - Jan 26, 2015 at 08:15
tehee. No memory constraints excuse this time for requests like this :)

Miguel - Jan 26, 2015 at 07:33
I am really enjoying all these blog posts. I appreciate it takes time to write them, but please be sure that we're enjoying them as much as we will enjoy the game itself. I did a small adventure game engine a year ago in HTML using PhantomJS and did some research on how SCUMM stored data. I found the way to store rooms' "walkable areas" in inter-connected boxes very interesting, but didn't have time to do it like that and ended up implementing a simple x-y node graph with pathfinding. Nodes also had a "scale" property, which affected the speed and size of the actor from that node to the next one.

As you've mentioned the room design to be the next programming checkbox, do you plan to use the same system? I read somewhere that the reason the "connections" (which is the fastest route from box A to box B) were precalculated was due to the low processing power of computers at the time. Will the engine you're working on calculate them on the fly?

Please don't be afraid of sharing those details once you come up with solutions, nothing is technical enough! Thanks again, I'm so proud to be a backer :)

Yuri Brunetto - Jan 26, 2015 at 10:18
Hey man, what is this game that you did using HTML and PhantomJS? There is a GitHub repository for this or an URL link?

Miguel - Jan 26, 2015 at 17:43
It's too basic to be used and it just includes room definition with objects, paths and actor animation. I really have very little time to work on my pet projects, but if you're really interested send me an email to miguelmail at gmail dot com

Yuri Brunetto - Jan 27, 2015 at 06:52
Just emailed you :D

Zak Phoenix McKracken - Jan 26, 2015 at 09:30
It's really fantastic!
I remeber that in MI2, when the room was a "long shot", Guybrush sprite changed its size while walking on the paths, to respect the depth of the room.
Do you plan to implement that feature, or it will look like Maniac Mansion?

TheBuzzSaw - Jan 26, 2015 at 11:09
Don't be *misled*.

Mattias Cedervall - Jan 26, 2015 at 11:56
Looks good! :-) I want to translate Thimbleweed Park into Swedish for free like I mentioned before! ;-)

Watching Good Will Hunting helped me solve the seckrit question. :-)

Second best regards, Mattias (maleman guydude)

Francesco Favia - Jan 26, 2015 at 14:13
What? no rag doll engine? O_O

Max - Jan 26, 2015 at 18:34
Very confident walking style that lady has with all that chest beating...! Great blog so far, will definitely remain interesting in it's own right even after the game is finished, I think!

Mike McP - Jan 26, 2015 at 20:28
Another great article...thanks!

I only understand about 1/4 of what is going on in the article and comments, but it's still fascinating seeing what goes on behind the scenes in an adventure game.  As a programmer, this is much more interesting than seeing a room of 2 dozen people coding and motion capturing the next Call of Duty.

Ron Gilbert - Jan 26, 2015 at 20:40
_"seeing a room of 2 dozen people coding and motion capturing the next Call of Duty."_

Crap. There goes our next blog entry.

Jammet - Jan 27, 2015 at 01:26
The animation looks really good. I am thrown back to Maniac Mansion and Zak! I love how they now swing their arms - having them stretch away further from their bodies! I know back than that was not possible or feasible to accomplish because of technical limitations, if I remember correctly!

Thanks so much for this update! I love this!

Marco Lizza - Jan 27, 2015 at 08:50
You're correct. At the time the character animations where confined into a strict bounding box (being formed by vertical stacked sprites).

Joost - Jan 27, 2015 at 03:55
It must be very rewarding to see things actually fall together and DO stomething. Fun to read, at least.

Petruza - Jan 27, 2015 at 08:52
The sprites are looking great, but why are the woman's breasts square? it looks like Commodore's fat pixels, although the rest of the sprite has square pixels. I think her breasts could be a little smoother. (Yes, I know these are definitely not final graphics)

Farooq - Jan 27, 2015 at 14:34
Is it safe to say i'm the youngest fan you have? I mean i was just born the year day of the tentacle got released. Thank you gilbert and winnick for bringing back those sweet "pixelated" days . Rock on!

Dave - Jan 27, 2015 at 19:15
This post, once again in my life, has me thinking about how I can possibly repair the stairs in the mansion's library and see what's up there. Knowing it's impossible, it's a frustration that will most likely stay with me my whole life.

Christopher Griffin - Jan 28, 2015 at 12:09
That's exactly the sense of wonder these games were so good at evoking.  I too had the same desire to climb those damn stairs, and I feel much better as an adult now knowing that others longed to explore what was at the top of them!

Tim - Jan 29, 2015 at 10:41
This blog takes me back to my childhood. Back then I found it fascinating just sitting in the living room, listening to the conversations grownups had, despite understanding half of it at best. To me blog updates like these have a similar effect. Keep it that way, it has a charm of its own.

Justin Graham - Feb 10, 2015 at 22:04
IIRC SCUMM had a tool that you could draw walk boxes in, and set the Z for the near and far sides, and the walk code would linearly interpolate over that distance, so you could create a box that had a really deep Z so it would take a long time to traverse the distance vertically. Perhaps the same was true for left and right, I forget now :)

Ron Gilbert - Feb 10, 2015 at 22:07
Kind of. When scaling was add in Monkey Island, the walk-boxes had a scale at the front and back and that did control time it took to walk.  In Maniac Mansion, LOOM, Zak and Indy it was hard coded.

ac - Feb 12, 2015 at 20:22
(this might not be really relevant - I'm assuming you are intentionally going for this style but I'll have my 2 cents anyway make of it what you will)

If there's one thing that bothers me about this project, it's how serious the characters we've so far seen look like and that's part accentuated with the palette. The palette feels more life-like, or in other words more "drab" than "80's tv/jerry bruckheimer/don simpson". There's a crazy amount of drab-palette+sadface style indie games out in last couple years. I generally think that once something is getting popular in way that it's hard to ignore, the trend pendulum is going to swing the other way or elsewhere.

A good example of what I'm talking about is the cheery old school palette of Minecraft vs a bunch of clones trying to do the same but with a drab palette that's not really doing any favors besides being different for the sake of it. I kind of believe that in both music and graphics, it's not about the unlimited possibilities of sounds and colors you can produce, but figuring out which frequencies in sound and light and their combination produces the most pleasing output. According to some statistics only ~5% of the population are wired in a way to be able to "hone in" on the ideal colors/sounds suited for based on the scene, writing etc.  I can instantly tell within 5 seconds of youtube viewing whether any entertainment product had the "right people" making it as the difference especially in music is so striking. As "bedroom production" became popular I suspect where the industry in past had higher percentage of these 5%'ers, they are now in a niche - and that's why I stopped listening to new music as finding good new music became extremely more time consuming.

ac - Feb 12, 2015 at 20:31
I'll have to add to the "drab palette" point that of course tweaking the lcd TV/CRT-like output helps a great deal but it does highlight the age of music production dilemma : how you get the mix (or palette) to sound great on as many systems as possible - using some sort of case by case center band in eq or palette will be needed to find out what works in as wide range of settings as possible. (eg. I had this LCD set to brightness 0% and it tends to make the colors more drab, while on my OLED TV I can do to quite dim through its wider array of available settings and stay closer to the intended colors).

Gianni - Feb 22, 2015 at 08:42
Hi Ron,
first of all, thank you and Gary for this great devlog: it is very nice to peek at the Voodoo you do to piece this great adventure game together.
I'd have a question about the interactions between your C++ game engine and the Squirrel scripting layer.
Assuming you could have a script like the following this:
selectedActor.walkTo(100, 10);
selectedActor.playAnimation("wave");
selectedActor.say("Hello Everybody!");

I imagine the walkTo will invoke the actual C++ code that will set the state of the character class to render the right frame at each draw call.
How does the Squirrel script gets notified when the walk target as been reached, so the script can resume to the following line?
Do you achieve that with some event subscription/dispatch system?

Ron Gilbert - Feb 22, 2015 at 12:29
In your example, all three of the commands will execute without waiting (like a normal program would).  

To make it wait, you'd do...

selectedActor.walkTo(100, 10)
waitForActor(selectedActor)
selectedActor.playAnimation("wave")
waitForAnimation(selectedActor)
selectedActor.say("Hello Everybody!")
waitForTalking(selectedActor)

I haven't completely figured out the naming of the commands, so that will likely change.

You can also do...

breakwhile(selectedActor.walking())

Gianni - Feb 23, 2015 at 02:47
I see: asynchronous calls and waitFor functions for synchronization.
Cool, thank you!