Glimmr Canvas-Based Drawing

version 2/101030 by Erik Temple

  • Home page
  • Beginning
  • Previous
  • Next

  • Example: ** Wandering Rhodes - We want to show the player's location on a map, but the full map is so large that it leaves us unable to see details. This example explores one solution to this problem, displaying the full map in one graphics window, and showing a detail view, an inset, in a second window.

    This example illustrates one way to do this, by displaying the same canvas in two different windows, with each window having different framing parameters. We have a larger graphics window on the left, displaying the full map, scaled to fit in the window. A smaller window on the right displays a close-up of the map, centered on the player's location.

    Because this by itself is too easy, we also provide the ability to "TOGGLE" between two means of showing the player's location: a placemarker, a la Google Maps, and a box on the full map that marks the area shown in the inset view. The latter will also serve to illustrate how we can dynamically resize elements based on the size of our windows.

        "Wandering Rhodes"

        Include Glimmr Canvas-Based Drawing by Erik Temple.

        Figure of Rhodes is the file "Rhodes.jpg".
        Figure of Placemark is the file "Placemark.png".

        The graphics-window is a graphics g-window spawned by the main-window. The measurement of the graphics-window is 50. The position of the graphics-window is g-placeabove. The associated canvas of the graphics-window is the graphics-canvas.

        The graphics-canvas is a g-canvas. The background image of the graphics-canvas is Figure of Rhodes.

    We use the graphics-window to display the full map view, and the dimensions of the graphics-canvas are determined by the map (Figure of Roads, used as the background image of the canvas). We also define the closeup-window, the g-window that will show the inset. Note that we assign the same canvas to the closeup-window as to the main graphics-window. We also set the closeup-window to a scaling factor of 1.0000 (i.e., 100%), so that the map will always be displayed without scaling.

    We then assign x,y coordinates to each room. These coordinates will determine where the placemarker will be placed, and will also serve as the center of the frame of the closeup-window; that is, we will display the graphics-canvas in the closeup-window such that the window is centered over this point. This is done using the window-framing adjustment activity and the "center the framing..." phrase.

        The closeup-window is a graphics g-window spawned by the graphics-window. The position is g-placeright. The measurement is 25. The associated canvas is graphics-canvas.

        The arbitrary scaling factor of the closeup-window is 1.0000.

        When play begins:
            open up graphics-window;
            open up the closeup-window;
        [After printing the banner text:
            say "[line break]This example for the Glimmr Canvas-Based Drawing extension demonstrates the display of a single canvas in two different windows. The inset window at right shows a detail view of the main map window at left. The main window scales the canvas to fit, while the inset window always displays it at 100% of actual size, zoomed to the specific location shown by the placemarker in the main window.[paragraph break]The placemarker can be toggled between a pointer and a box the same size as the inset: Type TOGGLE at the command line to change it.[paragraph break]"]

        A room has a list of numbers called the origin. The origin is usually {0, 0}.
        Some rooms are defined by the Table of Room Origins.

        For window-framing adjustment of the closeup-window:
            center the framing of closeup-window on the origin of the location;
            continue the action.

    We offer the player the choice to display the current location on the map using either a placemarker (a pointer), or a rectangle that reflects the area of the larger map that is displayed in the closeup-window; the former is implemented as a sprite/image, while the latter is a box primitive. As with other maps, we update the status of these primarily in the carry out looking rules, since the looking rules are always consulted when the player moves between rooms. The currently chosen display option is put into a global variable called the placemarker, which we will use to determine how the properties of the element should be updated.

        The associated canvas of a g-element is the graphics-canvas.

        Pointer is a sprite. The image-ID is Figure of Placemark. The pointer is center-aligned.

        Map Inset is a box primitive. The tint is g-White. The display status is g-inactive. The line-weight is 2.

        Toggling view is an action applying to nothing. Understand "toggle" or "toggle map" or "toggle placemarker" as toggling view.

        The placemarker is a g-element variable. The placemarker is the pointer.

        Carry out toggling view:
            if the placemarker is the pointer:
                now the placemarker is the map inset;
                activate the placemarker;
                deactivate pointer;
                now the placemarker is the pointer;
                activate the placemarker;
                deactivate map inset;
            refresh windows;
            say "The placemarker will now be displayed [if the placemarker is the pointer]as an image[otherwise]using a box to depict the area displayed in the closeup window[end if]."

        Carry out looking:
            follow the refresh windows rule;
            continue the action.

    We don't want to display the marker in the closeup-window, so we simply skip it during the drawing sequence for that window (closeup-window placemarker rule). We then use the drawing active elements activity as a hook for calculating the origins (and endpoint) of the placemarker elements. This activity is a good place for this since it is the activity that controls the scaling and drawing of all elements.

    The calculation for the map inset element, which is the box primitive that outlines on the large map the area displayed in the closeup-window, is more interesting (see the map inset placement rule). This calculation (the map inset placement rule) uses the room coordinates, the dimensions of the canvas, and the dimensions of the closeup-window to calculate the placement and sizing of the map inset. Remember that the origin and endpoint are actually lists of numbers, hence the need to access each entry individually, as seen in the map inset placement rule.

    Note the use of "continue the action" at the end of each rule. Most of the rules and activities in Canvas-Based Drawing end automatically in success, so we need to provide explicit continuation in order to use the rest of the rulebook. In this case, the drawing the active elements activity needs to go on to actually draw the elements, not just calculate placement.

        Element display rule for the placemarker when the current window is the closeup-window (this is the closeup-window placemarker rule):
            do nothing.

        For drawing the active elements when the placemarker is the pointer (this is the pointer placement rule):
            change the origin of the placemarker to the origin of the location;
            continue the action;

        For drawing the active elements when the placemarker is the map inset (this is the map inset placement rule):
            change entry 1 of the origin of the placemarker to (entry 1 of the origin of the location) - ((width of closeup-window) / 2);
            change entry 2 of the origin of the placemarker to (entry 2 of the origin of the location) - ((height of the closeup-window) / 2);
            change entry 1 of the endpoint of the placemarker to (entry 1 of the origin of placemarker) + (width of closeup-window);
            change entry 2 of the endpoint of the placemarker to (entry 2 of the origin of placemarker) + (height of closeup-window);
            continue the action;

        Table of Room Origins
      room  origin  
      West Tower  {108, 221}  
      East End of Tower Street  {356, 292}  
      West End of Tower Street  {211, 280}  
      Port Fortress  {412, 415}  
      Bell Tower  {585, 204}  
      North Tower  {667, 135}  
      Main Square  {447, 355}  

        West End of Tower Street is east of West Tower. East End of Tower Street is east of West End. Main Square is east of East End. Port Fortress is south of Main Square. Bell Tower is north of Main Square. North Tower is north of Bell Tower.

        The description of a room is "[exits]".

        To say exits:
            say "Exits: ";
            let L be a list of directions;
            repeat with the way running through directions:
                let place be the room way from location;
                if place is a room:
                    add way to L;
            say "[L]. "