John 'The Gneech' Robey's comics, writing, and art. Sat, 15 Jul 2017 19:33:28 +0000 en-US hourly 1 The Halfling Lass From Appletop Sat, 15 Jul 2017 19:33:28 +0000
Berelandine the Halfling Serving Wench by Dunlaoch on DeviantArt

A popular barracks/meadhall song in Orbis Leonis, sung to the tune of “The Mademoiselle From Armentiers.”

The halfling lass from Appletop is a tavern maid.
The halfling lass from Appletop is a tavern maid!

The halfling lass is a tavern maid.
In gold or kisses she gets paid!

Will you have another round, me lord?

The halfling lass from Appletop is three foot high.
The halfling lass from Appletop is three foot high!

The halfling lass is three foot high.
She looks your codpiece in the eye!

Will you have another round, me lord?

The halfling lass from Appletop is a lovely girl.
The halfling lass from Appletop is a lovely girl!

The halfling lass is a lovely girl.
She’ll take your stallion for a whirl!

Will you have another round, me lord?

I asked the lass from Appletop to be my bride.
He asked the lass from Appletop to be his bride!

I asked the lass to be my bride,
and spend a lifetime at my side!

Will you have another round, me lord?

The halfling lass from Appletop said “Nay, sir, nay.”
The halfling lass from Appletop said “Nay, sir, nay!”

The halfling lass said “Nay, sir, nay!
Not until your tab you pay!”

Will you have another round, me lord?

Put that in your weed-pipe and smoke it. 😉

-The Gneech


]]> 0
A Bit of AwesomeSauce Fri, 09 Jun 2017 18:04:26 +0000 "Roughness in da House" by Vince Suzukawa
“Roughness in da House” by Vince Suzukawa

Longtime Suburban Jungle fans know that Vince and I are ol’ pals and mutual fanboys. We don’t get to collaborate (or even chat) nearly as often as I would like or as we used to, but we do still keep in touch when we can, and he recently sent me this, which I have been geeking out about for weeks now.

He finally posted it to his FA page, and so it’s time to share it with the world! Enjoy. 😉

-The Gneech


Tigerdile and YouTube and Twitch, Oh My! Mon, 22 May 2017 20:22:01 +0000 Bringin' the Awesome! Art and Gaming Streams by The Gneech

In an effort to broaden my reach and find more audience, I have begun doing livestreams of art sessions and of my Overwatch sessions, as well as posting recordings to YouTube. So far I’m still in the earliest stages of figuring it all out, but I’m a pretty quick study and I think I’m getting the hang of it! I will add these feeds to the sidebar links on (which is due for a massive overhaul, actually), but for now here’s a quick list where you can find Gneechy Video Goodness!

These time slots are fairly dependable, although if I’m at a convention or something similar obviously that will have an impact. Besides subscribing for notifications on the respective services, you can also follow me on Twitter for the most reliable updates. I try to Tweet at least an hour before I will start streaming to give people a heads-up.

Thanks for watching! Let’s have some fun!

-The Gneech


Tutorial: Create a Tic-Tac-Toe Game in JavaScript Wed, 10 May 2017 20:12:33 +0000 This exercise was created as a tech writing sample, but hey, it also made a playable Tic-Tac-Toe game, so I figured I’d put it up here for you to enjoy!

Tic-Tac-Toe has been around since at least the days of the pharaohs and has been played with sticks, pebbles, pencils and paper, but with these instructions you and your friends can play Tic-Tac-Toe on any web browser. A sample version of the game is here: My Tic-Tac-Toe Game.

The Basic Game

Tic-Tac-Toe is played on a 3-square by 3-square grid, as shown below. Players take turns placing their mark (an X or an O) until one player wins by putting three marks in a row, or until all squares are full. If all the squares are filled without getting three in a row, the game is a draw.
Tic-Tac-Toe sample games illustration
(click to enlarge)

How the Script Works

