Sunday, March 10, 2019

Space Farm devlog 11

After a bit of a hiatus, I'm back with a fun post.  I'm making the Space Farm repo public!  Find it here:


The reason?  I'm pivoting away from my initial design towards more of a farming/ RPG hybrid that an actual game designer is helping me with.  Much of the code I've put together can be reused, but I'd like to save this little snapshot of Space Farm before I start tearing things apart to build RPG Farm.

I'm hoping someone somewhere will benefit from my code, as little as there may be.  To help y'all out, here's a features list:
  • Basic 3D isometric movement (which I borrowed from someone else...) with grid-locked mouse interactions
  • A limited-size inventory system with rudimentary UI functions
  • Plants that grow over time, drop items when harvested, and can be reset to specific growth phases as desired
  • A framework for a crafting system using JSON
  • A work-in-progress "auto-farm" system where players can define a rectangular space that will automatically generate farmland (planting and harvesting were up next, but I don't think I got there yet)
I know I should stop being impressed by myself, but it sure feels like I got a lot done.  Hopefully in the near future I will add more, but so long for now, Space Farm.  May your spin-off actually turn into a complete game this time!

Extra details


Images: here's a link to the most interesting work-in-progress .gifs and images, gathered into one imgur album for easier access.

Demo: here's a dropbox link to a demo!  Please note that at this stage, I am still relying on the console output as feedback that things are happening as expected, so it might be hard to know what's happening without those logs.  Controls are WASD to move, , and . to scroll through your hotbar, Q to open and close player inventory (and close chest inventory, for some reason), left-click to use your selected item, right-click while mousing over a chest to view its inventory, and shift-right-click to put items into and out of the chest.  You'll need to dig up dirt and then both till and water it before seeds will grow.  Give the auto-farm a try by placing the skinny poles in a small rectangle!

Thursday, June 14, 2018

Space Farm devlog 10

This update is all about plants!  I've been neglecting them since I felt like I got so much done last time I touched them, so here's a few much-needed features.

When I added seed bags, I had them default to a turnip plant, which felt like an appropriate first crop to add to the game.  Unfortunately, I simply hard-coded it to plant a turnip when used, so in this work session I changed the code to actually create the type of plant defined in the inspector window.  For some reason this changed the collision relationship between plants and their parent dirt block, so I had to redo a little bit of my code for detecting which block is being hit when the player clicks.  The end result is I can now more easily create a seed bag for each unique plant I add to the game.  Nifty!

In the process of working on seed bags, I went ahead and added plant prefabs to the Resources folder alongside the tools, blocks, etc I moved earlier.  I'm not entirely sure I needed to do this, however, as the seed bag is currently taking a drag-n-drop prefab input for which plant to grow.  I'm imagining at some point I'll rework this to remove the drag-n-drop requirements by converting the name of the seed bag into the corresponding plant name and attempting to load based on that new name, but that also seems a little unnecessary right now.  I'm putting it on the back-burner and will come back to it later.

Last but not least, I added some more functionality to the existing plant growth stages code.  Previously, after harvest every plant would just revert to the "just been planted" seedling state and regrow.  Now I can choose which growth stage a plant can return to after being harvested, if any.  This ended up being difficult mostly because I had forgotten how my old code worked.  I'm using four different variables to decide if a plant can move on to its next growth state: current game time (Time.time), growth stage time, growth start time, and elapsed plant growth time.  It's a little fuzzy in my head still, but the equation comes out to be as follows:

If current time > the starting timestamp + how long the plant's been growing + how long it should stay in this stage, then move on to next stage

When I tried to have a plant start in a new stage after harvest, the elapsed time variable threw me off.  When a growth stage is complete, the elapsed time variable is incremented by that stage's growth stage time variable.  For a while there, I had it programmed so plants were taking as long to grow from any stage as they would have from a seedling because I was using that elapsed time variable wrong.  It no longer needed to care about how much time should have elapsed to reach this stage, just how much time had actually gone by relative to the growth start time, which I was already resetting to Time.time after harvest.  As I'm trying to write this out, I'm realizing I can make this a little cleaner by combining the start time with the elapsed time to make one variable that's the timestamp of last growth:

Timestamp of last growth + how long it stays in this stage = timestamp at which it moves to next stage

Wish I had thought of this while I was working the other day!  I'll put a new task in my Trello board.  Thanks for being my rubber ducky, internet friend!

Speaking of my Trello board, I've made a new category I can drop cards into called "things missing art" so I can better see which tasks are pending which type of work.  A couple of my categories got pretty empty when I made this change, which helped me see what actually needs to be started next in a few places.  As a result, I've groomed a couple more features that I'll likely work on next time-- one for item and inventory management, and one for farming.  Yay!

Sunday, June 3, 2018

Space Farm devlog 9

I've got some fancy gif progress shots for you this time!  For the past week, I've been working mostly on the GUI and inventory functions, and I think I've gotten a lot done.

First, the hotbar:


Woo, hotbar!  Now I can kinda sorta see what item I have selected for use.  Well, once I get more icons in, at least.  The code for this is a little hairy.  Specifically for the player's inventory, any time the inventory is updated I split it into two arrays-- one for the hotbar, and one for the rest of the inventory.  These two arrays are used solely for updating the GUI, so I don't have to do any weird swapping around when it's time to let the player move things between them.  And as the gif shows, everything gets visually updated correctly when you place down or pick up an item.

I've also started on functionality to let the player pick up blocks again once they've placed them.  Right now, the player can pick them up by hitting them with the mattock three times.  This one I'm kinda proud of-- I added a little "decay" timer for the counter that tracks how many hits a block has received, so they'll have to hit it three times in a 10-second window to actually pick it up.  This is in case the player just hits it by accident every now and then, like I am prone to doing in these sorts of games.

My future goals for item dropping involve an intermediary step, where the object is dropped into the world as a floating item the player can choose to pick up by either clicking or walking over it instead of just automatically cramming it into their inventory.  I haven't picked which method to use yet, but I'm leaning towards walking over to avoid adding too-specific of controls to the interface.  I'll have to sit down and map this feature out before I can really get started on it, regardless.

In addition to these features, I've done some light refactoring and code clean-up during the times when I want to work but can't really get anything big done.  I reworked my inventory manager class to hold an array of inventory items instead of just game objects, which improves readability by getting rid of lots and lots of "get component" calls everywhere.  I also did a little code review with a good friend who reminded me that lambda expressions are scary but also beautiful, so a few of my functions have been reduced in length by a good 75% or more.  There's still a few messy spots left to clean up, but they'll also be affected by the item dropping feature, so I'll wait and scoop them up with the rest of the carnage that will likely leave behind.

In the meantime, my "tech debt and bugs" list on Trello has had a few more cards added to it in the past few days, so I should probably get the more urgent of those knocked out before I really get going on any "big" features.

Wednesday, May 23, 2018

Space Farm devlog 8

Hello again!  I've managed to start squeezing in an hour or two here and there this week, which is abnormal for me.  Usually I end up only devoting a few hours of my weekend to Space Farm, if even that, so it's kinda fun to see repro pushes dated "34 hours ago" instead of "2 weeks ago".  Since I've made some little bits of progress here and there, I'll try to keep this update little.

I've finally added a seed maker machine, which has been sitting in my todo list for a pretty long time.  As the name implies, this machine will convert a crop into its corresponding seed.  Code-wise it's relatively simple-- I added a new prefab that copied my sawmill, named it accordingly, checked the necessary checkboxes to mark it a container that can process things, and then dropped in a recipe for turning turnips into turnip seed bags.  At this point I'm not sure if it should continue using manually-created recipes or if I can make it "smart" enough to grab the crop's itemID and convert that into the corresponding seed bag's itemID.  It seems like a nifty change to make, but I might want to have some crops that you can't make seeds for-- that will be a design decision for future Caitlin.

I also took a few minutes to add in support for multiple output items from recipes.  I had been putting this off because it sounded scary, but it ended up being pretty trivial.  Most of the code was already there but hard-coded to use index 0 of the output item list-- I just needed to add a for loop that would cycle through the entire list.  Took like 5 minutes.

On the topic of recipes, adding the turnip seed bag recipe showed me pretty quick that my fancy recipe loading code could only handle one recipe, not multiple.  As I subtly alluded to in devlog 5, I was not super confident about blindly copy/pasting code from a tutorial, so I half-expected to run into this very issue once I added a second recipe.  After a bout of clicking on the same Google results over and over but not understanding what I was reading, I realized the issue-- I was trying to treat the JSON data as an array of recipes, but I didn't actually define its class as an array, but rather one single recipe.


Hopefully the commented out code can help you see what I mean here.  Originally the top class was just "RecipeData" and contained the commented out code.  This meant that when I read the JSON into a RecipeData object, it tried to cram the file into one RecipeData object.  This works fine when there's only one in there, but the editor got really confused when it found more data in the file after that.  To remedy this, I updated the top class to be a RecipeDataList class, and had it contain a list of RecipeData classes.  Now I read the JSON into a RecipeDataList object and it's perfectly happy to do so.  Having a class that has a list full of other classes which also have two lists of additional classes each makes my pea brain hurt, but it seems to work.

After getting all of the above checked in, I realized that my codebase was littered with a lot of junk, such as old commented out code and todos that had long since been completed.  I took some time to hunt through my classes (with the help of Visual Studio's fancy task list window that will look for standard "to do" comments and add them to a list for you!) and tidied up.  It feels a little like busywork at this point, but 15 minutes here and there will probably save me hours of clean-up later on when I can't remember what on earth that todo item was supposed to mean.

Unfortunately I still have a healthy bit of design decision paralysis going on, so I'll probably continue on with the little tasks in my Trello board for now and play some games for "research" in the meantime.

Monday, May 21, 2018

Space Farm devlog 7

I've been putting off writing this post because I'm not super proud of my most recent progress.  It's pretty messy and I have pretty much no idea what I'm doing.  I'm talking, of course, about UI.

UI graphics are courtesy of Kenney NL who is doing a wonderful thing by giving dorks like me access to some really nice art.  Visit his site here.


Yep, that's my player inventory as of my last code check-in.  I only got this far after hours of trying to follow a tutorial video series (why are they always videos?!) but getting distracted by the dogs every 10 minutes.  Ugh, I'm stressed out just thinking about it.

It looks pretty darn funky, but it does a couple kinda neat things already-- it can load icons based on the item (or lack of item) in a slot, as well as display the number of items in the stack in that slot.  It can also be opened or closed via button press.  The UI element itself is made up of a couple layers of panels and then some prefabs for the item slots.

The idea here was to have one version of the element that could be used by all the inventories in the game, but I'm already finding design flaws in this approach.  I'll likely end up using this more as a template for future inventory screens, assuming I keep any of this mess at all.

In the meantime, I've been trying to sort out some overall game design questions I've left unanswered for a little too long.  I need to get something nailed down for a core gameplay loop so I can build it and see if it's any good, but there are a few different directions I could take this basic "farming game but in space" idea.  I just might have to go play some of my inspiration games for ideas!

Sunday, May 6, 2018

Space Farm devlog 6

I'm not quite sure how frequently I should update this log, so enjoy a relatively short post while I try to figure that out!

As mentioned in devlog #5, I recently updated my prefab management process to allow for easier loading via script.  So for this work session I focused on cleaning things up to work in this new system.  Almost all of my prefabs are now in the Resources folder and renamed to use a standardized naming convention that I hope I won't decide to change again later.  The exceptions here were the things I'm not sure how I'm going to handle yet, namely the plants.  I'm assuming I'll eventually follow the same process I followed for items, but I'll save that for another time.

I found a couple interesting features of the Inspector pane during this reorg.  The good-- renaming and moving the prefabs in my Projects pane did not seem to break the links that already existed in the Inspector.  Hooray!  The bad-- I cannot for the life of me figure out how to reset just one field of a prefab back to the default I added in the code.  I can reset the whole thing, of course, but that's kinda overkill when I just want the "recipe name" field to update on my Sawmill prefab.  I struggled to Google the issue, as the keywords picked up a lot of similar-but-not-quite-matching forum questions.  However, the Sawmill is the only building that can craft things right now, so it's not exactly an urgent matter.

My Trello board is starting to fill up, and many of the old cards are tagged as "art" and "UI" tasks.  I'm still not sure how I ought to handle art-- hiring out sounds wonderful, but it's early enough in the project that really spending time or money on legit models seems a little silly.  I'll probably have to just keep suffering through my "I spent 30 minutes in Maya throwing something together" programmer art for the foreseeable future.

Monday, April 30, 2018

Space Farm devlog 5

Oof.  It's been a while since I've written a devlog thanks to 2018 being so... busy so far.  I got some stuff done before taking a break from Space Farm that I hadn't written about yet, so I'll go ahead and cover it here alongside the stuff I got done this weekend.

This post will give a brief overview of the new inventory system, how I'm going to start managing prefabs, and my work-in-progress crafting system.

Inventory!  This one is usually the stumbling block that derails my projects, but I managed to power through it this time.  I put together a relatively simple inventory manager class that I can just drop on any game object that needs to hold stuff.  As a companion to the manager, I've added an inventory item class that I'll be attaching to any object that can exist in the game and also in the player's inventory.  This means my manager can hold an array of "inventory objects" that have data about their quantities, quality level, stack size, and so on while also holding all the info I need to place that item back in the world.  Doing it this way required some elbow grease initially, as I had to go in and update all my prefabs to have both a world object class and an inventory item class, but it's been pretty straight-forward to use since that point.  It's helped standardize what's going into the inventory and reduced the "cast to this object" kinda code I had floating around everywhere.

My main gripe with my inventory manager at this point is that it has a lot of functions already.  I have functions for adding new items, removing items from a specific index, checking if there's already a stack of a specific item forming, checking if there's even room to add more items, and sorting the mess of items once they've been added.  And the weirdest part is when I realized I had all these functions but didn't have a means of taking a specified number of an item out of a stack, like it hadn't occurred to me while writing these other dozen functions.  I'm wondering how many more there will be-- I might have to come back and refactor this class before too much longer.

Prefabs!  I like prefabs now that I've figured out how to use them.  Unfortunately, it's easy to find yourself buried in prefabs when you're working on a game that will have a lot of different items, tools, and buildings.  As per my inventory changes, everything that appears in my game world is now a prefab with a world object class and an inventory item class attached, plus the other fun stuff game objects need to exist.  And any time I need to instantiate a new game object via code, I've been having to expose a variable in the inspector pane so I can drag-n-drop a specific prefab into a script.  This didn't seem too bad until I had more than one tool and realized I had to attach several prefabs to my player just to give myself the items I was trying to test.  I kinda pushed this problem under the rug until I got started on crafting and realized it'd be impossible to implement my solution with drag-n-drop prefabs everywhere, so I took to Google.  Luckily I found a relatively simple-sounding solution-- Unity has a Resources.Load function that can be used to load up a prefab by name.  It sounds like there may be some concerns about this method's efficiency, but it's an easy solution that I'll go ahead and use until I find something better.  It will take another round of changes to many of my scripts and prefabs, but the pain should be worth it if I can get crafting up and running as a result.

Crafting!  Yes, I decided to bite the bullet and start on the crafting system.  Like the inventory system, this was uncharted waters for me, and I'm pleasantly surprised I didn't run head-first into an iceberg.  I decided to use JSON despite being completely unfamiliar with JSON beyond knowing people use it for lists of stuff in Unity.  Luckily there's a Unity-sponsored tutorial on the topic that helped me get it up and running, so I created a JSON file to hold the crafting recipes.  Each recipe has an array of required inputs and their quantities, an array of outputs and their quantities, and a base crafting speed.  I'll be using the tutorial's nifty editor window class to add new recipes to the file over time, though I may need a more robust tool in the future.

To use the crafting recipes, I have a game object set up to load in all the JSON data at the start of the game so my buildings can simply request recipes by name as needed.  At the moment, I have buildings set up to check if they can make one of their recipes any time they receive an item, assuming they're set to automatically craft stuff.  If so, the code will check the building's inventory for all the items the recipe needs as input and make the new item if everything's there.  When I write it out like that it doesn't sound very complicated, but putting it together was a bit stressful-- I had to make some changes across a number of scripts before I could even really start testing the code I was writing.  Luckily there doesn't seem to be any goofy bugs... yet.  The next step will be to add more recipes and see if I can get a building to check more than one when an item comes in, so we'll see how that goes!