For a long time I've postponed the making of a crafting system, so I ended up making one of those bets with a friend, where you give each other a task, and failing means you have to give the other part something. So my task was to implement crafting in the game, which I did.
What's new?Both combat and crafting has been implemented in the game. The complete list of updates since last post:
- Added Crafting to the game. Currently there is 10 craftable items.
- Added new items to the game. Currently there is 18 items in the game.
- Combat has been implemented. You can now kill (and loot) rabbits.
- Two loot items has been added to the rabbit. Animal fat and Rabbit Hide.
- Sand tiles and the sand item has been added to the game.
- New background(s) for both day and night time.
- Tiles now crack when mined to visually show where you are currently mining.
- Terrain has been updated- This is still at an experimental stage, as you can easily see in the video.
- Random caves and holes has been added in the terrain. This is also very experimental.
- Optimized on RAM usage. Reduced the memory required for each tile by approximately 20%.
CraftingEver since I got mining implemented into the game I've wanted to add a crafting system. I thought it would be a lot of boring coding, so I kept doing other more exciting stuff. Now where the basics are complete I can see I was a bit wrong. The thing that took the most time was figuring out how my crafting system should work. On top of that I had to make it so that it was easy to understand, which I think I did accomplish. At the moment, you can craft any craftable item, as long as you have the required material. Since crafting is a major part of this type of game, I will expand on the crafting system later. Further restrictions, such as work benches, forges, etc. will be requirements for some items later. I've also though about adding recipes for some of the more unique and rare items in the game, where you need to find the recipe before you can craft the item.
Currently all recipes are hardcoded into the game. Actually what I do is keep all the recipes in one Method, within a switch case. I throw in the ItemID of the desired item, and it returns a list of Vector2 containing the ID and the amount of each required item in the recipe. Currently the code to retrieve the recipes are running every loop as long as the inventory is open. This is not optimal, but I needed to be sure that if I remove an item while the inventory is open that It wouldn't allow me to craft items that I didn't have the ingredients for. This is not that hard to fix. All I need to do is run the CraftingUpdate everytime I open my inventory, or change something in it while it is open.
I really should do that soon...
The UI for crafting is simple and straight forward, at least in my opinion. I haven't decided on the colors yet, but for now I'll stick to what I've got. I am planning on making the colorscheme for the UI customisable anyways.
Items and LootAs a consequence of both combat and crafting I've added a few more items to the game. This includes "Wooden Sticks, Animal Fat, Rabbit hide and sand. Except for sand, all of these were added because of either combat or crafting. I did put a lot of thought into what items I wanted to add to the game, especially the items needed to create torches. In this style of game torches are a very important aspect of the game, and their availability greatly impacts the game. Personally I believe that torches should be relatively easy to come by, but still require a bit of effort on the players part.
Since I don't want my game to be an exact copy of Terraria, I don't want to do the "get gel from slimes" thing. So I've decided to have more than one source of "fuel" for the torches. The first one being animal fat. Using one unit of animal fat, and one stick currently yields two torches. Animal fat currently only drops from rabbits, which is a harmless mob. My plan is to have a low to medium drop chance (somewhere between 5-20%) for every mob you kill that can be considered an animal. This will (hopefully) give a steady flow of "fuel" for your torches. I also want the player to be able to mine for his fuel, rather than kill animals. So being able to find coal while digging around was an obvious choice. Coal is not yet implemented in the game, but it will be added at a later time.
The rabbit hide has currently no use in the game. My first idea with it was to use it to craft animal fat by removing it from the raw newly skinned hide, but I decided against that. Instead I decided that a rabbit could drop both things. Currently there is a 25% drop chance on rabbit hide, and 20% on animal fat.
I also added the sand item and sand tile. There really isn't much to say about it. It was like a natural thing to add it sooner or later. It reacts to gravity, and falls down if something beneath it is removed. The physics for the sand is very basic. If a column of sand drops it drops just as a I shaped tetris block would do in a game of tetris (except for the grid based movement thing). Currently I am happy with the simplicity of it, so I might keep it that way... I haven't decided yet.
CombatSo eventually combat had to be implemented, and now was the time. I don't think I mentioned it in my earlier posts, but I've actually done some of the code for combat a while back now. I got stuck though, since the rotation of the weapon has some heavy mathematics around it. My math skills aren't sufficient for a lot of the more advanced stuff, so I do a lot of reading, and get help and find examples online, and basically I get something together by doing a mix of that.
So currently Swords, Axes and pickaxes are usable as weapons in the game. Already back before I even did anything related to graphics in this game, I fleshed out the tool/weapon classes very well, so after finishing the combat system it was all a matter of combining it with the calculated stats of the weapons and tools. Damage and mining efficiency are calculated from item type, material and other effects you can add to items. Speed is based on material and weapon/tool type. All three of these weapons are all swinging weapons, which means the swing in an arch from top to bottom in front of you. These are all working and are implemented.
How this works is, I rotate the weapon, and the origin of the weapon (Origin = hilt position). I tweaked the numbers so the sword arched nicely in front of the player. After that I added the swing animations to the sprite and polished the numbers a bit, and voila, Emma can now swing her sword. After I did that the next problem came up- I needed to have some decent collision detection so that I could kill some rabbits. Now when XNA rotates the sword visually, you don't have any boundingbox out of the box, that you can do collision detection on. So after reading up on the subject I found another solution. On your weapon you add a few points, in my case 3 points, and check if they intersect with the rabbit, and if so, you deal damage. Basically what I do is add 3 points, in line with the start position of the tool, and rotate it around the same origin (sword hilt). This way the points follow the sword and you have a decent collision detection for your combat.
I still need to implement stabbing weapons, and a digging weapon. The digging weapon (shovel) will rotate just like the swords and axes, but going from down to up instead.
I belive the stabbing collision will be simple enough, as there is no rotation involved there. I belive using a single point for collision detection would be viable here.
Terrain and Mining crackI have been playing around with the terrain quite a bit. There are underground caves, and randomized terrain. Everything is highly experimental at this stage, and although I've spend a lot of time playing around with it, and reading up on it, I don't have much to share about it currently. I use a variation of the Perlin Noise algorithm, which I haven't written by myself, but pieced together online. As you will see in the video, the results are promising, but definately needs improvement.
I've also added a small feature- The mining crack. When mining a tile a crack will now appear, indicating your progress. The further along you are, the more the tile will crack. If I remember correctly the crack is a 5 frame animation, and was implented very easily. Basically I just compare the tiles current hp to it's max hp, and based off on the percentage I draw the crack. So every 20% increases the size of the crack.
BackgroundsSo I've added some simple backgrounds, the most noticable is probably the night sky. It's very simple, but it does add a lot of mood to the scene. I do have a lot of plans with the backgrounds. I think I mentioned last time that the moon can be used to symbolize events, like a red moon in terraria causes zombies to invade. Their idea is very good, but sadly they don't utilize the potential of this idea very well, at least in my opinion. I can think of quite a few more events you can related to the moon. Even without the moon there is a lot of things you can do with the background. Imagine that sometimes a rare constellation will be visible on the night sky. This could be a subtle hint to the player that something is going on. Maybe a rare flower, needed for alchemy only spawns whenever there's a certain constellation on the night sky, or a certain kind of mob or animal only shows up during a specifik constellation. Adding lots of small events, gives the player options that can benefit them, but it will not be game breaking if you are unable to react to them.
Now I do know that adding tons of events like this can quickly become a lot of work, so my longterm goal is to see if I can find a fast, and yet solid way of handling these events. Something like everytime I want to add an event, it's all a matter of adding a few lines of code and store it in some event collection. As long as there are some solid, yet flexible, rules for these events, this should be possible.
I think that covered most of it. I didn't get around the RAM optimization at all, but really there's not much to it. I realized some time ago that my tiles had a lot of information in them, that I could possibly store elsewhere. Information like whether or not a certain tile type reacts to gravity. Instead of storing that information in the tile, I would just go look it up somewhere. I was hesitant to do that since then I'd have to jump through ifs or switch cases, for every single tile on the screen. So I went online and got some very nice advice. I create a list of tiles with static information (Not a static class). One for each TileType. Then all I need in the tile to access all the static information is the index number for the list. An example would be: Dirt is placed in the 2nd. spot in the list, thus it would be on location 1 in the zero based index. I than keep a short with the value one on the dirt tile, and use that as an argument everytime I want to retrieve information from the list. This way I save a lot of information from being stored in the memory, and I avoid having to juggle with switch cases hundres of times each cycle.
Phew.. This turned out to be quite a wall of text this time. It's getting late and there is school tomorrow, so I'll wrap it up.
Enjoy the video, and don't hesitate to comment, rate or subscribe, if you feel like it.