MacCASOutreach / graphicsvg / GraphicSVG.EllieApp

The methods in this library are analogous to those in GraphicSVG.App; however, they are built upon GraphicSVG.ellieApp for compatibility with that platform.

Apps

graphicsApp : { view : GraphicSVG.Collage () } -> GraphicsApp

The simplest way to render graphics to the screen. These graphics will be static (they don't move) and cannot be interacted with. This is great for beginners or for when only need static graphics are needed. Note that your view function is bare, with no parameters: view = collage 500 500 [ circle 10 |> filled red ][ circle 10 |> filled red ] graphicsApp takes a parameter like { view = view } so the main program that would get the whole thing started for the above view would be: main = graphicsApp { view = view }


type alias GraphicsApp =
GraphicSVG.EllieApp () () ()

This type alias is only used as a target for a user main type signature to make the type signature more clear and concise when main calls graphicsApp: main : GraphicsApp userMsg main = graphicsApp { view = view } Note that userMsg can be anything as no messages are used in this type of program.

notificationsApp : { model : userModel, view : userModel -> GraphicSVG.Collage userMsg, update : userMsg -> userModel -> userModel } -> NotificationsApp userModel userMsg

Like graphicsApp, but you can add interactivity to your graphics by using the notify* functions. This allows you to learn Elm's architecture in a fun way with graphics. Note that your view function needs a model parameter now, which in this example is the colour of the shape: view model = collage 500 500 [ circle 10 |> filled model |> notifyTap Change ] notificationsApp takes a parameter like: { model = model , view = view , update = update } so the functions that would be required to make the above view function work are as follows: type Msg = Change update msg model = case msg of Change -> green main = notificationsApp {
model = red -- causes circle to start red , update = update -- function which changes the model , view = view } which will cause the drawn red circle to change to green the first time it is mouse clicked or tapped.


type alias NotificationsApp userModel userMsg =
GraphicSVG.EllieApp () userModel (HiddenMsg userMsg)

This type alias is only used as a target for a user main type signature to make the type signature more clear and concise when main calls notificationsApp: main : NotificationsApp Model MyMsg main = notificationsApp { model = init, update = update, view = view } where Model is the type alias of the user persistent model, and MyMsg is the name of the user defined message type; if other names are used, they can be substituted for these names.

gameApp : InputHandler userMsg -> { model : userModel, view : userModel -> GraphicSVG.Collage userMsg, update : userMsg -> userModel -> userModel, title : String } -> GameApp userModel userMsg

Automatically maps time and keyboard presses to your program. This should be all you need for making complex interactive games and animations. gameApp takes two parameters: one is your own type of InputHandler message which will be automatically called each time the browser window is refreshed (30 times per second) of the form Float -> GetKeyState -> UserMsg and the other is

{
  model = model
, view = view
, update = update
}
````
The following program causes animation of the drawn line,
causing it to spin around; also, a press of the "r" key
causes the direction of the spin to reverse:

type Msg = Tick Float GetKeyState

type alias Model = { angle : Float, speed : Float }

init = { angle = 0, speed = 1 }

update msg model = case msg of Tick _ ( keys, _, _ ) -> case keys (Key "r") of JustDown -> { model | angle = model.angle - model.speed , speed = -model.speed } _ -> { model | angle = model.angle + model.speed }

view model = collage 500 500 [ line ( 0, 0 ) ( 250, 0 ) |> outlined (solid 1) green |> rotate (degrees model.angle) ]

main = gameApp Tick { model = init , update = update , view = view }



<a name="//apple_ref/cpp/Type/GameApp" class="dashAnchor"></a>

<div style="padding: 0px; margin: 0px; height: 1px; background-color: rgb(216, 221, 225);"></div>

<div class="mono"><br /><strong> <span class="green"> type alias </span><a class="mono" name="GameApp" href="#GameApp">GameApp</a></strong> userModel userMsg<span class="grey"> =</span> </div> 

    GraphicSVG.EllieApp () ( userModel
    , HiddenModel userMsg ) (HiddenMsg userMsg
    }

 This type alias is only used as a target for a user `main` type signature to make
the type signature more clear and concise when `main` calls `gameApp`:

main : GameApp Model Msg main = gameApp Tick { model = init , update = update , view = view }

where `Tick` is the message handler called once per browser window update,
`Model` is the type alias of the user persistent model, and
`Msg` is the name of the user message type; if other names are used,
they can be substituted for these names.


# Time and Keyboard interactions

<a name="//apple_ref/cpp/Type/InputHandler" class="dashAnchor"></a>

<div style="padding: 0px; margin: 0px; height: 1px; background-color: rgb(216, 221, 225);"></div>

<div class="mono"><br /><strong> <span class="green"> type alias </span><a class="mono" name="InputHandler" href="#InputHandler">InputHandler</a></strong> userMsg<span class="grey"> =</span> </div> 

    Basics.Float -> GetKeyState -> userMsg

 The `InputHandler` type alias descripts a message that contains a Float representing the time in seconds from
the time the program started and the `GetKeyState` type alias used for returning key actions.
This type is used for by the `gameApp` fully interactive application.


