codeworld-base-0.2.0.0: Replacement base module for CodeWorld

Safe HaskellNone
LanguageHaskell98

Extras.Cw

Contents

Description

Additional entry points and graphical primitives for CodeWorld.

To use a function defined in this module, you must begin your code with this line:

import Extras.Cw(function)

where instead of function you write the actual name of the function you want to use.

You can specifiy more than one function. For example, if you want to use 3 functions, then instead of writing 3 separate import lines, you can write this:

import Extras.Cw(function1,function2,function3)

All the functions defined in this module could be implemented directly in CodeWorld, as no internal features of the CodeWorld system are used in their implementation. These functions are provided to save you the tedium of having to add them to your code. To keep this module as small as possible, functions are added to this module only when it has been observed that several people keep adding variations of them to their respective codes.

Synopsis

Animation convenience functions

between :: (Number, Number, Number, Picture) -> Picture #

The expression between(t,start,stop,drawing) will show the given drawing when the time t is between start and stop

beyond :: (Number, Number, Picture) -> Picture #

The expression beyond(t,start,drawing) will show the given drawing when the time t is beyond the start time

saw :: (Number, Number) -> Number #

The expression saw(t,p) is 0 when t=0, increases up to 1 when t=p/2, and then decreases back to 0 when t=p. This increasing and decreasing when t goes from 0 to p is called an oscillation of period p. The oscillations will keep repeating, so that the function is 0 when t is 0,p,2p,3p,4p,5p,... and it is 1 when t is p/2, 3p/2, 5p/2, 7p/2, ...

Functions for accessing the points in a curve

openCurvePoints :: ([Point], Number) -> [Point] #

openCurvePoints(controls,distance) is a list of points that approximate a curve passing through the given controls. A variable number of points is generated in such a way that the distance between them is approximately the given distance.

closedCurvePoints :: ([Point], Number) -> [Point] #

This function is similar to openCurvePoints, but the points approximate a closed curve passing through the given controls.

Layout

pageFromTexts :: [Text] -> Picture #

A picture that represents the given list of texts, so that each text in the list is shown in a separate line. Lines start at the top left corner of the output window and grow downward. Each line of text can fit 66 characters, and 40 lines can fit in a single page. The lettering is shown in monospaced font.

Example:

program = slideshow(pages)
  where
  pages = foreach(gs,pageFromTexts)
  gs = groups(ls,40)
  ls = foreach(result,\g -> joinedWith(g,", "))
  result = groups(forloop(1,(<= 2000000),(+ 1),printed),7)

The example above shows two million numbers in 7143 pages, so that each page has 40 lines, each of which has 7 numbers. This example uses forloop and foreach from Extras.Util.

grid :: ((Number, Number) -> Picture, Number, Number) -> Picture #

A grid(cell,rows,columns) is a grid with the given number of rows and columns, where the rows are numbered top to bottom (top row is row 1) and the columns are numbered left to right (leftmost column is column 1). The user needs to specify what to draw at each cell in the grid. The given function cell should specify a 20 by 20 picture for each row and column, where the first argument is the row number, and the second argument is the column number:

cell(row,col) = fullSizePicture

Each full size picture will be scaled to fit within the corresponding cell. Look at the example in the documentation of sprite to see how to use it.

sprite :: (Picture, Number, Number) -> (Number, Number) -> Picture #

A sprite(picture,rows,columns) creates a function that can be used to place the given picture of a sprite into a grid with the given number of rows and columns. The created function needs two arguments: the row and the column at which you want to show the sprite. The picture of the sprite should be a full size picture (20x20), which will be scaled to fit the corresponding cell in the grid.

Example:

import Extras.Cw(saw,grid,sprite)
import Extras.Util(printedPoint)

program = animationOf(movie)

movie(t) = sprite1(row,col) & background
  where
  -- Jump between rows 1 and 10 every 100 seconds
  row = 1 + truncation(10*saw(t,100))
  -- Move smoothly between cols 1 and 10 every 10 seconds
  col = 1 + 9*saw(t,10)

sprite1 = sprite(pic,10,10)
  where
  pic = rotated(eks,45)
  eks = solidRectangle(10,1) & solidRectangle(1,10)

background = grid(cell,10,10)
    where
    cell(row,col) = dilated(lettering(printedPoint(row,col)),5)
                  & rectangle(19,19)

overlays :: (Number -> Picture, Number) -> Picture #

overlays(fig,n) is a shortcut for fig(1) & fig(2) & ... & fig(n)

underlays :: (Number -> Picture, Number) -> Picture #

underlays(fig,n) is a shortcut for fig(n) & fig(n-1) & ... & fig(1)

squareFrame :: Number -> Picture #

A white frame around the standard 20x20 output window that covers anything that may spill over. The argument is the thickness of the frame border.

Graphing

graphed :: (Picture, Number, Number) -> Picture #

The given picture scaled by the given scaling factors and shown in a graph that zooms along with the picture. For example, a scaling factor of 2 in either the X direction or the Y direction means that the picture will show twice as big as usual in that direction.

Example 1:

program = animationOf(movie)
    where movie(t) = let zoom = 1/(1 + t^3)
                     in  graphed(circle(5*t^3), zoom, zoom)

Example 2:

program = guiDrawingOf(widgets,draw)
  where
  widgets = [ withConversion(zooming, slider("zoomX",-8,9))
            , withConversion(zooming, slider("zoomY",-8,7))
            ]
  zooming(v) = 2^(-8 + v*16)
  draw([zoomX,zoomY]) = graphed(manyCircles, zoomX, zoomY)
  manyCircles = pictures([circle(n) | n <- [1..100]])