The pre-game stage draws a table with three columns and three rows and a label indicating whose turn it is. Each data cell within the table can have one of three values: “X,” “O,” or “blank.” At the beginning of a new game, which player goes first is chosen randomly and all cells are blank.

When a player clicks on a blank cell, the page assigns the selected cell to the player by filling in their mark, and redraws the grid.

If there is no winner and there are still blank cells, play continues, returning to step 2. If there is a winner, or there are no more blank cells, the game ends with either a message indicating the winner or that the game is a draw, and generates a “Start New Game” button.

Step One: Create a Framework

Before we can play a game, we need to have a page for it to reside on. Since this game is written in JavaScript, that means a simple HTML page. This particular page uses basic inline styles for simplicity, but your own page can use CSS to be as fancy as you like. A basic HTML shell looks like this:

Tic-Tac-Toe sample code
(click to enlarge)

Note the ID attributes of the <p> and <td> tags. Those are important, as we’ll be using those to tell the JavaScript where to place game elements. Each one must be unique, to avoid confusion.

Step Two: Draw and Populate the Grid

The HTML table you created above simply shows an empty grid. Next we will write the JavaScript necessary to put something in it! This will be done with three functions: freshGame(), updateDisplay(), and updateGrid().


This function initializes the variables we will be using. You may ask, “Why bother to put this in a function instead of just writing a script at the top of the page?” Good question! The answer is because we will want to have a “restart” button later, so we need to be able to re-initialize the variables at will. Fortunately, this is simply a bunch of variable declarations all at once, so the code is quite simple.
Tic-Tac-Toe sample code
(click to enlarge)

What do all these variables do?

  • player keeps track of which player’s turn it is. It will either be “X,” “O,” or “blank.”
  • winState keeps track of the “state” of the game, which will change as time goes on. We are giving winState a numerical value here: 0 is a new game, 1 is a game that has started but not finished, 2 is a game that somebody has won, and 3 is a game that has ended in a draw. We could have used text values for these instead– which would be a good practice in a more complex game with a lot of potentially different gameplay states.
  • grid is an array that keeps track of the contents of each cell. At the beginning of a new game, all cells are “blank,” meaning they have not been claimed by either player. There are nine cells, therefore nine slots in the array– but JavaScript arrays start at 0. To make it easier to mentally match cells with their values, the cells have IDs of “cell0,” “cell1,” “cell2,” etc.

TIP: At this point, the script has not chosen which player goes first, creating a “blank slate.” It might be tempting to choose who goes first here since you know that’s going to be determined randomly. But what if you decide later that players get to choose who goes first? Generally speaking, it’s good practice for every function to “only do ONE thing,” and in this case the one thing is “initialize the page.”


“Display” here refers to the message at the top of the game that says “You go first, Player ___” or something similar. What is shown there depends on the value of winState, and so what the function does will be chosen with a switch statement.
Tic-Tac-Toe sample code
(click to enlarge)

  • Case 0 is a completely fresh game, which means that no player has been chosen yet! But it’s not this function’s job to choose a player– that job gets kicked to a new function we will have to write later, called choosePlayer(). Right now we don’t care what choosePlayer() does, it just needs to tell us who the player is. Once that’s determined we display a message telling the player that it’s their turn. And now that the game has actually started, we will update winState to 1, or a continuing game. That’s how it will stay until someone wins or we run out of empty cells.
  • Case 1 is a “normal” turn. Nobody has won but the game is not over, so we just tell the current player that it’s their turn.
  • Case 2 is that somebody has won! Besides a little victory message, we want to do a couple of things. First, we want to display a button to create a new game in case the players want to play again. Second, we want to redraw the grid to hide all the other buttons so the players don’t just keep pointlessly clicking buttons. As with choosing who goes first, above, those actions are beyond the scope of this block, so we’ll send them to the displayNewGame() and upDateGrid() functions, respectively, which we will write later.
  • Case 3 is a draw– all of the cells are filled, but there’s no winner. We’ll update the alert message and show the new game button with displayNewGame().
  • Default is a catchall, which in the case of this game there should never be a reason to see. But it’s a good idea to have something there just in case the unexpected happens. So we’ll just show an error message and call displayNewGame() to start over.

