Sunday, November 27, 2016

Harvest Booze Update #5: Grass!

Ok, grass. No sweat, bucko, just throw some green squares down & call it a day, on to bigger shit.

It looks sort of ... what's the word ... stupid?

Well, fuck. That kind of seemed like it would work. After a brief  "Christ, who am I kidding" panic & a couple of beers, I stepped calmly back to the drawing board. Sure, this looks like shit. Let's figure out why & let's fix it.

First, grass just doesn't grow like that; I can't drop single patches randomly. That method works fine for the trees, because that's kind of how trees grow; as an individual plant in competition with it's neighbors for resources. Grass grows in patches, though, spreading outward when it can. My first idea for generating random grass patches was this recursive algorithm:
create_grass_patch(x, y, patch_size) {
    Create a grass patch at (x,y)
    If patch_size > 0, then with each adjacent dirt_tile:
        With some chance (maybe 50%?):
            Call create_grass_patch(dirt_tile.x, dirt_tile.y, patch_size-1)
          }

Now, I'm not the type of dude who just whips up recursive algorithms, so I was as surprised as anyone when this happened:


Here I'm generating 10 random patches of increasing size just by increasing the patch_size variable by 1 at a time. So far so good, but it still looks really flat. Maybe we can generate grass blades kind of like how we did with the tree leaves?


Alright, not bad! Another performance drain for another day, but not bad, otherwise. It still looks weird, though, the edges are all squarey. But wait, these games always happen on grids, right? How come everyone else's squares look so much better than mine? Here's why:

Elder Statesman Harvest Moon (SNES)
If you look closely, the grass squares on the outside edge of the patch aren't quite squares; the edges are sort of ragged, letting the dirt show through. I chose the above screenshot because, you know, Harvest Moon, & those cows are fucking adorable but this isn't, like, a Harvest Moon thing; tons of games do this, I just never looked that closely. So this means we need a bunch of sprites for the different ... edge cases (har har), and we also need to make the grass smart enough that it can look at the neighboring grass tiles to figure out which sprite it should use. But most of the different edge pieces can really be the same one, just rotated differently, so I only need this little sprite sheet:



It's kind of hard to see, but there are six tiles there; the pink parts are actually transparent & the rest will be colored programmatically. It was a little tedious, but not really difficult, to make the grass smart enough to choose it's own tile. It can decide which tile to use by counting the number of adjacent grass tiles, then it chooses the rotation of the tile by looking at which sides those adjacent grass tiles are actually on. And, voila:
IT'S GRASS!
We're back down to running at like 2 frames per second, but I think it looks pretty good. Apparently every small victory is going to be followed by a grueling round of code optimization, so I guess that's what I'm doing next!


Wednesday, November 23, 2016

Harvest Booze Update #4: Game Optimization 101

Remember how I thought that drawing all of those leaves individually might be a bit of a drain on performance, but whatever, I'll just deal with it later? This is just painful:

Just don't worry about the acorn numbers?

Yeeeah, check the (low)-single-digit FPS in the upper left there. Turns out I've got to deal with it now.

Quick side note first, I love how huge these trees are. Trees are always way too small in games. These guys are big enough to make it feel like you really are a little dude in the woods. I'm into it.

Anyway, the first problem is that GameMaker draws everything that it knows about, many times per second, even if the thing it's drawing is outside of the screen. A single line of code in the tree's draw event stops the game from drawing it when it's outside of the player's view. We see a pretty huge performance gain here:

Also don't worry about how he glitches through that tree at the start.

Still not good enough, though. The game is supposed to update 30 times per second, so any FPS below 30 is slow. And, like, we have a shitload of stuff to add to this game, still. It's just fucking dirt & trees! I'm playing on a mediocre laptop & performance takes a hit from the screen recording software, but still.

At this point, I wasn't really sure what to do. I knew that the problem was that I was drawing a million leaves, but I didn't want to compromise on my original plan & I was liking the way the trees looked & Ok, actually I just didn't want to redo shit. A little bit of research led me to GameMaker's surface drawing functions, which, as it turns out, are super useful. GameMaker calls the thing that it's drawing to a surface; this is, by default, the gameplay screen. But you can instead draw to another programmer-defined surface, basically a virtual canvas, and then draw that surface to the screen whenever you want. So instead of trying to draw a million leaves while calculating their color, rotation, coordinates & scale 30 times every second, I can draw all of that just once to a surface, then draw that single surface, with it's single color, rotation, yadda yadda, 30 times per second. That's like, at most, 1% of the work we were doing before. Each leaf clump has about 100 leaves, and the tree is doing a handful of calculations for each one, but by drawing it all to a surface I can skip all of those calculations and just draw one thing. Anyway, it works:

Let me take a moment to point out that masterfully crafted custom mouse cursor & the sick scroll wheel zoom action.

Well, that's better. It's actually 50+ when the screen recording software isn't running. Any gains over 30 won't have a noticeable effect, but that's headroom that I'm sure I'll need later. Like, when the game is more than dirt & trees & a dude. Like, soon, hopefully?

Sunday, November 20, 2016

Harvest Booze Update #3: Trees!

Check out these trees:


I want trees of the same species to look similar, of course, but I also want enough variation to keep things from looking too copy & pasty. I also really don't want to draw a bunch of shit. So all of the above trees (and over 18 quintillion more #NoMansFarm) are procedurally generated from this humble set of art assets:


The game resizes, colors & assembles these pieces on its own whenever it needs a tree. There are a few bonuses to this general method; for one, it means I can animate the tree growing over time by basically having all the pieces start out small & green, then slowly stretching them into the adult tree. Also, since all of the leaves are colored & drawn individually, it should be easy to have them change color naturally in the fall & to drop from the branches individually as winter approaches. I suspect there may be performance-related problems with this approach, treating each leaf individually, but I'll deal with that later.

I think I'll hold off for now on making the trees actually grow so that I can get into some gameplay stuff sooner. I'm going to get rocks & grass into the game, then start working on the inventory & crafting systems. Once we can start crafting tools & collecting wood, I should at least have a nice little lumberjack simulator on my hands.

Monday, November 14, 2016

Harvest Booze Update #2: The Miracle of Time

So I'm working on getting trees into the game, but here's the thing: trees have to grow. That growth is somehow tethered to time. WHAT IS TIME?

Most farming games deal with the problem of things growing over time by just having them grow while you're asleep. So you just need a few sprites for the various growth stages of a tree, and it updates between days, so you'll wake up to find that the oak tree which was a sapling last night is now an adult tree. It's a weird convention, I guess, but it works just fine as long as you force the player to sleep every night. I really want to let the player sleep wherever & whenever they want, though, which poses a couple of problems.

First of all, events in time clearly can't be synced to the player's sleep schedule. There will be good reasons to work during the day & sleep during the night, just like there are in life (e.g. it's pain-in-the-ass dark at night), but I want the player to decide how they spend their time in the game. So, if I stick with my planned sleep system, I won't know ahead of time when a player will sleep or even for how long. I need another way for things in the world to keep track of time. What's more, I need to be able to speed up time when the player is sleeping, so time passing in the game world can't rely on a constant clock or on time passing in the real world like some always-on games (Farmville & so on) do. And everything in the game needs to be on board, marching in sync.

The other thing is, with this system, I can't have just a couple of sprites for different growth stages. I mean, I could, but it would be goofy if a sapling suddenly changed into a mature tree as you were walking by. I could just draw a bunch of in between sprites so the transition isn't so jarring, but, like, what a pain in the dick, I'm not going to do that. Even if I had a program interpolate the in between sprites, I would have to load all of those into the game, which would probably have a noticeable effect on loading times once I have all of the plants finished. So I need a better way.

I've finished a time keeping system which I think solves the first problem. It keeps track of time in the game world, updating a few times per (real world) second to move time along and call an update function which iterates over everything in the game world, letting the trees & everything else know that a minute or whatever has passed. Then the objects themselves, the trees & whatnot, use that information to take care of themselves. I can easily change how many minutes pass per update, so I can speed up the passage of time when I need to. So I have an acorn object in the game now that is born with a "time_to_sprout" property. Once planted, whenever the time keeping system tells it that some time has passed, the time_to_sprout decreases by that same amount. When the acorn sees that time_to_sprout is zero or less, it starts to grow a tree.

That still doesn't solve the problem of how to visually represent the tree growing in a smooth, gradual way. I've got a plan which I think will work, though, so that's what I'm working on now. Next post will either feature a nice forest growing from a bunch of acorns, or a hilarious glitched out mess. Should be good either way.

Thursday, November 10, 2016

Harvest Booze Update #1: A Guy In Overalls Walking Around a Field of Dirt

Well, I'll be damned.


A vast, procedurally-generated field of dirt, mind you (#NoMansFarm).

And don't worry, got the buggy infinite scroll wheel zoom working as well:


Ok, we're having fun again. Better give this dude some glitchy trees to punch, you think? Stay tuned, pals.


Wednesday, November 9, 2016

Project Codename: Harvest Booze

Yeah, haven't been making much progress on Haunted Monster Cocktail Party of Doom. I've got all the excuses locked & loaded, but really, I'm just not having any fun working on it. So I'll get back to it at some point, and in the meantime I'm getting started on something more fun.

Harvest Booze (that's a working title, officially) is pretty much what it sounds like; a Harvest Moon-like focusing on booze production. You'll farm crops for beer, wine & liquor, craft tools & machines, build Factorio-like production lines and manage a little tavern in the woods. I'm pretty sure you're a backwoods-type brewing beer for the anthropomorphic forest creatures, but maybe that will change.

I've been wanting to make a hardcore-ish automation-heavy Harvest Moon-inspired game for a while. I've got a ton of notes, but I've pared the design down to just the booze makin' parts, just to keep the project small enough that I might actually finish it. It's still the "biggest" game I've ever really thought about making. I know myself well enough to be skeptical that I'll make it past the "you're a dude in overalls walking around a field of dirt and you get stuck in walls sometimes and the game crashes when you walk off the screen" phase, but I'm feeling pretty excited to get working on it all the same.

I promise to let you know as soon as I get a guy in overalls walking around a field of dirt.