Level-Up Coding

Level 7: Arrays and For loops can manage many objects

In the last level you moved two sprites based on input from the user. But what if you want twenty enemy ships on the screen at the same time? In this level, you will learn to use arrays to hold many different objects, and for loops to do something to all of the objects in an array, such as move or display them.


Arrays are Numbered Lists of Objects

In Javascript, a special kind of variable called an array can hold a numbered list of items. The number of an item is called the index, and the item itself is called an element.

Instead of starting with the index 1, the beginning index in an array is 0. Suppose I have the list of words “Programming”, “is”, and “fun” in an array. The word “Programming” has index 0, as shown below, and “is” and “fun” have index 1 and 2:

    Index   Value
    -----   ------------
    0.      "Programming"
    1.      "is"
    2.      "fun"

Creating an empty array

To create an empty array in Javascript, you use square brackets []. The code below creates an empty array called enemies as part of the gameState:

    gameState.enemies = [];

Once it has been created, the array exists in the computer, but does not have any items in it (the length is 0).


Adding an object to an array

When you create a new array it does not have any elements in it. You can add values to the array by using the push method. For example, you might want to add an enemy sprite to the enemies array. This code adds a sprite to the enemies array:

    var enemy = makeSprite("enemyImage", 100, 100, 1.0, 0.0);
    gameState.enemies.push(enemy);

When you push something onto an array, it increases the length of the array by one, and puts the new element on the end. Whenever you need to know how many elements are in an array, you can get it by using the length property:

    // Get the number of objects in the enemies 
    var numEnemies = gameState.enemies.length;

To remove something from the end of the array, use the pop method:

    gameState.enemies.pop();

With for loops, you can add a bunch of enemies in a row

Imagine that you want to add 5 sprites to the enemies array in a row. One way to do this would be to copy the code above and paste it into your program 5 times, but then your program would start to get long! It would be better to make the program run the same code 5 times to create all the enemies. Javascript has a way to do this called a for loop.

Loops work a lot like if statements. In an if statement, there are is a bunch of code that will run once if a condition is true. In a for loop, the program will run a bunch of code over and over as long as the condition stays true.

The code below is a for loop that will add 5 enemies to the enemies array. Copy this code to window.onload after the line you used to create the enemies array.

    // Add 5 enemies to the enemies array
    for (var i=0; i<5; i++)
    {
        var enemy = makeSprite("enemyImage", 100+110*i, 100, 0.0, 0.0);
        gameState.enemies.push(enemy);
    }

Now instead of 10 lines of code, there are just 5. There are a bunch of parts to this code, so let’s go though them one-by-one.

The Loop Body. The main code of the loop is the part in curly braces {}. It is called the loop body. Notice that it is just like the code to add an enemy that you saw earlier. The only difference is that the x position is set using an equation (100+50*i). Each time when the loop body runs, the value of i will be different, so the program puts a new enemy at a different position on the canvas. The image below shows how this looks.

Controlling the Loop. Let’s look at the first line of the loop: for (var i=0; i<5; i++). This line controls how the loop will work. There are a few parts to it:

  1. The word for tells the computer that the code is a for loop. Then the different parts that control the loop are put in parentheses ().

  2. The first control part var i=0; is called the initialization. The initialization for this loop declares a variable called i and sets its value to 0. As the loop progresses, the value of i will change.

  3. The next control part i<5; is called the test. It is used to decide whether to repeat the loop body each time. In this case the test tells the computer to run the loop body again whenever i is less than 5.

  4. The final control part i++ is called the increment. For loop above, the increment adds 1 to i after the loop body runs. This means that every time through the loop, i will be 1 larger than the last time. In all, i will have the values 0, 1, 2, 3, 4, and the loop body will run 5 times. Each time the loop body runs is called an iteration.


Array Indices

To access one of the elements of an array, you use square brackets, putting the name of the array on the left of the square brackets, and the index inside them. As mentioned before, the beginning index is 0 instead of 1. This is called zero-based indexing. For the enemies array, you can get the beginning element of the array using the following:

    var enemies = gameState.enemies;
    var e = enemies[0];

To get the last element, you use index enemies.length-1:

    var enemies = gameState.enemies;
    var e = enemies[enemies.length-1];

Drawing all the enemies with a loop

You can draw all of the ships in the enemies array in a loop. This time, the test part of the loop uses the length of the enemies array. In the drawGame function, you would add a loop like this:

    // Make a variable to reference the enemies array
    var enemies = gameState.enemies;

    // Draw all of the sprites in the enemies array
    for (var i=0; i < enemies.length; i++)
    {
        drawSprite(enemies[i]);
    }

Moving all the enemies with a loop

You can move all of the sprites in the enemies array with a for loop just like the one for drawing them. The only difference is that you would call the function moveSprite instead of drawSprite.


Removing an element from an array

In games, objects appear and disappear all the time. Making something appear is called spawning. To spawn an enemy sprite, you can make a sprite and push it on the enemies array. Then it becomes part of the list of enemies, and will be drawn when drawGame gets called.

To destroy an enemy, you just remove it from the enemies array. Javascript has a built-in function called splice that can remove items from anywhere in the array. Notice that this is different than pop, which always removes the end element.

splice works by telling the computer the index in the array where to start removing items, and how many items to remove. The example below removes one enemy at index 3:

    gameState.enemies.splice(3,1);

Note that starting index could also be held in a variable, so that if you want to remove the element at location n, you would write

    gameState.enemies.splice(n,1);

Terms


Exercise

  1. Start with level7exampleStart.html. Copy this file to a folder on your computer.

  2. Copy the shipImage.png and enemyImage.png images and store them in the same folder.

  3. Add enemyImage.png as an invisible image in the HTML part of your page.

  4. In Window.onload, create an empty array for enemies with the code:
    gameState.enemies = [];

  5. After making the enemies array, use a for loop to add a five enemies to it in a horizontal row across the canvas. Set the vx property to 1.

  6. Add a for loop in the drawGame function to draw all of the enemies. If everything is hooked up correctly, you should see 5 enemy images when you run the page, as well as the ship.

  7. Add a for loop in animateGame to move all of the enemies. If everything is working, the enemies should move from left to right across the scene.


Bonus Level

  1. The code written so far moves all of the enemies to the right, wrapping them around at the edge. Change the code so that when any of the enemy ships hits the edge of the screen, all of the enemies change direction and go the other way. (Hint: do this in animateGame).

  2. Go back and make the ship respond to keyboard input the way that you did for the last level.