Welcome back, dear readers, to the fourth part of Sophie’s journey of writing a DrWho computer game with Greenfoot and Java.
If you have read the previous parts, then thank you for sticking with us for so long! (If not, you may like to start reading here: Part I, Part II, Part III).
I’ll try to make it short today – it’s been a long day, and it’s getting late. But this programming session I’d like to record took place five days ago, I have only sparse notes, and I’d like to get it down before I forget too much. I have been busy this week, so I haven’t had time to write this up earlier, but there was so much lovely and encouraging feedback on the previous posts that encouraged me to continue writing this up.
Thus, without further delay, on to the next task: Reaching the TARDIS with the energy pellets!
To show you upfront what we did: Here is the result of our work today. Go and have a quick play!
If you just had a play, you might have noticed what we did: more sound, a TARDIS, and counting pellets. But one thing after the other…
After the last programming session, Sophie was really keen to continue. The next day was a Saturday, we were sitting at home, and Sophie showed Feena what she had done. We all played the game for a bit (trying to collect the energy pellets), and Sophie was itching to continue.
What she was most keen on was using one of the sounds we had found the previous day. (We had found several Doctor Who sounds by googling around a bit.) So far, we had used her self-made sounds, but Sophie really liked one “THE DOCTOR MUST DIE!” sound clip (spoken by the Daleks!) which she wanted to use at the start of the game.
So, that’s the first thing we did. Moving the sound file into the scenario sounds folder is easy, playing it is easy as well, but getting it to happen when the game starts is actually a little harder then it might seem.
The Greenfoot world has an ‘act’ method that gets called on every step of the execution, but it does not have an initialisation method that gets executed only once. (Except for the constructor, but that gets executed when the world is created, which is well before the game starts.)
The trick we used is to use the world’s act method, and to count the act cycles. Then we can check whether we’re in the first act cycle, and play the sound only then.
This was actually a very nice bit of code (pedagogically speaking) since it reinforced quite nicely what we had done before. It shows a different context of a variable and an if statement. And it’s a nice little piece of logical thinking to get the idea. Here is the code we wrote in the “Mars” class:
public void act() { counter++; if (counter == 1) { Greenfoot.playSound("doctordie.wav"); } }
We also added, of course, the declaration for the counter field at the top of the class.
Once we had that done, we added the Tardis. This is easy by now: The Tardis is an entirely passive object in our game at the moment, so it was just a question of finding an image (easy with Google), creating an Actor subclass named “Tardis” and using the image (also easy). No code required.
We then wanted to get the first game task complete: the Doctor should collect all six energy pellets, and then get to the Tardis. If he gets there, a “Tardis sound” (which we also found on the web) should be played, and the Doctor gets to the next level.
First, we needed code to check whether the Doctor had reached the Tardis. We already had code that checked whether the Doctor ran into an energy pellet. It looked like this:
if (touches (EnergyPellet.class)) { remove (EnergyPellet.class); Greenfoot.playSound("gotit.wav"); }
It was now quite easy to adapt that to check whether he ran into the Tardis. Once I pointed out that we can reuse the same code, Sophie had no problem copying and adapting it:
if (touches (Tardis.class)) { Greenfoot.playSound("tardis.wav"); }
(This was all done inline in the Doctor’s ‘act’ method. I was thinking that it’s time to introduce private methods at some stage to get a better code structure with nice short, cohesive methods. But I decided to leave that until another day.)
This already worked somewhat – the sound played when the Doctor got to the Tardis – but it wasn’t quite right. It also played the sound when we hadn’t collect all energy pellets first.
So we decided that there should be six pellets, and introduced a counter. We also discussed how to stop the simulation. I showed Sophie the Javadoc API for the Greenfoot class (which you can just open from within Greenfoot), and she then found the ‘stopSimulation’ method. We worked out the syntax together, and she is getting close to understanding dot notation for method calls. Here’s the code we ended up with:
int pelletCounter = 0; .... if (touches (EnergyPellet.class)) { remove (EnergyPellet.class); Greenfoot.playSound("gotit.wav"); pelletCounter++; } if (touches (Tardis.class)) { if (pelletCounter == 6) { Greenfoot.playSound("tardis.wav"); Greenfoot.stopSimulation(); } }
Whoohoo – that was great! Some time of intensive playing followed with both Sophie and Feena getting very much into it and having great fun.
The last thing we did was initialisation: So far, we had always placed all objects into the world manually. Now we wanted to add some code so that the objects (Doctor, Daleks, Pellets, Tardis) get placed automatically. The game can then start up properly without any necessary further setup.
We can easily do that by adding the code to construct and place the objects into the constructor of the world object. Since the world gets instantiated automatically, we then also get the initial actors automatically.
Here is the new constructor of our ‘Mars’ class:
public Mars() { super(750, 450, 1); addObject( new Tardis(), 700,100); addObject( new Doctor(), 200, 400); addObject( new Dalek(), 420, 320); addObject( new Dalek(), 100, 120); addObject( new EnergyPellet(), 150, 75); addObject( new EnergyPellet(), 610, 290); addObject( new EnergyPellet(), 25, 200); addObject( new EnergyPellet(), 310, 160); addObject( new EnergyPellet(), 520, 110); addObject( new EnergyPellet(), 670, 400); }
That was a good chance to discuss coordinate systems again (something that Sophie had seen in school – it was quite nice to show her some interesting use of something she had encountered in her maths class). The fact that the origin of the coordinate system in maths is in the bottom left and on computer screens typically in the top left was an interesting little detail.
With this in place, we were done. It’s not the most riveting game in the world – I doubt anyone will get into heart attack territory from excitement anytime soon – but it’s a nice enough start for our level 1.
Let’s see what Sophie thinks up for level 2…
Summary:
Session #4
Time: approx 45 min
Result (live on the Greenfoot site): DrWho4
(Source code can be downloaded from the link above.)
Hey there,
thanks for keeping us all up to date, I really enjoy reading these installments! 🙂
One thing though, didn’t you already modify your Mars constructor in the last session? I think the only modification is the addition of the Tardis, but the other objects were already there (on slightly different coordinates, but still)…
Well spotted! Someone is really paying attention here…
I had modified the constructor, as you say, but I had done that on my own (without Sophie) only to produce the online version. For the online playable version, the object must be constructed programmatically, because you can’t do the interactive stuff.
But I hadn’t discussed that bit with Sophie before, and deleted it again.
I’m very excited to be reading this – hopefully in a few years my toddler will be able to do something like this with me.
A question, though – why did you use a counter in the act() method instead of just a “firstTime” boolean, like:
…
boolean firstTime = true;
…
public void act()
{
if (firstTime)
{
Greenfoot.playSound(“doctordie.wav”);
firstTime = false;
}
}
Was that for pedagogical reasons? This seems simpler to me, but I imagine there’s something I don’t understand.
Can’t wait to see level 2!
-Matt
As a computer science major in the US, who came across Dr. Who at the encouragement of a friend. I have to tell you, I am absolutely loving reading about this. I caught part I on StumbleUpon and RSS’d your site for the main purpose of following the developments, although I admit your articles on JAVA/etc. are quite informative.
Quick question about the online implementation of the Greenfoot project, as I showed my room mate, who is also following your journey, the latest installment, we discovered that it is possible to mouse click and drag any of the objects in the project. Is this just an oversight built into Greenfoot, or am I missing something….?
Thanks for keeping us all updated.
-Gabriel
Matt,
Regarding your question about using a boolean versus using an int: It is my impression that using ints is initially easier than using boolean flags.
The concept of just counting is very easy. And checking whether we are at 1 is as well. Boolean flags, in my experience, are a little harder for kids to get their head around.
So, even though a boolean is logically what we want here, I think the int version is easier to understand.
Gabriel,
Regarding dragging objects in Greenfoot: That is intentional, but will soon change.
We had various examples where we made good use of the ability to drag objects for input. So that was a feature, not a bug.
However, as you discovered, for most games, you don’t want most object to be draggable. From the next version of Greenfoot, the whole mouse input semantics will change, and objects will no longer be draggable by default.
I think this series is great! My first exposure to programming was the book “BASIC computer games:”
http://www.digibarn.com/collections/books/basicgames/
It seems like such a great, natural way to teach a lot of concepts, from programming to analytic geometry (as you’ve found) to basic calculus (e.g. position vs. velocity vs. acceleration) to physics. I’ve heard Seymour Papert say similar things.
As for private methods: they seem most useful in really big systems, when you can’t be sure who is messing with what variable. Python and other dynamic languages get by just fine without them, as did C and all languages before OO programming.
I’ve heard there’s an age where many girls become disinterested in maths and science, around the age where peer opinion starts to become very important. I can’t remember what age it is. I hope your daughter bucks the trend and keeps seeing the joy of programming, although being a programmer myself I’m biased.
Hi, have you been carrying on with this project? It seemed to have been developing so well and now it seems to have slowed down, I enjoyed reading about how you created the game.
Hello, my 9 year old son has just asked me to teach him to program. Based on your experience with your daughter do you think Greenfoot is appropriate or did you research any other options to guide her down the path of programming?
For a 9 year old, this is challenging. If he’s really interested, then it is certainly possible (as you have seen with my daughter), but only if you’re there to help him.
You have two options: You can use a system that is made for younger kids, such as Alice or Scratch (both excellent systems with drag-and-drop languages). With these systems, he can do quite a bit on his own.
Or you can work together with him, then you could use Greenfoot, which has a more challenging syntax, but is more open for future expansion.
@kris:
Yes, we have slowed down. That’s due to my being away for a while, and then being busy, etc.
But we will pick it up again soon – promise!
please give a simple bluej program(code) of a game,please its urgent