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!
A place where I share my projects and what I learn while working on them
Monday, April 30, 2018
Saturday, December 30, 2017
Space Farm devlog 4
Alrighty, time to share some more details about how I've been structuring my code. As mentioned in the last post, I've recently added in a few tools the player can use. I'm kinda excited about the way they're implemented, so first I'll cover the tools themselves, and then I'll describe their current implementation now that I've refactored a bit. Disclaimer-- this feels pretty clever right now, but I'm more than willing to admit that it's an experiment that I might scrap for something better later on.
Tools! What is a farmer without farming tools? Right now I have a mattock, a watering can, and seed bags. The mattock will be a multi-purpose tool covering digging, tilling, and chopping. The watering can is, well, a watering can. And the seed bag currently lets you plant an unlimited number of my generic testing plant, but in the future will come in a variety of species and max seed counts.
Ok, the tools themselves aren't super exciting. But maybe the way I've coded them will be. As seems to be standard practice for Unity, I have a player controller class. Right now, this class handles all the button presses. I currently have three tools, which means three unique functions. But wait, I've already mentioned that some of the tools, like the mattock, will have different uses depending on what they're getting used on. This could easily turn into a lot of different functions. Cramming them all into the player controller would be a nightmare, and putting all the different uses for each tool into the tool's own code would be multiple smaller nightmares.
I've chosen option three: have the objects you act on be the ones holding code for what to do when they are clicked on. I'll admit it, when I write it out like this it sounds more like a bunch of tiny nightmares scattered across my entire code base. To try to prevent it from getting out of hand, I've started trying to keep the different classes to a minimum, but give each one a lot of options that can be used when making a prefab to create the unique game objects.
To illustrate, here's what happens if you click on a dirt pile with the watering can equipped: the player controller detects the click, and then tells the dirt pile you've clicked on to run its "get hit with the watering can" function. The dirt block checks to see if it already has its "I've been watered" boolean set to true, and if not, it sets it to true. If there's a plant attached to the dirt pile, it will be told about this new update to its watered status so it can start growing. Essentially, the player's click was passed through every game object connected to the place they clicked on, and anything hit took care of managing its own reaction.
It can get a little hairy trying to track down the path an input takes (or is supposed to take but didn't!) but so far this method has been more help than harm. I guess over time I'll get to see if my opinion changes!
Tools! What is a farmer without farming tools? Right now I have a mattock, a watering can, and seed bags. The mattock will be a multi-purpose tool covering digging, tilling, and chopping. The watering can is, well, a watering can. And the seed bag currently lets you plant an unlimited number of my generic testing plant, but in the future will come in a variety of species and max seed counts.
Ok, the tools themselves aren't super exciting. But maybe the way I've coded them will be. As seems to be standard practice for Unity, I have a player controller class. Right now, this class handles all the button presses. I currently have three tools, which means three unique functions. But wait, I've already mentioned that some of the tools, like the mattock, will have different uses depending on what they're getting used on. This could easily turn into a lot of different functions. Cramming them all into the player controller would be a nightmare, and putting all the different uses for each tool into the tool's own code would be multiple smaller nightmares.
I've chosen option three: have the objects you act on be the ones holding code for what to do when they are clicked on. I'll admit it, when I write it out like this it sounds more like a bunch of tiny nightmares scattered across my entire code base. To try to prevent it from getting out of hand, I've started trying to keep the different classes to a minimum, but give each one a lot of options that can be used when making a prefab to create the unique game objects.
To illustrate, here's what happens if you click on a dirt pile with the watering can equipped: the player controller detects the click, and then tells the dirt pile you've clicked on to run its "get hit with the watering can" function. The dirt block checks to see if it already has its "I've been watered" boolean set to true, and if not, it sets it to true. If there's a plant attached to the dirt pile, it will be told about this new update to its watered status so it can start growing. Essentially, the player's click was passed through every game object connected to the place they clicked on, and anything hit took care of managing its own reaction.
It can get a little hairy trying to track down the path an input takes (or is supposed to take but didn't!) but so far this method has been more help than harm. I guess over time I'll get to see if my opinion changes!
Friday, December 29, 2017
Space Farm devlog 3
I've had a lot more free time lately due to the holidays, so I ended up getting some neat stuff done. I also didn't stop to think about a devlog post until now, so I guess I'll put the small stuff in this post and the big stuff in another one where I can go into more detail.
I took a screenshot this time-- there's stuff to see! The green cube off in the distance is the cursor from my last post. I haven't really made any changes there, beyond tidying up the code. I tend to do a lot of writing lines in and then commenting them back out as I work through problems, so I had some discarded code to delete.
I took a screenshot this time-- there's stuff to see! The green cube off in the distance is the cursor from my last post. I haven't really made any changes there, beyond tidying up the code. I tend to do a lot of writing lines in and then commenting them back out as I work through problems, so I had some discarded code to delete.
Working my way down, the cylinders are my first farm "buildings" which is the term I think I'll use to describe any structure the player places in the world, e.g. chests, machines, decorations. Right now these guys don't really do anything, but the player can put them down under the cursor by clicking.
The little brown squares are my dirt blocks. They have a few booleans on them to control plant growth-- whether or not the dirt has been tilled, if the block has been watered, and if it currently has a plant in it. Using the mattock, which I'll cover more in my next post, the player can click an empty space to spawn a dirt block, and then click the dirt block to till it. The player can also plant a seed in tilled dirt, and then water it (again, more on those tools in the next post). It sounds a lot fancier than it is, really-- just a bunch of if statements. I also got the game object to change materials when tilled, which really tickles my fancy for some reason.
Finally we come to the plants themselves. Here's where things get fun-- the plant class has an enum for growth stages, and each growth stage can have its own timer for how long to spend in that stage. In other words, my plants will visibly grow through multiple different stages! Right now I'm just scaling a capsule mesh, but in the future I'm expecting to swap out models as they grow. I might also add different requirements for the stages, like needing to be pollinated, fertilized, weeded, etc. We'll see how the design goes.
Wednesday, December 13, 2017
Space Farm devlog 2
Welcome back! I have more Space Farm updates. To help you navigate these posts, I've added a "space farm" tag that should bring up anything related to this project. I'll try to add other useful tags as I go, especially whenever I include code snippets.
As I might have mentioned in the last post, this time around I worked on letting the player interact with the game world. Since I don't really have a clear plan for the gameplay just yet, I figured a cursor might be a good start. I created something similar in a tower defense prototype in GM, so I had already worked out some of the logic at some point in the past and felt it should be possible to make again. Seems reasonable enough, right?
So I started with simply spawning an object called "cursor" on the map. Like everything else in this game so far, it's a cube. I put a translucent green material on it so it'd stand out a little better. Life was good.
And then I tried to make it follow the mouse. This was... not as easy. As I'm sure I'll state a million times in this devlog, I'm not super familiar with cameras, especially in a 3D space. So translating from screen coordinates to world location wasn't intuitive for me. I've written the kinda code where it works but I'm not really sure how-- Unity's "screen to world point" function got me most of the way, but I needed to add some funky-looking math to adjust the received value to account for the camera angle. Without this adjustment, the cursor would float off the ground near the top of the screen, but sink through the floor near the bottom of the screen.
After correcting this, I decided to go ahead and lock the cursor's movement to a grid, as well. I figured one of the first player actions I'll add is placing things in the world, and as a player I always appreciate a placement grid so I can plop things down all willy-nilly and have it still look decent. This should also theoretically make things easier to program later, as I won't have to deal with detecting multiple objects under the cursor when the player clicks. The design document for this project is still pretty bare-bones, so I might change this later.
Even with all the Googling, I'm having fun. I think next I'll start on the farming tools. It's kinda hard to have a farming game without the part where you grow plants, after all!
As I might have mentioned in the last post, this time around I worked on letting the player interact with the game world. Since I don't really have a clear plan for the gameplay just yet, I figured a cursor might be a good start. I created something similar in a tower defense prototype in GM, so I had already worked out some of the logic at some point in the past and felt it should be possible to make again. Seems reasonable enough, right?
So I started with simply spawning an object called "cursor" on the map. Like everything else in this game so far, it's a cube. I put a translucent green material on it so it'd stand out a little better. Life was good.
And then I tried to make it follow the mouse. This was... not as easy. As I'm sure I'll state a million times in this devlog, I'm not super familiar with cameras, especially in a 3D space. So translating from screen coordinates to world location wasn't intuitive for me. I've written the kinda code where it works but I'm not really sure how-- Unity's "screen to world point" function got me most of the way, but I needed to add some funky-looking math to adjust the received value to account for the camera angle. Without this adjustment, the cursor would float off the ground near the top of the screen, but sink through the floor near the bottom of the screen.
After correcting this, I decided to go ahead and lock the cursor's movement to a grid, as well. I figured one of the first player actions I'll add is placing things in the world, and as a player I always appreciate a placement grid so I can plop things down all willy-nilly and have it still look decent. This should also theoretically make things easier to program later, as I won't have to deal with detecting multiple objects under the cursor when the player clicks. The design document for this project is still pretty bare-bones, so I might change this later.
Even with all the Googling, I'm having fun. I think next I'll start on the farming tools. It's kinda hard to have a farming game without the part where you grow plants, after all!
Sunday, December 3, 2017
Space Farm devlog 1
Howdy, internet people! I've started a new game project, which I will call Space Farm until I come up with a real name. If that working title isn't descriptive enough, Space Farm is a farming game set in space. That's the bulk of the design document at the moment, to be honest.
I'll start keeping track of my progress here on my blog, partly to share with y'all and partly for my own convenience. I'm a habitual note-taker and have found some of my old posts to be consistently helpful as I worked on GameMaker and Unreal Engine games-- hopefully this devlog will do the same as I get started in Unity.
A quick note on engine choice-- although I have a fair bit of experience in GameMaker, my last couple attempts at a project felt hindered by the development environment it provides. I really wanted to start using the scripts feature as much as possible to make the code more modular/ reusable, but they didn't give me the level of control (or maybe flexibility?) I expected. And so I tried UE4 for a while. It seemed like it ought to have been a good fit considering how much I had played with UDK in school, but it just felt too heavy for this dinky little farming game. Unity and C#, which I haven't really used before, will be my weapon of choice. At least for now.
Ok, that's enough of a preamble-- let's get to what I've gotten done. For this work session, I kept things simple so I wouldn't get overwhelmed by the switch to Unity. First, and perhaps most importantly, I set myself up a repository I can save all my work to. Right now it's just saving a copy onto another HDD on my computer, but since this machine likes to kill itself about once a year, I'll be considering better locations soon.
Second, I implemented a simple 2.5D camera and movement system. Cameras are still kinda foreign to me after spending so long with GameMaker, so I had to do some Googling. Some nice person on the internet had already posted their solution to exactly what I wanted, which might have helped a little too much, but got me up and running. You can now move around the world in eight directions with the camera keeping you centered on the screen. Fancy!
I went ahead and added some "dirt blocks" to the scene for fun. They don't really do anything yet, but it's starting to look like something now.
That's all for now. Like I said, trying to keep it simple at the start. Next on my task list is interacting with the world, so that ought to be a little more complicated.
I'll start keeping track of my progress here on my blog, partly to share with y'all and partly for my own convenience. I'm a habitual note-taker and have found some of my old posts to be consistently helpful as I worked on GameMaker and Unreal Engine games-- hopefully this devlog will do the same as I get started in Unity.
A quick note on engine choice-- although I have a fair bit of experience in GameMaker, my last couple attempts at a project felt hindered by the development environment it provides. I really wanted to start using the scripts feature as much as possible to make the code more modular/ reusable, but they didn't give me the level of control (or maybe flexibility?) I expected. And so I tried UE4 for a while. It seemed like it ought to have been a good fit considering how much I had played with UDK in school, but it just felt too heavy for this dinky little farming game. Unity and C#, which I haven't really used before, will be my weapon of choice. At least for now.
Ok, that's enough of a preamble-- let's get to what I've gotten done. For this work session, I kept things simple so I wouldn't get overwhelmed by the switch to Unity. First, and perhaps most importantly, I set myself up a repository I can save all my work to. Right now it's just saving a copy onto another HDD on my computer, but since this machine likes to kill itself about once a year, I'll be considering better locations soon.
Second, I implemented a simple 2.5D camera and movement system. Cameras are still kinda foreign to me after spending so long with GameMaker, so I had to do some Googling. Some nice person on the internet had already posted their solution to exactly what I wanted, which might have helped a little too much, but got me up and running. You can now move around the world in eight directions with the camera keeping you centered on the screen. Fancy!
I went ahead and added some "dirt blocks" to the scene for fun. They don't really do anything yet, but it's starting to look like something now.
That's all for now. Like I said, trying to keep it simple at the start. Next on my task list is interacting with the world, so that ought to be a little more complicated.
Sunday, June 26, 2016
Game Maker Tip: Collision and Instances
Wondering why your collision code isn't working, despite the fact that your code is written exactly like the documentation suggests? I was, too. Five hours of my life down the drain, bashing my head against my keyboard in the hopes I'd hit the "fix my code plz" button we all secretly fantasize exists somewhere. Bad news, I did not find this fabled button. Good news, reading the docs until my eyes blurred did reveal this one snippet of information tucked away in the place_meeting function page:
There it is. "... this function can check... for collision... using the collision mask of the instance that runs the code for the check [because duh, why would the function itself let you decide?]" Emphasis and commentary mine, of course. I mean, how else would collision functions work-- by giving you a clear idea of what objects you're checking? Or maybe the opportunity to set both objects? Hah! Foolish peasant, bow to the glory of the rabbit hole of obscured instancing!
Ahem. Sorry about that. Needed to get it all out. To be a little more serious-- and hopefully helpful-- here's the problem I was having. Since I love functions and want to offer both mouse and gamepad support for the project I'm working on, I decided to write a script to handle shooting. The key press detection code is in the Player Object, and thus the Shoot script technically gets called by said Player Object. So far so good, right?
However, I want to do some fancy shooting. I made a sprite to act as a "cone of vision" that could be scaled depending on how much of a range the currently equipped weapon has. So instead of shooting out a projectile, I want the Shoot script to detect any enemies that are under this cone and act on them accordingly. I used the built-in place_meeting function to do this, as I remembered this function working pretty well for this purpose before. Long story short, this did not work in my setup. After much struggling, I finally realized that this place_meeting call was using the Player Object when it checked for collision with my enemies. After some additional struggling, I figured out that this is the intended function of GameMaker and I had just glossed over the part of the documentation that stated this fact.
To be fair, it makes sense. The place_meeting function only allows you to specify one of the objects you're checking for, so logically the code has to be getting the other object from somewhere. Unfortunately, I would vastly prefer it not just assume the other objects is the one calling the function, and that the person writing the code is aware of this. Clear code is happy code, after all.
Ultimately, I just added a with clause to the chunk of code checking collision and the issue cleared right up. It also let me delete about 50 lines of code I had scrambled together trying to fix what technically wasn't broken, so now my code looks pretty again. Hooray!
#%&@#% |
There it is. "... this function can check... for collision... using the collision mask of the instance that runs the code for the check [because duh, why would the function itself let you decide?]" Emphasis and commentary mine, of course. I mean, how else would collision functions work-- by giving you a clear idea of what objects you're checking? Or maybe the opportunity to set both objects? Hah! Foolish peasant, bow to the glory of the rabbit hole of obscured instancing!
Ahem. Sorry about that. Needed to get it all out. To be a little more serious-- and hopefully helpful-- here's the problem I was having. Since I love functions and want to offer both mouse and gamepad support for the project I'm working on, I decided to write a script to handle shooting. The key press detection code is in the Player Object, and thus the Shoot script technically gets called by said Player Object. So far so good, right?
However, I want to do some fancy shooting. I made a sprite to act as a "cone of vision" that could be scaled depending on how much of a range the currently equipped weapon has. So instead of shooting out a projectile, I want the Shoot script to detect any enemies that are under this cone and act on them accordingly. I used the built-in place_meeting function to do this, as I remembered this function working pretty well for this purpose before. Long story short, this did not work in my setup. After much struggling, I finally realized that this place_meeting call was using the Player Object when it checked for collision with my enemies. After some additional struggling, I figured out that this is the intended function of GameMaker and I had just glossed over the part of the documentation that stated this fact.
To be fair, it makes sense. The place_meeting function only allows you to specify one of the objects you're checking for, so logically the code has to be getting the other object from somewhere. Unfortunately, I would vastly prefer it not just assume the other objects is the one calling the function, and that the person writing the code is aware of this. Clear code is happy code, after all.
Ultimately, I just added a with clause to the chunk of code checking collision and the issue cleared right up. It also let me delete about 50 lines of code I had scrambled together trying to fix what technically wasn't broken, so now my code looks pretty again. Hooray!
Thursday, May 22, 2014
Senior Capstone: a Simple HUD or Screen Overlay in Kismet and Flash
Updated 16 June 2014
This tutorial covers a quick method of creating a very simple HUD or screen overlay using Kismet and Flash. Assuming you have your image ready, this should take you about two minutes to put together. You can use it as a starting point for a Kismet-based HUD if you'd like, but I'd recommend it as a means of prototyping or for simple screen overlays, as things will get messy pretty quickly.
This tutorial covers a quick method of creating a very simple HUD or screen overlay using Kismet and Flash. Assuming you have your image ready, this should take you about two minutes to put together. You can use it as a starting point for a Kismet-based HUD if you'd like, but I'd recommend it as a means of prototyping or for simple screen overlays, as things will get messy pretty quickly.
![]() |
A sample of what you can do with this method |
Update 16 June 2014: Step Zero: prepare your UDK map
Thanks to commenter Glorius for pointing out that this does not automatically work right for the UTDeathmatch game mode, as I was using UDKGame for my project. If you're using Deathmatch, the first thing you will want to do is hide the HUD that comes with it. This is something that can quickly be done in Kismet, don't worry. You just need the "Toggle HUD" node attached to an "On Level Load" node through the "hide" option, with the target set to "All Players." Here's a picture of that for clarity:
Simple, but effective |
Please comment below if this does not work for you for some reason. It should not affect the pseudo-HUD I'm about to show you, but it should hide your ammo and map graphics if you're using Deathmatch and any other graphics from game modes that use an UnrealScript-based HUD.
Step one: prepare your image
In this case, I wanted a pseudo-HUD that would show the player how to equip the different items in their inventory once they picked them up. My first draft was a sloppy .jpeg, while my final version (shown above) was done in Illustrator. What program and file-type you use is up to you-- just make sure it's of the quality you want and something that will play nice with Flash. I'm not entirely sure about scaling yet, so I recommend saving it at whatever size you want it to be on the screen.
Step two: making the Flash file
After you have the image ready, you'll want to drop it into Flash. For this project I just went with their default canvas size, but you might want to alter it to be the right resolution or ratio for your image and game. If you haven't used Flash before, you can just drag your image in from wherever you saved it on your computer. Get the image place where you want-- again, for noobs like me, there are align tools under "Modify..." When it loos good, hit "File > Export > Export Movie..."
This part I'm a little iffy about because my files derped when I moved my UDK environment to a different hard drive after the project was completed, so bear with me. You'll want to create a new folder in UDK's Flash repository, which can be found at (wherever you put it)\UDK-(build#)\UDKGame\Flash So you'll be saving your .swf files in UDK-(build#)\UDKGame\Flash\YOUR_FOLDER Name the folder and file whatever you want, but avoid using whitespace in your filenames, as it can confuse UDK.
Step three: import the Flash file in your content browser
Hopefully you already know how to do this. I don't recall it needing any special treatment, so just import it like you would anything else and save it in your project's package. If you're not sure how to import things, open up your Content Browser and hit the "Import" button at the bottom of the window and then find the file.
Step four: putting it together in Kismet
This part is also pretty simple. The logic is on level load, start up the "movie" we made. Here's a diagram of the Kismet:
Yay Kismet! |
In the "OpenGFxMovie" node, you'll need to use the drop-down bar to select the .swf file to open. I just left all the other settings on default. Now when you start up the game, your fancy screen overlay should show up!
Step five: polish and expanding the code
From here on, you're on your own. Maybe you'll want to tweak the Flash file to look better, maybe you'll want to show and hide the overlay with a button press, or maybe you'll want to get fancier with the code and have it actually do something interesting. My next little tutorial will cover how to put replaceable text into Flash files and edit said text in Kismet.
It's pretty hacky and doesn't do anything interesting on its own, but this is a very quick way to get something up on the screen without writing a single line of UnrealScript. It suited my purposes perfectly, and I hope it'll benefit someone else out there as well. If you have any problems or questions, please let me know. It's been a while since I put this system together, so I might not have written the most precise instructions.
Happy deving!
Subscribe to:
Posts (Atom)