Example 1 shows a circle that grows forever, while the graph keeps adjusting the scale so that it fits within the output. Example 2 shows a graph with 100 circles. It uses the function guiDrawingOf from Extras.Widget.

wideGraphed :: (Number, Picture, Number, Number) -> Picture #

This function is similar to graphed, but it creates a graph that is as wide as specified by the first parameter. Thus, wideGraphed(width,pic,sx,sy) creates a graph that is width units wide and 20 units high.

customGraphed :: (Number, Number, Picture, Number, Number) -> Picture #

This function is similar to graphed, but it creates a graph that is as wide and as high as specified by the first two parameters. Thus, customGraphed(width,height,pic,sx,sy) creates a graph that is width units wide and heighth units high.

Drawing Trees

data Tree a #

A Tree is built by repeated applications of the -< operator.

Example:

import Extras.Cw((-<),tree,treeDepth,treeWidth)

program = drawingOf(picture)
  where
  w = 3
  picture = tree(t1,draw,w) & translated(lettering(info),5,-9)
    where
    draw(node) = lettering(node)
               & colored(solidRectangle(0.8*w,1),translucent(light(red)))
    info = joined([ "width: ", printed(treeWidth(t1))
                  , ", depth: ", printed(treeDepth(t1))
                  ])
    t1 = "hello" -< [ "a" -< [ "a1" -< []
                             , "a2" -< []
                             ]
                    , "b" -< [ "b1" -< [ "b11" -< []
                                       , "b12" -< [ "b121" -< []
                                                  , "b122" -< [ "b1221" -< []
                                                              , "b1222" -< []
                                                              , "b1223" -< []
                                                              ]
                                                  ]
                                       ]
                             , "b2" -< [ "b21" -< []
                                       , "b22" -< []
                                       , "b23" -< []
                                       ]
                             ]
                    , "c" -< []
                    , "d" -< []
                    ]

(-<) :: a -> [Tree a] -> Tree a #

A tree that has the given node at the head and the given list of trees as children nodes.

Example: A binary tree

 program = drawingOf(tree(t,\n -> lettering(printed(n)),1.2))

 t = 1 -< [ 2 -< [ 4 -< [  8 -< [ 16 -< []
                                , 17 -< []
                                ]
                        ,  9 -< [ 18 -< []
                                , 19 -< []
                                ]
                        ]
                 , 5 -< [ 10 -< [ 20 -< []
                                , 21 -< []
                                ]
                        , 11 -< [ 22 -< []
                                , 23 -< []
                                ]
                        ]
                 ]
          , 3 -< [ 6 -< [ 12 -< [ 24 -< []
                                , 25 -< []
                                ]
                        , 13 -< [ 26 -< []
                                , 27 -< []
                                ]
                        ]
                 , 7 -< [ 14 -< [ 28 -< []
                                , 29 -< []
                                ]
                        , 15 -< [ 30 -< []
                                , 31 -< []
                                ]
                        ]
                 ]
          ]

treeDepth :: Tree a -> Number #

The depth of the given tree

treeWidth :: Tree a -> Number #

The width of the given tree

tree :: (Tree a, a -> Picture, Number) -> Picture #

A Picture of the given tree, where each node is drawn according to the given function. It is assumed that each node is no wider than the given width. Otherwise, overlap between nodes will occur.

New entry points

slideshow :: [Picture] -> Program #

A slide show of the given list of pictures with keyboard and mouse navigation. The following keys can be used to control the slide show:

  • Restart the slide show: R
  • Go to the next slide: N, space bar, Enter, Page Down
  • Go to the previous slide: P, Backspace, Page Up

The given list of pictures must be finite. When the last slide is reached, the slide show will wrap, so that the first slide is shown next. This function cannot be used for showing undelimited step-motion animations.

autoSlideshow :: ([Picture], Number) -> Program #

A slide show that automatically cycles through the list of given pictures. Each picture will be shown for the given number of seconds before advancing to the next picture.

Entry points with randomization

All the randomized versions of entry points provided in this module use the same mechanism to handle random numbers. Before your code runs, the CodeWorld system generates a very large list of random numbers, which is passed to your code. For efficiency, the list is generated on demand, so that only those random numbers actually used in your code are generated. All the random numbers that the system generates are between 0 (included) and 1 (excluded).

Using the randomized versions is very simple. When you click on the output window, the drawing or animation that is currently being shown is replaced with a new one that uses different random numbers. You can keep clicking on your output to see different randomized outputs of your program.

When you write a program that uses the randomized versions, instead of providing a definition of a drawing, you must provide a definition of a function that takes in the list of random numbers as input and generates your drawing as output. Inside your function, you can use as many random numbers as you want.

randomDrawingOf :: ([Number] -> Picture) -> Program #

A randomized version of drawingOf

Example:

program = randomDrawingOf(draw)
draw(random) = solidRectangle(width,height)
    where
    width  = 1 + 9 * random#1
    height = 1 + 9 * random#2

The example above will show a different rectangle every time you click on the output. The width and the height will vary randomly between 1 and 10 units.

randomAnimationOf :: (([Number], Number) -> Picture) -> Program #

A randomized version of animationOf

Example:

program = randomAnimationOf(movie)
movie(random,t) = rotated(solidRectangle(width,height),45*t)
    where
    width  = 1 + 9 * random#1
    height = 1 + 9 * random#2

The example above will show a random rectangle that rotates around the origin. When you click on the output, a different random rectangle will be shown, which will also be rotating around the origin.

randomSlideshow :: ([Number] -> [Picture]) -> Program #

A randomized version of slideshow

randomAutoSlideshow :: ([Number] -> [Picture], Number) -> Program #

A randomized version of autoSlideshow