.. _lab7-array-graphics: Lab7 - Using Arrays for graphics ################################## Remember the Refrigerator Art project you did way back when? For most of you, that artwork was constructed by hand coding a bunch of calls to the shape functions provided in the Graphics library. (A few of you wrote smarter programs to draw your pictures, but basically, you ended up with a set of simple calls to functions with data you provided in your code. Array driven artwork ******************** For this lab, we will draw a simple robot. However, instead of going about this problem the way we did earlier, we will set up a data array with all the information we need. I will show you basically how to do this, you will need to come up with the numbers that build your robot. Here is an image of a robot toy to give you an idea what we want to construct: .. image:: SimpleRobot.png :align: center Figuring our the data ===================== As before, you will need to sketch your robot and figure out the approximate values you need for parameters to the shape drawing routines you will need to use. We will record those numbers in a big array of integer numbers, and trick our program into fetching the data needed for each function call from the array. .. note:: This will not be so bad, just follow my lead! Building the drawing program ============================ To create our drawing, we need to write down (on paper, not code) the sequence of shapes we want to draw, and for each shape, write down the numbers we will pass in as parameters on the appropriate function call line. Next, we will assign a simple number for each shape. Something like this: * 0 = circle * 2 = triangle * 3 = rectangle Now, we can write out our data as a set of numbers, line so: .. code-block:: text 0, 50, 50, 25 1, 200, 125, 100, 275, 200, 375 9 .. note:: That last number is bigger than any number we use for a shape. This set of numbers should draw a circle at x = 50, y = 50, with radius = 25, followed by a triangle drawn from x1 = 200, y1 = 125, and so on. We will record all of these numbers , in order, in a simple data array, then write code to pull these numbers back out as needed to generate our drawing! The main program code ===================== You will need to create a loop that works through the entire data array. Your loop will need to be coded so it checks the shape value, then pulls out the numbers needed for the right function call. We will use a new C++ statement to control the actual drawing. Here is the code we need to generate our drawing: .. literalinclude:: code/main.cpp :lines: 4-45 The switch statement ==================== There is a new statement in this code, the ``switch statement``. Basically, this statement is a replacement for what would be a complicated nested if-then-else statement, It works like this: Suppose you have an integer variable that can hold one of a defined set of values and you want to process different code depending on the actual value in that variable. The ``switch(shape_type)`` part of this statement examines the variable (``shape_type`` in this example). What comes after the ``switch line`` is a C++ ``block``, which is a series of things inside curly braces. In this statement, each possible value we want to check is identified by a ``case value:`` line. In the example above, I have set up simple numbers for each possible shape I want to draw (well not all of them, this is just an example). After each ``case value:`` line, we place a series of statements (indented) that will be processed only if the value of the variable matches the ``value`` on the ``case`` line. For our program, the last line in this set of statements should be a ``break`` line. The ``break`` "breaks" us out of the ``switch`` statement, and we continue processing on the statement following the close curly bracket. In special cases, programmers leave the ``break`` out, but what happens if beyond this course, so make sure you remember to put this statement in as shown. If the value in ``shape_type`` does not match any of the values listed on the set of ``case`` lines you include, we can do something by default. We just include a final ``default:`` line, followed by the code we want to process. In this set of code, we do not need a final ``break``, since this chunk of code comes at the end of the ``switch statement``. Phew, sounds complicated, but it is not too bad, and can be handy. Like everything in programming, you only use statements if you feel that they will help you get your job done. IN this case, it is just what we need to control our drawing! How this code works =================== The code shown above is a bit tricky, but it gets the job done! I figured this out a million years ago when I was trying to draw things in a language called FORTRAN! (Wait!, I am not really that old!) The main ``for-loop`` uses the counter to track the ``shapes`` we want to draw. In the example data set, there are two shapes, plus another number that will stop the loop, in case I mess up the data somehow! I set up another variable named ``index`` that I will use to point to the first number for a shape in the data array. Initially, this variable is initialized to zero (remember, the first number in the array, which is at ``data[0]``). Since the number in the ``data`` array is a zero in our example, that means we will draw a circle, and we need three additional numbers. Those numbers will be at: .. code-block:: text data[0] = 0 - draw a circle data[1] = 50 - the x coordinate data[2] = 50 - the y coordinate data[3] = 25 - the circle radius The ``case 0:`` line is where the code for drawing the circle needs to go. Notice that I am using the ``index`` variable to send the values from the ``data`` array into the drawing function. What happens at after the call to the drawing function is key to getting this all to work. For the next shape we want to draw, the shape number is in ``data[4]``. If we add 4 to Index, then ``index`` will be "pointing" to the next shape number in the array. In ``data[index]`` (``data[4]`` now), we find our next shape number, The parameters for that shape are passed in as parameters exactly as we did for the circle. Each ``case`` block needs to add something to the ``index`` variable, but exactly what that something is depends on the shape being drawn. For the circle, it was 3, for the triangle, it will be 6 (can you see why). I am not going to explain this code further here. You have enough background to figure out what is going on! Writing your code ================= You should start up your lab project by making sure this code works. Then add comments to the code to show you do understand what is going on. Once you have that done, add code to complete your robot (changing the data, of course!) Make sure you build this as a ``glut`` project and add the two files as usual. Have fun with this, and let me know if you have any problems getting things going!