This note describes the Graphics Sampler, PA1 assignment for COM1370, Summer 1998. It includes a small program from the project in the folder Sampler demo 1-98 ƒ that is on the Ambassador server in the COM1370 Student folder. Run the application Sampler demo 1-98 to see how it works. But more importantly, you need to run a number of the samplers created by students in past graphics courses to see the range of possibilities. Your goal is to come close to or to exceed the quality of the past samplers.

Your task, for PA1, is to create a display with 9 subwindows (not 6, not 12, but 9) and create a variety of displays, a "sampler" of various simple graphics techniques. We will go over some of the basics in class. Inside Macintosh and Toolbox Assistant will give you the information you need to do any kind of graphics you might want to try.

THE CODE BELOW IS POORLY ORGANIZED. You are to use an improved style that should include at the very least, the following two major changes:

  1. The main() program should be very short and basically call an init function, a run function and a close function. Those functions should do all the work. The run function should contain the even loop and calls to other functions to do the drawing in each of the different windows.
  2. There should be substantial comments in your code, functioning at the top level to explain your strategy and at more detailed levels to explain your strategies for particular pieces of code.

		// First assignment code for COM1370, by RP Futrelle, updated 1/11/98
// File: Sampler demo 1-98.cp.
// Done in C++ for CodeWarrior Pro on Macintosh PPC.
        
        
    #include <stdlib.h>
    #include <Strings.h>
        
        
    WindowPtr  macWindow   = nil;
    Rect    windowRect;
    EventRecord  theEvent;
    WindowPtr windows[6];  // the six windows
        
        
    void init_stuff();  //prototype
    void init_stuff()
      {
       InitGraf(&qd.thePort);   
       InitFonts();
       InitWindows();
       InitCursor();
       TEInit();
      }
        
    WindowPtr NewWin(Rect &R);
    WindowPtr NewWin(Rect &R)
      { return (
      NewCWindow(nil, 
             &R, 
                   nil,
                   true,
                   plainDBox,
                   (WindowPtr)-1L,
                   nil, 
                   nil));
                   
        };
        
    // Generate random number in a range:
    int ran_num_in_range(int low, int high);
    int ran_num_in_range(int low, int high)
      {return (low + rand() % (high - low + 1));}
        
    ************************************************************
        
    main() {
        
      Rect rc;
      PenState ps;
      int menuH = 21;
      
      
      init_stuff();  
      
      // Get the screen size and scale to it.
      int screenW = qd.screenBits.bounds.right;
      //adjust for menu height
      int screenH = qd.screenBits.bounds.bottom - menuH;  
      int windowW = screenW/3;
      int windowH = screenH/2;
      
      // Set up the window array:
      // First row of three
      // #0
      SetRect(&windowRect, 0, menuH, windowW, windowH +menuH);
      windows[0] = NewWin(windowRect);
      // #1
      SetRect(&windowRect, windowW, menuH, 
               2 * windowW, windowH + menuH);
      windows[1] = NewWin(windowRect);
      // #2
      SetRect(&windowRect, 2*windowW, menuH, 
               3 * windowW, windowH + menuH);
      windows[2] = NewWin(windowRect);
      // #3  Start new row, horizontals the same
      SetRect(&windowRect, 0, windowH + menuH, windowW, 
               2 * windowH + menuH);
      windows[3] = NewWin(windowRect);
      // #4
      SetRect(&windowRect, windowW, windowH + menuH, 
               2 * windowW, 2 * windowH +menuH);
      windows[4] = NewWin(windowRect);
      // #4 
      SetRect(&windowRect, 2 * windowW, windowH + menuH, 
               3 * windowW, 2 * windowH +menuH);
      windows[5] = NewWin(windowRect);
        
        
        
      SetPort(windows[0]);  // where we draw 
      
      MoveTo(30,30); // local coordinates
      
      // Either of these two forms will work (about strings: A:67-68)
      // The first converts the C-string to a Pascal string
      
      DrawString("\pClick in any of 6 windows to quit.");
      
      // The second uses the CW lower-case function name 
      //  that accepts C-strings
      
      SetPort(windows[1]);
      //drawstring(myString);
      
      // and underline the string, IQ: 3-49 -- 3-52
      MoveTo(30,34);
      LineTo(110,34);
      
      // Now, some more graphics, a filled oval (in local coordinates)
      
      SetPort(windows[4]);  
      ForeColor(yellowColor);  // light on a grey-level screen, IQ: 3-142.
      
      // args are: SetRect(&rectvar, left, top, right, bottom)
      
      SetRect(&rc, 100, 50, 170, 80);  // IQ: 3-53
      PaintOval(&rc);  // draw filled oval, IQ: 3-69
        
      ForeColor(blackColor);  // reset to black
      
      // Draw some random lines, with random colors.
      
      SetPort(windows[3]);
      
      srand(2);
      
      for(int i = 0; i < 50 ; i++)
        {RGBColor myc;
         myc.red = ran_num_in_range(0x4000, 0xFFFF);
         myc.green = ran_num_in_range(0x4000, 0xFFFF);
         myc.blue = ran_num_in_range(0x4000, 0xFFFF);
         
         MoveTo(ran_num_in_range(0, windowW), 
                ran_num_in_range(0, windowH));
         LineTo(ran_num_in_range(0, windowW), 
                ran_num_in_range(0, windowH));
        };
         
        
      // draw a number of pixels, fading to white.
      // This works fine.  Should be built into a routine.
      
      SetPort(windows[5]);
      
      RGBColor myc;
      myc.red = 0xFFFF;  // keep this one maxed
      myc.green = 0x0000;  // and vary these two
      myc.blue = 0x0000;
      int grad = 640;
      
      // The first one is done with individual pixels
      for(int j = 50; j < 150; j++)
        {
         for(int i = 0; i < 100; i++)
          { myc.green = i * grad;
             myc.blue = i * grad;
             SetCPixel(i + 50, j, &myc);
           };
         };
      
      // This one is done with lines, with j being 
      //  the horizontal start.
      for(int j = 0; j < 100; j++)
        {
         myc.green = j * grad;
         myc.blue = j * grad;
         RGBForeColor(&myc);
         MoveTo(j + 50, 160);
         LineTo(j + 50, 300);
        };
      
      // The previous non event loop.  
      //while (!Button()) {}
      
      // EVENT LOOP:
      
      FlushEvents(everyEvent,0);  // Start with a clean slate.
      
      while(true)
        {WaitNextEvent(everyEvent, &theEvent, 6, nil);
         if(theEvent.what == mouseDown)
           {for(int i = 0; i < 6; i++)
            DisposeWindow(windows[i]);
            break;};
         }
        
      return(0);
      
    }