So, I figured I'd write some blog posts about some of the problems I faced in Village and how I went about solving them. The first one I decided to write is going to be about the property system, because it's what I came up with first.
When I sat down to design Village, I already had an idea in my head. I wanted it to be quite a lot like Animal Crossing, but I wanted everything to be outside. The game was going to center around collecting stuff and adding it to your Village to make it all pretty, so I knew I needed a way to make items have certain properties. If I didn't have properties for each item, they'd all act the same. You wouldn't be able to walk on top of flowers but not trees; you wouldn't be able to dig up certain objects but not others. You wouldn't be able to do a lot of stuff! Of course, I could have hard coded all that stuff (like "IF (item in front of me)==TREEID THEN GOSUB @NOTDIGGABLE"), but with the amount of items I had planned, that just wasn't an option. I'd have to add more and more IF statements each time I added an item, and that's no fun. Plus, modularity is expandability are really important no matter what you're designing!
Anyway, I started with the property system. I needed a way to give any set of properties to any item in any combination. For instance, maybe an item could be diggable, but not obtainable. Or maybe it could be an obstacle, hammerable, AND obtainable. Maybe one day I'll come up with an item that has a set of properties I've never used before; I needed a system to support this. I decided to use the same system as that button presses used, which is to use powers of 2 to represent properties and save the combination of properties as a number. How does this work? Let's look at an example:
Suppose I have only 3 properties: A, B, and C. Let's assign the first 3 powers of 2 to each of them:
A = 1
B = 2
C = 4
OK, let's get right down to proving this works. Let's look at each combination of properties A, B, and C, and see that by adding the "value" of the properties together, we get a unique number. Ready?
No properties: 0
Wait, is this some kind of magic? How is it that choosing powers of 2 always lets us make unique numbers when we add them together?! The magic lies in the binary representations of each of these numbers. Let's look at A, B, C again as their powers of 2 in binary:
A (1) = 001
B (2) = 010
C (4) = 100
The leading 0's aren't necessary, but it does help us see how this works. In binary, you add just like you would in regular numbers. So, A+B = 011, because the 1's just trickle down. Notice that for each property, there is just a single 1 in a unique location. This can be thought of as setting a flag: property A sets the "first" flag (2^0), property B sets the "second" flag (2^1) and property C sets the "third" flag (2^2). Let's look at some more powers of 2 for a sanity check:
1 = 000001
2 = 000010
4 = 000100
8 = 001000
16 = 010000
32 = 100000
Wow, cool! So if we assign properties as powers of 2, we can create a unique set of properties by just adding them together! Oh, but how do we extract a property once we set it? Let's pull up the old ABC example: let's say we have properties A and C set. Well, A = 1, C = 4, so our group property is 5. Now we need to know what 5 is later: we just use AND. AND returns a 1 only if both things we're ANDing together are 1 for each position. Let's look at our 5 example:
5 in binary is 101. We want to see if we have the property C, which is 4 (100). AND them together:
This is because the two numbers we ANDed together both have a 1 in the leftmost position, but nowhere else do they share a 1. Thus, if we just take our group property and AND it with a single property, we can see if the group contains that property by checking that it isn't 0. Let's look at one more example:
Let's say we have the group property 010110 in binary (don't worry about what the real number is for now). We need to see if we have the property 001000 (remember, in this system, properties have a single 1 in a unique place in the binary representation, ie powers of two). If we AND them together:
Oh no, there are no bit positions where both numbers have a 1! This means that the group property 010110 does not contain the single property 001000. Well, that's how I implemented properties! If it's still unclear (and you know how binary works already), please let me know!