This tutorial will explain how to find out if you are touching another actor, and subsequently remove that actor from the world. It will also explain how to keep your code readable using methods.
We're going to continue on directly from part 2, in which we got our crabs moving around the screen, under our control. In this part, we're going to introduce some worms for us to eat.
We already have a class for the crab -- we're now going to add another for the worm. Worm is also going to be an actor, so to make the worm class, right-click (Mac: control-click) on the Actor class and select "new subclass...":
As the new class name, enter: Worm -- note that we are using a capital W. It's the convention in Java that we begin class names with a capital letter. If you accidentally use a small w now, you'll get an error later on when copying our code that uses a capital W. From the left-hand list of images, select "worm.png" as the image and press okay:
Our Worm class will have no real code in it to begin with -- just like our crab class was when we started. We're going to leave it that way; our worms are dumb and just sit in one place ready to be eaten. Easy prey! We're going to modify our crab class so that when our crabs pass over a worm, they eat the worm. To do this, we go back to our crab's source code, which currently looks like this:
At the end of the act() method, we're going to insert some code to check whether the crab is currently touching a worm. We'll use the method getOneObjectAtOffset. This method takes three parameters. The first two are the X and Y offset (difference) from our current position. We want to know about what's directly underneath us, so we'll pass zero for both of these. The third parameter allows us to indicate which class we're interested in; that's the Worm class:
Note that we're not only calling the method, we're doing something on the left-hand side, too. This method returns something (the object underneath us, if there is one), so we need to store this return value ready to use it again. To do this we declare a variable (something for holding values) which we've called worm, on the line before. Then we use the assignment operator (an equals sign) to indicate that the value of worm should be set equal to the return value of the method.
Now we have the return value of the method in the variable worm. If there was no Worm touching us, this variable will contain the special value null. We can only remove the worm when there is a worm, so we need a check that the worm is not the special null value before removing:
The != is the "does not equal" operator in Java. This means we will only execute the code when worm is not null. The code in question is to get a reference to the world in the variable imaginatively named world and tell it to remove the worm using the removeObject method.
So, let's give it a test. Compile it, create some worms and place them in to your world, then add a crab, hit run and use your left and right keys to guide the crab to the worms, which should then get eaten. Tasty!
Before we move on, we are going to make a change to the code. This is something known as refactoring: changing the code without changing its behaviour. Currently the run() method for the Crab has two distinct behaviours in it: the top half deals with moving around, and the bottom half deals with eating worms. It would be clearer to name these and split them up, to avoid confusing ourselves later on. We can do this by creating methods for each behaviour. We've actually already seen how methods are written: act() is a method, after all.
Both of our new methods require no parameters and return no value, so they can be declared just the same as act(); the adjusted code is below:
If you compare this code to the previous version, you'll notice that we haven't actually changed or removed any of the existing code. We moved the top half into a new method called moveAndTurn, and we moved the bottom half into a new method called eat. We then replaced the contents of the act() method with calls to these new methods. This will make the code we have to focus on shorter in future parts of the tutorial -- part 4 is next.