PART SEVEN
HARVESTING
MAKING MONEY
Game
We'll need to create a variable to keep track of the player's money and another method to add money to the player.
Since there is only one Game class, we can use the Singleton Pattern to make this method static (See: Coder's Handbook - Object Oriented Programming).
Thus, we'll create the following data and methods:
private static int money;
public static void gainMoney(int amount) {...}
public static void spendMoney(int amount) {...}
public static boolean hasMoney(int amount) {...}
Displaying Money
We'll also want to make a method to display the user's money:
public void renderMoney(Graphics g) {...}
USING FANCY FONTS!
Fonts Class
Make sure you have read Coder's Handbook - Fonts before working on this section part
Create a Class called Fonts and use that to store fonts in a similar way to how we added images in Part Three.
Don't forget to call loadFonts() in Game!
There is a known bug with Slick that can cause visual artifacts to appear with very large size text in most fonts. The workaround is to avoid that by generally making your titles be pre-rendered text.
Displaying Money In Style
Modify your program to use your chosen Font
You may find that your text doesn't "pop" across all terrain types. An ideal solution to this is to use white text with a black outline.
We can't quite do that, but, we can use a shadow effect to do something similar. Try drawing the same text on top of each other, but make it slightly offset and black the firt time.
Notice how we add +2 to the first time we draw the text in black. This offsets it by 2 pixels, creating a shadow type effect.
CHECKPOINT
Run your code and see...
Your program should now display a money counter in the top left with a font of your choice
SELLING CROPS
Setting Value and Expiration
In class Entity, create the following variables
A protected integer called value.
A protected boolean called expired.
For each of these methods, write a matching accessor.
In classes Corn and Potato, set the value of each crop.
My values are: Corn 5 and Potato 3
Removing Entities
In class Cell, write a method called removeEntity()
It should first check if the cell has an entity. If so...
Have entity setCell its cell reference to null.
Set entity to null.
It's important we do both steps, that way both sides of the relationship are cleared.
Clicking
If you remember, back in Part Four we created an abstract method in Terrain called clicked(). We'll need to do the same for Entity.
In class Entity, create an abstract method called clicked().
In class Crop, implement that method. You'll want to check if the crop is mature, and if so...
Remove this from Cell
Mark the tile as expired
Increase the money in Game by value.
In class Cell, we'll need to alert the entity (if we have one) that it has been clicked.
Check if entity is not null. If so, call the entity's clicked() method.
We're marking the cell as expired, but it isn't actually being removed yet!
Removing Expired Entities
In class World, write a method called cleanup(). This method should:
Loop through all entities
Check if the current element is expired, and if so, remove it from the list.
Hint: Be wary of how you might "skip" an element in the array by removing an object as you're looping through the list. You'll want to either decrement while removing or go through the array backwards.
In class Game, call the world's cleanup() method
CHECKPOINT
Run your code and see...
You can now sell crops, which removes them and increases your money
Note that when removing a crop, you may also water the ground. This is a known bug we'll fix in the next section...
FOCUS
Resolving Ambiguity
Uh oh! When you click on a mature plant to sell it, we also click on the Terrain at the same time. That could cause some issues in our game. Let's make sure the user can only do one interaction per click.
To solve this, we'll create a system to manage focus. We can mark that an entity on the tile is drawing the focus, and if so we'll interact with the entity. If not, a click will interact with the terrain beneath it.
Focus
In class Entity, create a protected variable called focus and write a getter called isFocus().
In class Plant, when a plant grows check if it is mature. If so, set focus to true.
In class Cell, if the cell has an entity and that entity is the focus, tell that entity it is clicked. Otherwise, tell the terrain it was clicked.
CHECKPOINT
Run your code and see...
Clicking on a mature plant should sell the plant but not modify terrain