This site requires JavaScript, please enable it in your browser!
Greenfoot_back

Tutorial 5: Adding a Randomly Moving Enemy

After our last tutorial, we now have a scenario with a crab that we can control, that runs around eating worms. The game is quite easy though -- even though the crab is (deliberately) a little tricky to control, there's no tension. What we need is an enemy that eats crabs: a lobster!

To begin with, let's add a lobster that moves in a straight line and eats crabs. We can do that using code that we've already seen how to write. First, we add a Lobster class -- remember that we do that by right-clicking (Mac: control-clicking) on the Actor class and selecting new subclass. You'll find the lobster picture in the list of images on the left.

Once you've made your Lobster class, you can fill it in by making it move in a straight line and eating a crab if it finds one. You've already seen how to do each of those things in previous tutorials, so I'm not going to paste the code in here directly. Have a go yourself, but if you get stuck, you can see the answer here.

You can test that the lobster is working by placing one to the left of a crab, then clicking Run and let them both run to the right-hand side of the world where the crab will be eaten. (If you want to, make your own sound for when the lobster eats the crab.) That's great, but our lobster is pretty dumb; it's easy to get away from it by moving sideways, and when it reaches the right-hand edge of the world it stays there forever (just like our original crab did).

Let's make our lobster more difficult to avoid by introducing some randomness. Greenfoot provides a Greenfoot.getRandomNumber function that will give you a random number. Here's a first attempt, where we turn a random amount every frame:

Edit-lobster-movearound-narrow

That code means we will turn a random amount each frame, between 0 degrees (inclusive) and 90 degrees (exclusive). Try it out, and see how it works. You'll see that it doesn't create a very threatening enemy: the lobster seems to mostly spin on the spot (turning too often, in effect), and it always turns to the right. Let's fix those problems one by one, starting with the spinning on the spot.

At the moment, our lobster turns every frame, which makes it spin rather than wander around. There's a couple of different ways that we could make it turn less often. One would be to have a counter variable that keeps track of how long it was since we last turned, and turns, say, every 10 frames. Another way is to use the random number generator to turn randomly, with a certain average (e.g. every 10 frames). We'll go with another use of the random generator, as it makes for a less predicatable lobster.

Let's say that a lobster has a 10% chance of turning each frame. We can code this by comparing Greenfoot.getRandomNumber(100) to a given percentage:

Edit-lobster-movearound-narrow

If you are interested, think carefully about how this works -- why do we use < rather than <=. Could we have coded this differently, for example using Greenfoot.getRandomNumber(50) or Greenfoot.getRandomNumber(10)? What about Greenfoot.getRandomNumber(5)?

That will make our lobster turn (on average) every 10 frames. Compile and run it, and see what happens. The lobster should mostly wander along in a straight line, occasionally turning right by a varying amount. That's great, and it brings us back to our other problem: the lobster always turns right.

We know from our crab that the way to turn left is to use a negative number for the angle. If we could change from turning our lobster in the range 0 to +90 to turning in the range -45 to +45, that would fix our problem. There's a few different ways to achieve this, but here's the simplest: notice that if we subtract 45 from our number, we end up with a number in the right range. So let's adjust our code accordingly:

Edit-lobster-movearound-narrow

Is our range of turning perfectly symmetric at the moment? If not, how could you fix this?

Compile and run that, and we should have a somewhat effective predator that can turn towards you at any moment. Put a crab, several lobsters and lots of worms into the world (then save the world!), and try to eat all the worms before the lobsters catch you. You might notice however that there is one remaining flaw: the lobsters can get stuck for a time at the edges of the world. This is because once they hit the edge of the world, they'll only move away from it once they've done a few random turns.

We can speed up the process of getting the lobsters off the walls again by making them turn 180 degrees as soon as they reach the edge of the world. We can check for being at the edge of the world by seeing if their X coordinate is close to zero, or close to the width of the world -- and a similar logic for the Y coordinate (and the height of the world). The code is below:

Edit-lobster-movearound-narrow

That finishes the crab tutorial. You can continue to experiment with it and add new features (such as a second player), or use your knowledge to make your own new scenario. Have fun!