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!


No comments:

Post a Comment