<a name="//apple_ref/cpp/Type/GetKeyState" class="dashAnchor"></a>

<div style="padding: 0px; margin: 0px; height: 1px; background-color: rgb(216, 221, 225);"></div>

<div class="mono"><br /><strong> <span class="green"> type alias </span><a class="mono" name="GetKeyState" href="#GetKeyState">GetKeyState</a></strong><span class="grey"> =</span> </div> 

    ( Keys -> KeyState
    , ( Basics.Float
    , Basics.Float )
    , ( Basics.Float
    , Basics.Float ) 
    )

 `GetKeyState` returns a triple where the first argument is of type `Keys -> KeyState`
so you can ask if a certain key is pressed. The other two are tuples of arrow keys and
WASD keys, respectively. They're in the form (x,y) which represents the key presses
of each player. For example, (0,-1) represents the left arrow (or "A") key, and (1,1)
would mean the up (or "W") and right (or "D") key are being pressed at the same time.


<a name="//apple_ref/cpp/Union/Keys" class="dashAnchor"></a>

<div style="padding: 0px; margin: 0px; height: 1px; background-color: rgb(216, 221, 225);"></div>

<div class="mono"><br /><strong> <span class="green"> type </span><a class="mono" name="Keys" href="#Keys">Keys</a></strong><br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">=</span>&nbsp;Key String<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;Backspace<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;Tab<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;Enter<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;Shift<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;Ctrl<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;Alt<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;Caps<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;LeftArrow<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;UpArrow<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;RightArrow<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;DownArrow<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;Delete<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;Space</div>

 Includes all the regular keys. Ask for letters and numbers using `Key String`, e.g. `Key "a"` or `Key "3"`.


<a name="//apple_ref/cpp/Union/KeyState" class="dashAnchor"></a>

<div style="padding: 0px; margin: 0px; height: 1px; background-color: rgb(216, 221, 225);"></div>

<div class="mono"><br /><strong> <span class="green"> type </span><a class="mono" name="KeyState" href="#KeyState">KeyState</a></strong><br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">=</span>&nbsp;JustDown<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;Down<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;JustUp<br />&nbsp;&nbsp;&nbsp;&nbsp;<span class="grey">|</span>&nbsp;Up</div>

 The possible states when you ask for a key's state:

  - `JustDown` is the frame after the key went down (will show up exactly once per press)
  - `Down` is a press that is continuing for more than one frame
  - `JustUp` is the frame after the key went up / stopped being pressed (will show up exactly once per press)
  - `Up` means the key is not currently being pressed nor was it recently released



# Barebones ellieApp with keyboard and time

<a name="//apple_ref/cpp/Type/EllieAppWithTick" class="dashAnchor"></a>

<div style="padding: 0px; margin: 0px; height: 1px; background-color: rgb(216, 221, 225);"></div>

<div class="mono"><br /><strong> <span class="green"> type alias </span><a class="mono" name="EllieAppWithTick" href="#EllieAppWithTick">EllieAppWithTick</a></strong> flags userModel userMsg<span class="grey"> =</span> </div> 

    GraphicSVG.EllieApp flags ( userModel
    , HiddenModel userMsg ) (HiddenMsg userMsg
    }

 This type alias is only used as a target for a user `main` type signature to make
the type signature more clear and concise when `main` calls `gameApp`:

main : EllieAppWithTick Model Msg main = ellieAppWithTick Tick { model = init , update = update , view = view , subscriptions = subscriptions }

where `Tick` is the message handler called once per browser window update,
`Model` is the type alias of the user persistent model, and
`Msg` is the name of the user message type; if other names are used,
they can be substituted for these names.


<a name="//apple_ref/cpp/Function/ellieAppWithTick" class="dashAnchor"></a>

<div style="padding: 0px; margin: 0px; height: 1px; background-color: rgb(216, 221, 225);"></div>

<strong> <a class="mono" name="ellieAppWithTick" href="#ellieAppWithTick">ellieAppWithTick</a> <span class="grey"> :</span> </strong><span class="mono">InputHandler userMsg <span class="grey">-&gt;</span> { init : flags <span class="grey">-&gt;</span> ( userModel, Platform.Cmd.Cmd userMsg ), update : userMsg <span class="grey">-&gt;</span> userModel <span class="grey">-&gt;</span> ( userModel, Platform.Cmd.Cmd userMsg ), view : userModel <span class="grey">-&gt;</span> { title : String, body : GraphicSVG.Collage userMsg }, subscriptions : userModel <span class="grey">-&gt;</span> Platform.Sub.Sub userMsg } <span class="grey">-&gt;</span> EllieAppWithTick flags userModel userMsg</span>


A GraphicSVG.ellieApp with automatic time and keyboard presses passed into the update function.
`ellieAppWithTick` takes two parameters: one is your own type of `InputHandler` message
which will be automatically called each time the browser window is refreshed
(30 times per second)
of the form `Float -> GetKeyState -> UserMsg` and the other is

{ init = model , view = view , update = update , subscriptions = subscriptions } where init is the model and initial commands, view is a collage and a title, update is the usual update function with commands, and subscriptions are things which you'd like to be notified about on a regular basis (e.g. changes in time, incoming WebSocket messages)