TIP: The function is called updateDisplay(), but the <p> tag we’re sending the message to has an ID of “gameState”. It works, but could it be clearer? Should the <p> tag have an ID of “display”? Or should the function be called updateGameState()? A consistent naming convention will make your code easier to read.


This is the function that populates the table, which it does by looping over the array grid, looking to see what should be in the table cell with the corresponding ID. So for example, if our table and array look like this:

Index 0 1 2 3 4 5 6 7 8
Cell ID cell0 cell1 cell2 cell3 cell4 cell5 cell6 cell7 cell8
grid “blank” “X” “blank” “blank” “X” “O” “X” “O” “blank”

…then our grid should look like this:
Tic-Tac-Toe sample screenshot
(click to enlarge)

So, updateGrid() is going to have two major parts: a for loop that starts at zero and counts a number of iterations equal to the number of slots in the grid array, and a switch statement inside the loop which looks at the value of the current array slot and fills the table cell accordingly.

At this stage, we don’t yet know how the values in grid get changed, but we don’t really need to know that yet either. All we need to know is what the possible values could be. freshGame() sets them to “blank,” so we know that’s a possibility. If the value is blank, we want the players to be able to click a button to claim that cell.

We also know that the players are either “X” or “O,” so those are possible values for grid as well. Furthermore, we know that when someone wins the game, we’ll want to display a “You win!” message instead of a clickable button.

TIP: We don’t need a value for the draw condition. Why not?

Tic-Tac-Toe sample code
(click to enlarge)

  • Cases X and O are simple enough: either player X or player O has claimed that cell and so it shows their label.
  • Case “victory” shows up when somebody wins the game– but we don’t have any code in place for that yet. When we write the code to update the values of grid we’ll have to remember that “victory” is what goes into the grid array here!
  • Default is what we want to have happen when nothing else does. In this case, that means drawing the buttons players press to claim a cell. The button will call a function, which we’ll call advanceTurn(), and that function will need to know which cell is being claimed, so we’ll send it a parameter with the current value of our loop index. (Note the variable closure ” + i + ” in order to tell JavaScript “the current value of i” rather than “the global value of i”.)

Step Three: Actually Play the Game

So far, we’ve built a grid, populated it with default values, and told the game how to behave when the grid buttons are clicked. Except… the script doesn’t actually know how to do most of that stuff, because it’s been shoved off on support functions. Oops. Let’s start writing those, shall we?


This function is our game’s big workhorse. When the player clicks to select a cell, advanceTurn() assigns that cell to the player and checks to see if the game continues or there is a winner. If the game continues, advanceTurn() switches players, but either way it then redraws everything and patiently waits for the next click.
Tic-Tac-Toe sample code
(click to enlarge)

For all that work, advanceTurn() is actually quite small. It takes a parameter of which cell is being talked about, finds player in the global scope, and does its magic. However…

TIP: Remember that functions should only do one thing? If we assume “run the turn” is one thing, advanceTurn() as written is actually doing three. It works, but it’s not the best way to do it! How about something like this…?
Tic-Tac-Toe sample code
(click to enlarge)

That’s an advanceTurn() function that only does one thing: advance the turn. It means creating two more new functions than we’ve already got, but when you’re building enormous scripts to handle very complex games, it’s a lot easier to fix a single broken function than it is to track down a bug buried in the middle of three other things. For something simple like this Tic-Tac-Toe game, it may seem trivial, but you might just be amazed at how complex your code can become very quickly– and how easy it is to forget what those 20 lines you wrote yesterday were supposed to do. Writing the assignCell() and changePlayer() functions we’ll leave as an exercise for the reader.

checkWinstate() and checkWinner()

