Javascript can’t be in two places at the same time & a rant on math games
Spirit Lake: The Game is mostly an adventure game that teaches math. However, it has lots of Easter eggs, side quests and spin-offs added because hey, these are kids and sometimes they like to do something different and some of them have the attention span of an ant.
Our idea is to make the game fun, even when you get the answers wrong, you get sent to do something else that’s fun. I saw a Flash game that used refrigerator magnets for division problems which seemed pretty fun, but we are avoiding Flash since we want our game to be easily portable to iPads from the current version that runs on Mac OS and Windows. So … I spent today writing a refrigerator magnet division application. You can see it here. It still could use a bit of tweaking – I need to add the refrigerator background and I think I’ll change the pictures of magnets I have to some that are more cute and fun.
Being our child, The Spoiled One did not even ask why The Invisible Developer was in the kitchen taking pictures of the refrigerator.
Here is the problem I ran into …. it was working fine EXCEPT if I had a problem like 36 ÷ 6 in which case the second value was blank and all I got was
36 ÷
It was as if the image (remember, each number is a picture of a refrigerator magnet), could only be used once. Well, of course, that WAS the problem.
From the enormously helpful Mozilla Developer Network
If
child
is a reference to an existing node in the document,appendChild
moves it from its current position to the new position (i.e. there is no requirement to remove the node from its parent node before appending it to some other node).This also means that a node can’t be in two points of the document simultaneously. So if the node already has a parent, it is first removed, then appended at the new position.
I was doing exactly that, the offending statement is shown with *** below
function getProb()
{
var choose2=randnum(1,9);
var temp=randnum(1,9);
var choose1 = choose2 *temp ;
rightanswer=choose1 / choose2;
w = choose1 + "" ; x = w.substring(0,1) ;
** document.getElementById("pic").appendChild(imgArray[(choose2)]);
document.getElementById("tot").appendChild(imgArray[(x)]);
if (w.substring(1,2) )
{
y = w.substring(1,2) ;
document.getElementById("tot2").appendChild(imgArray[(y)]);
}
}
What this snippet does is generate a random number between 1 and 9, then generate a second random number. The two random numbers are multiplied to give me a product of two numbers between 1 and 9 because the game progresses gradually in difficulty from early levels that assume children have not yet mastered division with remainders, and this little applet goes into an early level. So, the number which we use as our divisor should be divisible without a remainder.
The divisor (which, of course goes first in a division problem) divided by the second number shown on the page (choose2, our dividend) gives us the right answer.
Earlier in the program (not shown) I had created an array which was like this
var imgArray = new Array() ;
imgArray[0] = new Image() ;
imgArray[0].src = "zero.png" ;
imgArray[1] = new Image() ;
imgArray[1].src = "one.png" ;
The answer is going to be between 1 and 9, so I can take whatever it is, find the same number in the array and put that image into the cell for the dividend.
I need to break the number to be divided down into digits because, remember, these are refrigerator magnets and numbers between 1 and 9, so each digit is a separate image. I did it by making a string variable by adding “” to choose1. I then took the first digit and put that image into a table cell. If there was a second digit, I took the image in the array corresponding to that and put that into another table cell.
BUT …. what happened was when a number was used twice, like in the example of 36 divided by 6, when I appended the 6 to the divisor, it was removed from the dividend cell.
How to solve this? Well, one way is to create another array of images, which I did, both because it was a super simple solution and I immediately thought of several other reasons off the top of my head why that might be useful. I can certainly envision using this code again in the game, for example, to emphasize which is the divisor and which is the dividend. There are lots of points where students confuse the two, or fail to understand that you cannot switch them around and still get the same answer, like you do with multiplication. In fact, I’m already thinking about having the numbers for the dividend being red or flashing (probably not) or from a different set of magnets.
So, there you have a nifty little reminder about how appendChild works and a super-simple way to fix a possible problem.
There is also another point in here I’d like to make. Last night, I attended a meet-up on gaming where some people were positive that they did not need to know anything about math education to write a math game because, “Hey, everybody knows K-12 math and the teachers know how to teach it.”
Yes, most teachers do know exactly what their students should be learning, but do YOU? Because if you have a game that is assuming students can divide numbers that have remainders and the students are not at that point yet, they will be frustrated. It really isn’t the teacher’s responsibility to insure that your game that you say is at fourth grade level really is. Even if it is, at what point in fourth grade? What exactly does it teach? When should he or she be introducing it to the students? At the end of the school year? At the beginning? Do you know what a divisor or dividend is and that students often mix them up? What area of mathematics do most students have problems with in fourth and fifth grade? What should your game emphasize?
I think the fact that many math educational game designers don’t give much attention at all to math is why most math educational games suck at being educational, no matter how cool they may be as games.
Interesting little program.
Since I never worked with the draggable interface, I messed around a bit with it for fun and ended up improving a few things along the way (score keeping, resize on hover to make it look like you are actually lifting the magnets, fixed a couple bugs, things like that).
Here is the code, in case you are interested:
http://jsfiddle.net/bW9ne/
(If you aren’t familiar with jsfiddle, the bottom right panels works shows the end result in a frame and works as a completely separate webpage – it’s fully functional).
Some general comments:
* In your code, you add images to the document as nodes in the DOM, and then you position them where you want. As you found out, you end up moving them by specifying a different position, which makes sense.
Here the solution is NOT to copy/paste a new array and maintain a new set of pictures in a different folder, but simply add links to the pictures as you need them: append an image tag with the right url and it will work just fine.
If you have to copy/paste a block of code, you’re doing something wrong. (Not a big problem at the beginning, but very quickly, the whole thing becomes a maintenance nightmare with duplicate code everywhere).
The second you feel copying/pasting a big chunk of code is a good solution, your spider senses should go as berserk as when your opponent slides your collar under your chin – there is no situation where this is good news.
* the 90’s called and they want their tables back. (ok, I know, I am a bastard, but seriously, hand-coded tables?). It’s much easier and faster to loop through the array AND it’s also easier to change afterwards if needed.
* No need to reload the page to clear it, and clicking twice on “get problem” should remove the old problem before displaying the new one. (It’s very easy to do if you generate the layout on the fly instead of hard-coding cotton picking tables.)
Some suggestions:
– Reset the score with the reset button (I forgot and I am too lazy to edit/resave the fiddle)
– Add a timer and keep track of scores, times and users, and make levels (i.e: shorter time limits).
– allow keyboard input (moving numbers with the mouse looks nice the first few times, but it quickly becomes a pain and if a kid starts playing for time, it just gets in the way)
When I was a kid, my brothers and I used to play a math game my dad had programmed on an old Sharp computer (MZ 80). Pretty much the same concept as this one, except of course for the green on black screen and the ascii art. Well, that and about 48kb of RAM. But the game had levels, scores, rankings, timers and did multiplication, subtraction, division, addition and we were going crazy trying to beat each others’ times. Within days, we were getting really good at basic calculations.
Oh, well, anyway, I hope you find these comments useful and don’t take offense at the corrections.
Good luck with the program and feel free to drop me an email.
Hey, thanks. No I am not familiar with jsfiddle, I will check it out. No offense taken at all! Everything we do on the games is in a constant state of development. We do something, let kids play with it, then do it better, re-do it.
Every week, I go back through some code I wrote previously and slap my head going, “Oh, my God, what was I thinking when I did wrote that? Yeah, it works, but it’s unbelievably sloppy.”
As for the keyboard input, at first, I thought no, that defeats the purpose, which is to make it a physical thing, like dragging magnets on a refrigerator. Then … I thought about kids with disabilities who might have problems with that and your keyboard input idea suddenly seemed brilliant. I have a good friend who is blind and used to teach elementary school to blind children. In design, I often hear her voice, like my conscience, saying, “What about kids who CAN’T see or don’t have much fine motor control? What about THEM?”
Yeah, I am all too familiar with the “slap my head, what was I thinking” routine.
For jsfiddle.net, it’s a really nice way of sharing Javascript code and making a live demo. I fixed a small display issue on my previous demo and added a magnet sound to the drop event:
http://jsfiddle.net/bW9ne/3/ (click on the button to display the interface)
For the keyboard input, it’s true there is an accessibility aspect to it, but IMHO, being good at division requires a lot of practice before it becomes automatic. It takes a lot of “reps” before a kid can look at 56 and see 8 x 7.
The ability to drag numbers makes it fun and interesting at the beginning, but having to drag numbers each time will discourage most kids from doing enough drills to actually get better at division. Try to do 50 reps in a row and you’ll see what I mean.
A fun interface will make kids want to try, but an usable interface is needed to allow them to do enough drills to learn the skill. IMHO, you need both if you want kids to really use it.