Glimmr Canvas Animation

version 1/111030 by Erik Temple

  • Home page
  • Beginning
  • Previous
  • Next



  • Example: ** Maps of Murder - The user interface is an ideal place to experiment with animation effects. Here, we sketch a kind of image browser for an IF game. Four thumbnail versions (the map illustrations from Dell Map-Back murder mysteries) are displayed in a grid. We can click on any one of them to maximize it; we use two animation tracks to animate the maximization, scaling the image to full size while moving it to the center of the window. Click on the cover again to return it to the original thumbnail size and location.

    This example illustrates the "stacking" of animation tracks to achieve more complex effects; in this case we are stacking motion and scaling animations, with an easing effect lending a subtle arc to things. The example also demonstrates how we can test the animation state of an object so as to modify behavior appropriately, and more generally it shows how to write generalized code--we could add 20 more covers without changing any of the core code.

        "Maps of Murder"

        Include Glimmr Graphic Hyperlinks by Erik Temple.
        Include Glimmr Canvas Animation by Erik Temple.


        The graphics-window is a graphics g-window spawned by the main-window. The position of the graphics-window is g-placeright. The measurement of the graphics-window is 50. The back-colour of the graphics-window is g-black. The graphics-window is g-graphlinked.

        The graphics-canvas is a g-canvas. The canvas-width is 462. The canvas-height is 652. The associated canvas of the graphics-window is the graphics-canvas.

        When play begins:
            open up the graphics-window.
        
        There is a room.


        [-------------------------------]

        Figure of Whos Calling is the file "WhosCalling.png".
        Figure of Feathered Serpent is the file "FeatheredSerpent.png".
        Figure of Hidden Ways is the file "HiddenWays.png".
        Figure of Mourned Sunday is the file "MournedOnSunday.png".

        Figure of Transparent Overlay is the file "Overlay.png".

        [-------------------------------]

    We create a new kind of sprite, the "cover-image", and give it a new coordinate property, the "rightful position". This is the position to which the cover should return after it has been maximized. Note that we are showing the covers at half size initially; they will be shown at full size on maximization.

    When a cover has been maximized, we place a semi-transparent overlay over the other images so that they don't distract from the player's view of the enlarged sprite. (This overlay is itself a sprite.) The grid of covers is on display layer 1. The overlay, when it appears, will be drawn on layer 2, and the cover, when it is maximized is shown on layer 4. Layer 3 is used for sprites that are in the process of minimization.

        A cover-image is a kind of sprite. A cover-image is center-aligned. Some cover-images are defined by the Table of Covers.

        The associated canvas of a g-element is usually the graphics-canvas. The graphlink status of a cover-image is usually g-active. A cover-image is publically-named.

        A cover-image has a list of numbers called the rightful position.

        The linked replacement-command of a cover-image is usually "Toggle [the current graphlink]".

        Table of Covers
      cover-image  image-ID  origin  
      the first cover  Figure of Whos Calling  {126, 173}  
      the second cover  Figure of Feathered Serpent  {337, 173}  
      the third cover  Figure of Hidden Ways  {126, 479}  
      the fourth cover  Figure of Mourned Sunday  {337, 479}  


        The transparent overlay is a sprite. The image-ID is Figure of Transparent Overlay. The origin is {0, 0}. The display status is g-inactive. The display-layer is 2.

        [-------------------------------]

        A cover-image can be maximized.

    We define four tracks. Why four? It will be possible to click on another cover to maximize it while we have another cover already enlarged; we have four tracks so that both can move at the same time (using two tracks each). The primary tracks maximize, while the secondary tracks minimize the cover back to the grid.

    Note that the primary zooming track has an easing equation (cubic easing out) applied. Combined with the motion, this creates a rather subtle to the overall motion of maximization. We don't apply the easing to the secondary track--it's a bit too distracting for the return journey, which is after all about minimization.

    Also note the callback on the secondary zooming track. This moves the cover back to display layer 1 once it has finished moving back to its original position in the grid. By waiting until the end to move it to layer 1, we avoid seeing it move behind the semitransparent overlay. This is the last stage in a series of layer manipulations; see the carry out toggling rule below for the other layering logic.

        The primary zooming track, the primary motion track, the secondary zooming track, the secondary motion track are animation tracks.

        The animation-callback of the secondary zooming track is "[@ now the display-layer of the animation-target of the secondary zooming track is 1]".

        The easing of the primary zooming track is the cubic easing out rule.
        [The easing of the secondary zooming track is the cubic easing in rule.]

        The resting scaling ratio is a real number variable. The resting scaling ratio is 0.5000.
        The display scaling ratio is a real number variable. The display scaling ratio is 1.000.
        The display position is a list of numbers variable. The display position is {231, 326}.

    All of the animation action takes place in the carry out toggling rule. We first check to see whether the secondary zooming track is active; if it is, that means that the sprite that was clicked on was already returning to the original grid position, and we need to deactivate that animation so that we can maximize it again (later on in the same rule).

    Next we check to see whether there is already an image in the central position. If so, we need to start reducing it. We change its display layer so that it is above the semitransparent overlay, but below whichever sprite is actually the target of the player's click (which will be the noun supplied to the toggling action), then we animate it using the secondary tracks to return it to its original position and size. If this happens to be the image that we clicked on, we stop the action--we don't need to do any more, since clicking on an maximized image just toggles it back to the grid.

    Finally, we deal with the case in which a small sprite is clicked on. We first move it to the uppermost layer so it overlays everything else, then we activate the semitransparent overlay and animate the primary tracks to maximize the sprite that was clicked.

    All this may seem a bit complex. It does requiring some planning, and it especially helps to work out the layers you need in advance, but you will also undoubtedly also end up tweaking things as you test your original design.

    Note that the implementation of this as a standard action, particularly with the superfluous textual reports on what's been maximized and what's been minimized, is probably a poor design choice!

        Toggling something is an action applying to one visible thing. Understand "toggle [any thing]" as toggling something.

        Carry out toggling something:
            if the animation-flag of the secondary zooming track is g-active:
                [the sprite we clicked on is already reducing; stop that motion so we can maximize again]
                deactivate the secondary zooming track;
                deactivate the secondary motion track;
            if there is a maximized cover-image:
                [There is already a maximized sprite; we need to minimize it]
                let item be a random maximized cover-image;
                now item is not maximized;
                now the display-layer of item is 3;
                animate the secondary zooming track as a zooming animation targeting the item and ending at the resting scaling ratio at 24 fps with duration of 8 frames;
                animate the secondary motion track as a motion animation targeting the item and ending at the rightful position of the item at 24 fps with duration of 6 frames;
                now the display status of the transparent overlay is g-inactive;
                if item is the noun, stop the action;[We clicked on the already maximized image, so we don't need to enlarge it; the minimizing motion we've triggered is all that is called for.]
            now the display-layer of the noun is 4;
            now the noun is maximized;
            now the display status of the transparent overlay is g-active;
            animate the primary zooming track as a zooming animation targeting the noun and ending at the display scaling ratio at 24 fps with duration of 8 frames;
            animate the primary motion track as a motion animation targeting the noun and ending at the display position at 24 fps with duration of 6 frames.
        
        Report toggling something:
            say "[The noun] has been [if the noun is maximized]maximized[otherwise]minimized[end if]."


        When play begins:
            say "This example demonstrates the use of multiple 'tracks' to provide complex animation effects. Click on an image to zoom in and move it to the center. Click again to toggle. You can also click on a second cover while the first is zoomed; both will animate smoothly into the appropriate positions.[paragraph break]The images are the back covers of Dell Map-Back mystery books. The Map-Back was a prototype of and possibly a direct influence on the 'feelies' that accompanied classic Infocom games such as [i]Deadline[/i]. These images are from Marble River's Ephemera; you can see the front covers at http://marbleriver.blogspot.com/2010/01/backs-dell-more-map.html.";
            repeat with item running through cover-images:
                now the rightful position of the item is the origin of the item;
                now the scaling factor of the item is the resting scaling ratio.
            
        [Understand "show me source" or "source" or "source code" as a mistake ("
        Carry out toggling something:[line break] if the animation-flag of the secondary zooming track is g-active:[line break] [i][bracket]the sprite we clicked on is already reducing; stop that motion so we can maximize again[close bracket][/i][line break] deactivate the secondary zooming track;[line break] deactivate the secondary motion track;[line break] if there is an maximized cover-image:[line break] [i][bracket]There is already a maximized sprite; we need to minimize it[close bracket][/i][line break] let item be a random maximized cover-image;[line break] now item is not maximized;[line break] now the display-layer of item is 3;[line break] animate the secondary zooming track as a zooming animation targeting the item and ending at the resting scaling ratio at 24 fps with duration of 8 frames;[line break] animate the secondary motion track as a motion animation targeting the item and ending at the rightful position of the item at 24 fps with duration of 6 frames;[line break] now the display status of the transparent overlay is g-inactive;[line break] if item is the noun, stop the action;[i][bracket]We clicked on the maximized image, so we don't need to enlarge it; the reduction motion we've already set in motion is sufficient.[close bracket][/i][line break] now the display-layer of the noun is 4;[line break] now the noun is maximized;[line break] now the display status of the transparent overlay is g-active;[line break] animate the primary zooming track as a zooming animation targeting the noun and ending at the display scaling ratio at 24 fps with duration of 8 frames;[line break] animate the primary motion track as a motion animation targeting the noun and ending at the display position at 24 fps with duration of 6 frames.").]