All this grid-populating is great, but none of it means anything unless somebody wins the game! Or at least, the game ends in a draw. A player wins when they have selected all of the cells in a row, in a column, or diagonally across the grid. But the script has no idea what rows, columns, or diagonals are… so we have to tell it.
Tic-Tac-Toe sample code
(click to enlarge)

We start from the assumption that the game will keep going unless there’s a reason not to. (That’s determined by our old pal winState, which spends most of the game with a value of 1.)

Since JavaScript can’t really handle complex comparisons, we’re going to send most of that thinking to checkWinner(), which takes any three spots on the grid and sees if they match. Then all we have to do is see if anything sent to checkWinner() comes back true. If it does, somebody won!

If checkWinner() comes back false, there are no winners. That means the game keeps going, right? Well, no, not necessarily. There might not be any more blank cells, which is what the else block of checkWinState() is looking for.

After everything in this big chunk of code finishes, it’s entirely possible that every test came back false– in which case, winState is still 1 and the game just keeps on going.

TIP: There is a lot of repeated code in that first if statement. Could that be cleaned up? Possibly with an array of winning combinations? What would such a thing look like?

Everything Else (The Support Functions)

This is your game’s toolbox of miscellaneous functions that don’t perform the critical functions of playing the game, but keep other parts of the code nice and neat.
Tic-Tac-Toe sample code
(click to enlarge)

TIP: Remember the “victory” case of updateGrid(), and that we didn’t know where it came from? Here it is, quietly lurking in clearCells(), which is in turn a support function of checkWinState(). clearCells() goes through and changes every “blank” entry of grid to “victory” so that when advanceTurn() calls updateGrid() the buttons will automagically go away. Following these strings of logic is a skill you will want to develop to become a really good coder.

You’re Done! What Next…?

So we’ve got a working, playable Tic-Tac-Toe game! It probably won’t win an Origins Award, but it’s still pretty neat in its own little way. But how could you make it better? How about…

  • Graphics and Sound. How about making the game look like it’s on a stone tablet, with the sound of rock-scraping-on-rock when you click a button? How about a fanfare when somebody wins– or a sad trombone when the game is a draw?
  • Cats vs. Dogs. Instead of X or O, you could have anything. How about a cat’s head for X and a dog’s head for O? Or maybe a player’s name and user icon.
  • Connect Four, Reversi… Battleship? There are lots of games based on selecting points on a grid, and the way the grid changes when that selection is made. As the grid gets larger, just counting from 0 to “number of squares minus one” might become clunky. Maybe implement coordinates? The possibilities are endless.


The Feminine Mind (Suburban Jungle and My K-On! Obsession, Part Four) Thu, 06 Apr 2017 02:26:20 +0000
Source: K-On! Wiki

It was The Secret of NIMH that made me realize men were boring.

I mean, men can have their uses, and a few of us are marginally clever, but it wasn’t until The Secret of NIMH that I began to feebly catch a glimmer of the quantum differences between life as a man and life as a woman, even when dealing with the same things. [1] And from that point, women began to dominate my writing, and my reading too, when I have the option.

There are exceptions; NeverNever was theoretically about Arthur and Col. Beowulf (although the strip didn’t really come to life until Mopsy showed up, and I don’t think that’s an accident). Greg has sliiiiightly more focus in the Brigid and Greg fictionlets. Michael Macbeth had a long run as a character I kept trying to write about. But compare them to, say, Tiffany Tiger or Verity Anjo, and it’s probably easy to see where my creative interests lie. And as a general rule, in any given group, I gravitate towards and generally feel more kinship with the women.

I have been told that I write women characters well, for which I’m grateful. As much as this is true, beyond the obvious “write about human beings, regardless of their gender,” I suspect comes mostly from simply shutting up and listening to what women say, not just in public discourse, but also (and more importantly) to each other. This latter can be hard to pull off in daily life– women’s behavior changes when there’s a man around just as much as men’s behavior changes when a woman is– so I do it mostly by reading things written by women for a female audience. Doing this took me a long time to get used to, as I had to overcome a lot of social programming designed specifically to prevent it. But it has also taught me many, many things.

At a certain point, however, there are barriers I simply can’t cross. I know what muscle cramps feel like, and I know how changing brain chemistry can send my moods all over the map but I’ll never have a period or PMS. I can use my imagination to picture being shorter, lighter, and more flexible, but at the end of the day I will always be 6’2″ and one of the largest people I know. I know what it’s like to have people randomly dislike you or discount your opinion for no good reason, but I don’t get told I’m “dominating” a conversation when I’ve said one thing for every four things said by someone else.

I think about this sometimes when I’m working on Suburban Jungle. I know I have women readers, but if I had to guess I would assume that my readership skews mostly male. Certainly, there is a tendency among some of my readers to want me to, as the saying goes, “cater to the male gaze.” This isn’t just things like wanting pinup poses or playing up the sexualization of any given situation (although there is certainly that), it’s also pressure to reinforce stereotypical gender roles such as wanting the men come to Charity’s rescue or attacking Langley for being “too bitchy.” It might not be male gaze so much as “want everything to fit into comfortable traditional pigeonholes” gaze, I suppose… but whatever it is, I can tell it’s out there.

I also think about a comment I read online somewhere about K-On! which strikes me as relevant. The comment, left on a review somewhere I have long since lost the link to, was that it was nice to have a show about girls that actually felt like it was about girls, and not just some guy writing his vague idea of the sort of things girls do and repeating all the usual things that sort of scenario usually leads to.

There’s a reason for that, of course. Despite being a show about high school girls, K-On! was originally created by a man for a primarily male audience. What made the K-On! anime a commercial success in Japan, and arguably one of the reasons why it is so much better than most of the other shows of its type, was that it was made by Kyoto Animation, a studio comprised largely of women, who added all that other stuff and gave the show tremendous crossover appeal. In short, K-On! was popular with women too, not just with the stereotypical moe-fan otaku. And when women get behind a thing, they go big. 😉

Charity is finally part of the gang. <3

And really, if I could arrange it, that’s the kind of reaction I’d want people to have to Suburban Jungle. Someone once told me that despite the obvious fantasy elements “When Wally Met Mikey” from the original SJ was the most realistic depiction of a fledgeling gay relationship he’d seen in a comic– which made me very proud. I don’t know if I can hit that level again with Charity and her friends, but it is the target I’m shooting for. And among other things, that means pushing past comfortable traditional pigeonholes, and being as true to the “reality” of the characters as I can.

-The Gneech

[1] See also Scalzi’s discussions of “straight, white male is EZ mode.” Not that it’s all sunshine and roses– being male in our society is a lonesome and painful business, as Norah Vincent so powerfully demonstrated. But on the grand scale of life, not being able to talk about your feelings or wear attractive clothes and constantly having to fight the effects of testosterone poisoning, don’t quite stack up to being in constant (if usually low-level) fear for your life and having to work twice as hard for 2/3 the pay and recognition. And also, any woman over the age of 12 is more badass than most men ever have to be. Ask anyone who draws blood for a living. They’ll tell you.


Moe Cheegers and Genki Wolf Girls (My K-On! Obsession, Part Three) Sat, 25 Mar 2017 18:07:21 +0000

In 2014, I missed Suburban Jungle so much that I decided it was time to return to it. But I couldn’t just pick up with Tiffany, Leonard and the crew seven years later. Tiffany’s story was finished, and as she was the star that the rest of the comic orbited around, there was nowhere for it to go except to just sort of string along as a zombie franchise. So I decided instead to for a “next generation” idea, and Rough Housing was born.

I freely admit, I had very little idea what I was doing with it at first, so I just tossed in a bunch of things that I liked and figured it would gel. Possibly not the best way to start a new project, but it was also true of the original Suburban Jungle and that seemed to go fine. My initial vision for Rough House was a lot more pure OTT zaniness and parody. Issue two pretty much exemplifies this, with the S.S. Plot Device and “The _______ of Cangrejo Diablo!” being typical of the kind of jokes I had in mind.

But for whatever reason… I just didn’t love it. Scripting was constantly a chore and instead of wacky hijinks I kept wanting to write shippy or emotional moments. By the end of issue three and well into the scripting for issue four it would be fair to say that Rough Housing was having an existential crisis behind the scenes. This resulted in the scripting for issues four and five taking forever as I wrangled with it.

I knew from the beginning of the “Best Bodies Contest” arc that the big payoff moments were Parker getting up on that stage, and Leonard’s final decision. But I also clung to the idea of wacky hijinks, envisioning lots of sabotage at the contest, Charity doing ridiculous things to stall Leonard and Morrison, and so forth. But while the emotional moments flowed quickly and easily, for the hijinks I ended up with whole pages of script that said things like “FUNNY SCENE HERE.” Fortunately I was able to lean on my wit to come up with gags on a page-by-page basis, but it was a frustrating way to run a railroad.

But as I was working on issue five, two important things happened. First, I began streaming my art sessions, enabling me to get real-time feedback from some of my most engaged readers and see what they responded to and why. Second, I was watching and falling in love with K-On! and examining how I responded to that and why. And when I spotted the overlap, everything clicked.

See, here’s the thing: K-On! hits the sweet spot perfectly. At its core, it’s a remarkably subtle, character-driven story about connections, loss, savoring the moments of life, and so much more– but it sneaks all this past you by being adorable and laugh-out-loud funny. But the humor isn’t the GIANT MONSTERS ATTACK humor of Love Hina or Sgt. Frog. The girls spontaneously forming a cheerleading squad for Ritsu as she tries to eat a receipt they don’t want their teacher to see gets me every time, but it’s also a completely realistic moment.

This was the eye-opener for me. The original Suburban Jungle was very comfortable with the GIANT MONSTERS ATTACK style, with its very tenuous fourth wall, aliens hiding in the sun’s corona, and all that jazz, but when people talk to me about it today, what do they talk about? How Tiffany, Drezzer, or Leona impacted them personally. The connection they felt to Mikey and Wally. How they identified with Dover’s codespeak.

The people in my streams, similarly, talk a lot about how adorable Charity is and wanting to give her a hug, being proud of Parker’s overcoming his fears, or how fun it is to see Rufo wanting to make out with anything that moves.

In other words, the parts that were coming the most easily, are the parts that work the best anyway. XD So! Lesson learned.

Langley and Ritsu... separated at birth?

Langley and Ritsu… separated at birth?

The influence of K-On! has already worked its way into rewrites and page layouts. This Langley/Rufo moment, for instance, was not in my original script. It was inspired by the chemistry between Ritsu and Mio and tossed in to spruce up an otherwise dull page, but it’s just as great a moment for these two goofballs.

But the lessons I learned from K-On!, and the realizations I made about Rough Housing along the way, are going to have big repercussions moving forward. Issue six will see a shift away from “this issue’s funny premise”-style writing to focus more on the characters’ goals and fleshing out generally. I also hope to move away from being quite so much focus on Charity to being more of a proper ensemble with stories about the rest of the cast. (Who is Bounce? What does he do all day? What’s the deal between Langley and Rufo?)

This may lead to eventually changing up the cast somewhat, if existing characters aren’t working or new characters might work better. We’ll see. Rough Housing is sure to evolve over the next issues, but I finally feel like I understand it now. Giant monster attacks and wacky hijinks are not and were never going to be the strength of this comic, and really aren’t the strength of my writing generally. It’s the characters and connections, and the humor that naturally arises from them, that will make or break it.

Giant monster attacks may still show up from time to time, who knows? But where before I was saying “A giant monster attacks! What do the Rough Housers do?” I’m instead going to start with “The Rough Housers want X. How does that pan out?”

You’d think after being a writer for thirty-mumble years, I’d have learned that lesson by now. I guess I just need periodic reminders.

-The Gneech