eigenwijskids/elm-playground-eigenwijs/13.3.0

NOTE: the latest version is 16.0.0

Eigenwijs.Playground3d.Experimental

Beware that this is a project under heavy construction - We are trying to incrementally work towards a library enabling folks familiar with the 2D Playground, to add 3D elements to a 3D scene, and in this way enabling them to contribute to a collaboratively developed game.

Compatibility with the original Playground library

This library exports the same functions and types except for (for the time being):

  • oval, pentagon, hexagon, octagon (just some grunt work)
  • image
  • Color (Color is imported from the package avh4/elm-color)

The following primitives work in a (slightly) different way:

  • words (are rendered using a pixel font - actually Mogee from the kuzminadya/mogeefont package)
  • move (takes an additional z-coordinate)
  • Shape (also adds a z-coordinate, and has roll, pitch, yaw instead of only a single angle)

Playgrounds

picture : List Shape -> Program () Picture Msg

Make a picture! Here is a picture of a triangle with an eyeball:

import Playground exposing (..)


main =
    picture
        [ triangle green 150
        , circle white 40
        , circle black 10
        ]
animation : (Time -> List Shape) -> Program () Animation Msg

Create an animation!

Once you get comfortable using picture to layout shapes, you can try out an animation. Here is square that zigzags back and forth:

import Playground exposing (..)


main =
    animation view


view time =
    [ square blue 40
        |> moveX (zigzag -100 100 2 time)
    ]

We need to define a view to make our animation work.

Within view we can use functions like spin, wave, and zigzag to move and rotate our shapes.

(Computer -> memory -> List Shape)
-> (Computer -> memory -> memory)
-> memory
-> Program () (Game memory) Msg

Create a game!

Once you get comfortable with animation, you can try making a game with the keyboard and mouse. Here is an example of a green square that just moves to the right:

import Playground exposing (..)


main =
    game view update 0


view computer offset =
    [ square green 40
        |> moveRight offset
    ]


update computer offset =
    offset + 0.03

This shows the three important parts of a game:

  1. memory - makes it possible to store information. So with our green square, we save the offset in memory. It starts out at 0.
  2. view - lets us say which shapes to put on screen. So here we move our square right by the offset saved in memory.
  3. update - lets us update the memory. We are incrementing the offset by a tiny amount on each frame.

The update function is called about 60 times per second, so our little changes to offset start to add up pretty quickly!

This game is not very fun though! Making a game also gives you access to the Computer, so you can use information about the Mouse and Keyboard to make it interactive! So here is a red square that moves based on the arrow keys:

import Playground exposing (..)


main =
    game view update ( 0, 0 )


view computer ( x, y ) =
    [ square red 40
        |> move x y
    ]


update computer ( x, y ) =
    ( x + toX computer.keyboard
    , y + toY computer.keyboard
    )

Notice that in the update we use information from the keyboard to update the x and y values. These building blocks let you make pretty fancy games!

Shapes

type Shape

Shapes help you make a picture, animation, or game.

Read on to see examples of circle, rectangle, words, image, and many more!

circle : Color -> Number -> Shape

Make circles:

dot =
    circle red 10


sun =
    circle yellow 300

You give a color and then the radius. So the higher the number, the larger the circle.

square : Color -> Number -> Shape

Make squares. Here are two squares combined to look like an empty box:

import Playground exposing (..)


main =
    picture
        [ square purple 80
        , square white 60
        ]

The number you give is the dimension of each side. So that purple square would be 80 pixels by 80 pixels.

rectangle : Color -> Number -> Number -> Shape

Make rectangles. This example makes a red cross:

import Playground exposing (..)


main =
    picture
        [ rectangle red 20 60
        , rectangle red 60 20
        ]

You give the color, width, and then height. So the first shape is vertical part of the cross, the thinner and taller part.

triangle : Color -> Number -> Shape

Make triangles:

triangle blue 50

You give a color and then its size.

polygon : Color -> List ( Number, Number ) -> Shape

Make any shape you want! Here is a very thin triangle:

import Playground exposing (..)


main =
    picture
        [ polygon black [ ( -10, -20 ), ( 0, 100 ), ( 10, -20 ) ]
        ]

Note: If you rotate a polygon, it will always rotate around (0,0). So it is best to build your shapes around that point, and then use move or group so that rotation makes more sense.

snake : Color -> List ( Number, Number, Number ) -> Shape

Make a snake!

3D Shapes

sphere : Color -> Number -> Shape

Make sphere:

import Playground exposing (..)


main =
    picture
        [ sphere green 10
        ]

You give the color, width, height, and then depth. So the first shape is the vertical part of the cross, the thinner and taller part.

cylinder : Color -> Number -> Number -> Shape

Make cylinders:

pillar =
    cylinder red 10 50

You give a color, the radius and then the height.

cone : Color -> Number -> Number -> Shape

Make cones:

spike =
    cone red 10 50

You give a color, the radius and then the height.

cube : Color -> Number -> Shape

Make cubes:

import Playground exposing (..)


main =
    picture
        [ cube blue 10
        ]

You give the color, width, height, and then depth. So the first shape is the vertical part of the cross, the thinner and taller part.

block : Color -> Number -> Number -> Number -> Shape

Make blocks. This example makes a red cross:

import Playground exposing (..)


main =
    picture
        [ block red 20 60 10
        , block red 60 20 10
        ]

You give the color, width, height, and then depth. So the first shape is the vertical part of the cross, the thinner and taller part.

prism : Color -> Number -> Number -> Shape

Make a prism

obj :
Color
-> List ( Number, Number, Number )
-> List ( Int, Int, Int )
-> Shape

Make 3d objects from vertices and faces, such as a pyramid:

import Playground3d exposing (..)


main =
    picture
        [ obj
            [ ( 1, 1, -1 )
            , ( 1, -1, -1 )
            , ( -1, -1, -1 )
            , ( -1, 1, -1 )
            , ( 0, 0, 1 )
            ]
            [ ( 1, 2, 3 )
            , ( 3, 4, 1 )
            , ( 1, 4, 5 )
            , ( 5, 4, 3 )
            , ( 3, 2, 5 )
            , ( 5, 2, 1 )
            ]
        ]
objFile : Color -> String -> Shape

Use an obj file model by url as a shape. You can create obj file models using tools like Blender or search for premade ones online.

Words

words : Color -> String -> Shape

Show some words!

import Playground exposing (..)


main =
    picture
        [ words black "Hello! How are you?"
        ]

You can use scale to make the words bigger or smaller.

Move Shapes

move : Number -> Number -> Number -> Shape -> Shape

Move a shape by some number of pixels:

import Playground exposing (..)


main =
    picture
        [ square red 100
            |> move -60 60 0
        , square yellow 100
            |> move 60 60 0
        , square green 100
            |> move 60 -60 0
        , square blue 100
            |> move -60 -60 0
        ]
moveX : Number -> Shape -> Shape

Move the x coordinate of a shape by some amount. Here is a square that moves back and forth:

import Playground exposing (..)


main =
    animation view


view time =
    [ square purple 20
        |> moveX (wave 4 -200 200 time)
    ]

Using moveX feels a bit nicer here because the movement may be positive or negative.

moveY : Number -> Shape -> Shape

Move the y coordinate of a shape by some amount. Maybe you want to make grass along the bottom of the screen:

import Playground exposing (..)


main =
    game view update 0


update computer memory =
    memory


view computer count =
    [ rectangle green computer.screen.width 100
        |> moveY computer.screen.bottom
    ]

Using moveY feels a bit nicer when setting things relative to the bottom or top of the screen, since the values are negative sometimes.

moveZ : Number -> Shape -> Shape

Move the z coordinate of a shape by some amount:

moveAlong : List ( Number, Number, Number ) -> Number -> Shape -> Shape

Move a shape along a path, specified by a list of coordinate-pairs, and a number between 0 and 1, where 0 corresponds with the start of the path and 1 indicates arriving at the end, the last coordinate in the list. So in the example below, the circle is moved halfway on the path:

cube red 50
    |> moveAlong [ ( 100, 0, 0 ), ( 200, 200, 0 ), ( 400, 200, 100 ) ] 0.5
moveAlongLoop : List ( Number, Number, Number ) -> Number -> Shape -> Shape

Move a shape along a path, just like with moveAlong, but by adding the first point also as the last one, we make sure that when amount reaches 1, we end up back at the beginning of the path. In this way you can keep looping from 0 to 1 and continue from 0 again.

Customize Shapes

scale : Number -> Shape -> Shape

Make a shape bigger or smaller. So if you wanted some words to be larger, you could say:

import Playground exposing (..)


main =
    picture
        [ words black "Hello, nice to see you!"
            |> scale 3
        ]
rotate : Number -> Shape -> Shape

Rotate shapes in degrees.

import Playground exposing (..)


main =
    picture
        [ triangle black 50
            |> rotate 10
        ]

The degrees go counter-clockwise to match the direction of the unit circle.

roll : Number -> Shape -> Shape

Rotate shapes in degrees, along the X axis:

import Playground exposing (..)


main =
    picture
        [ triangle black 50
            |> roll 10
        ]


Search Wikipedia for "roll, pitch, yaw" to find out why it is called "roll". ;)
pitch : Number -> Shape -> Shape

Rotate shapes in degrees, along the Y axis:

import Playground exposing (..)


main =
    picture
        [ triangle black 50
            |> pitch 10
        ]


Search Wikipedia for "roll, pitch, yaw" to find out why it is called "pitch". ;)
yaw : Number -> Shape -> Shape

Rotate shapes in degrees, along the Z axis:

import Playground exposing (..)


main =
    picture
        [ triangle black 50
            |> yaw 10
        ]


Search Wikipedia for "roll, pitch, yaw" to find out why it is called "yaw". ;)
fade : Number -> Shape -> Shape

Fade a shape. This lets you make shapes see-through or even completely invisible. Here is a shape that fades in and out:

import Playground exposing (..)


main =
    animation view


view time =
    [ square orange 30
    , square blue 200
        |> fade (zigzag 0 1 3 time)
    ]

The number has to be between 0 and 1, where 0 is totally transparent and 1 is completely solid.

Groups, extrusion, optimization

group : List Shape -> Shape

Put shapes together so you can move and rotate them as a group. Maybe you want to put a bunch of stars in the sky:

import Playground exposing (..)


main =
    picture
        [ star
            |> move 100 100
            |> rotate 5
        , star
            |> move -120 40
            |> rotate 20
        , star
            |> move 80 -150
            |> rotate 32
        , star
            |> move -90 -30
            |> rotate -16
        ]


star =
    group
        [ triangle yellow 20
        , triangle yellow 20
            |> rotate 180
        ]
extrude : Number -> Shape -> Shape

Pull a 2D shape "up" to form a 3D body:

circle blue 20
    |> extrude 50

This will create a flat circle "extruded" along the z-axis to form a 3D cylinder. The extruded form is centered around the xy-plane.

pullUp : Number -> Shape -> Shape

Pull a 2D shape "up" to form a 3D body:

circle blue 20
    |> pullUp 50

This will create a flat circle "pulled up" (or "extruded") along the z-axis to form a 3D cylinder.

prerendered : ObjLibrary -> Shape -> Shape

3D shapes can be quite intensive to render, so it is best to render the more complex shapes into an 3D entity once and then draw this prerendered version in the view. You can still use transformation functions from the Scene3d package such as translation and rotation on the prerendered entities.

For instance if you would like to prerender parts of your snow dog avatar but still want to animate its head:

snowdog time =
    group
        [ head white
            |> prerendered
            |> move 50 0 70
            |> yaw (wave -30 30 6 time)
            |> pitch (wave -10 10 3 time)
        , group
            [ cylinder white 15 80 |> pitch 90 |> moveZ 50
            , leg |> move 35 10 20
            , leg |> move 35 -10 20
            , leg |> move -35 10 20
            , leg |> move -35 -10 20
            , cylinder white 7 50 |> pitch -45 |> move -50 0 75
            ]
            |> prerendered
        ]


leg =
    cylinder white 10 40


head color =
    group
        [ sphere color 25
        , sphere color 10 |> move 25 0 -5
        , sphere black 5 |> move 35 0 -5
        , sphere black 5 |> move 17 12 5
        , sphere black 5 |> move 17 -12 5
        , triangle color 20
            |> move -5 12 37
            |> yaw 170
            |> pitch 83
            |> roll 2
            |> scale 0.4
        , triangle color 20
            |> move -5 -12 37
            |> yaw 190
            |> pitch 83
            |> roll -2
            |> scale 0.4
        ]

Time

type Time

The current time.

Helpful when making an animation with functions like spin, wave, and zigzag.

spin : Number -> Time -> Number

Create an angle that cycles from 0 to 360 degrees over time.

Here is an animation with a spinning triangle:

import Playground exposing (..)


main =
    animation view


view time =
    [ triangle orange 50
        |> rotate (spin 8 time)
    ]

It will do a full rotation once every eight seconds. Try changing the 8 to a 2 to make it do a full rotation every two seconds. It moves a lot faster!

wave : Number -> Number -> Number -> Time -> Number

Smoothly wave between two numbers.

Here is an animation with a circle that resizes:

import Playground exposing (..)


main =
    animation view


view time =
    [ circle lightBlue (wave 50 90 7 time)
    ]

The radius of the circle will cycles between 50 and 90 every seven seconds. It kind of looks like it is breathing.

zigzag : Number -> Number -> Number -> Time -> Number

Zig zag between two numbers.

Here is an animation with a rectangle that tips back and forth:

import Playground exposing (..)


main =
    animation view


view time =
    [ rectangle lightGreen 20 100
        |> rotate (zigzag -20 20 4 time)
    ]

It gets rotated by an angle. The angle cycles from -20 degrees to 20 degrees every four seconds.

BeginOfTime

secondsBetween : Time -> Time -> Number

Return the number of seconds between two instances of Time.

Computer

type alias Computer =
{ inbox : List Message
, secondsBeforeSend : Number
, touch :
{ list : List Touch
, current : Maybe Touch
, change : Maybe Touch
, previous : Maybe Touch
}
, mouse : Mouse
, keyboard : Keyboard
, screen : Screen
, time : Time
}

When writing a game, you can look up all sorts of information about your computer:

  • Mouse - Where is the mouse right now?
  • Keyboard - Are the arrow keys down?
  • Screen - How wide is the screen?
  • Time - What time is it right now?

So you can use expressions like computer.mouse.x and computer.keyboard.enter in games where you want some mouse or keyboard interaction.

type alias Mouse =
{ x : Number
, y : Number
, down : Bool
, click : Bool
}

Figure out what is going on with the mouse.

You could draw a circle around the mouse with a program like this:

import Playground exposing (..)


main =
    game view update 0


view computer memory =
    [ circle yellow 40
        |> moveX computer.mouse.x
        |> moveY computer.mouse.y
    ]


update computer memory =
    memory

You could also use computer.mouse.down to change the color of the circle while the mouse button is down.

type alias Screen =
{ width : Number
, height : Number
, top : Number
, left : Number
, right : Number
, bottom : Number
}

Get the dimensions of the screen. If the screen is 800 by 600, you will see a value like this:

{ width = 800
, height = 600
, top = 300
, left = -400
, right = 400
, bottom = -300
}

This can be nice when used with moveY if you want to put something on the bottom of the screen, no matter the dimensions.

type alias Keyboard =
{ up : Bool
, down : Bool
, left : Bool
, right : Bool
, space : Bool
, enter : Bool
, shift : Bool
, backspace : Bool
, keys : Set String
}

Figure out what is going on with the keyboard.

If someone is pressing the UP and RIGHT arrows, you will see a value like this:

{ up = True
, down = False
, left = False
, right = True
, space = False
, enter = False
, shift = False
, backspace = False
, keys = Set.fromList [ "ArrowUp", "ArrowRight" ]
}

So if you want to move a character based on arrows, you could write an update like this:

update computer y =
    if computer.keyboard.up then
        y + 1


    else
        y

Check out toX and toY which make this even easier!

Note: The keys set will be filled with the name of all keys which are down right now. So you will see things like "a", "b", "c", "1", "2", "Space", and "Control" in there. Check out this list to see the names used for all the different special keys! From there, you can use Set.member to check for whichever key you want. E.g. Set.member "Control" computer.keyboard.keys.

toX : Keyboard -> Number

Turn the LEFT and RIGHT arrows into a number.

toX { left = False, right = False, ... } == 0
toX { left = True , right = False, ... } == -1
toX { left = False, right = True , ... } == 1
toX { left = True , right = True , ... } == 0

So to make a square move left and right based on the arrow keys, we could say:

import Playground exposing (..)


main =
    game view update 0


view computer x =
    [ square green 40
        |> moveX x
    ]


update computer x =
    x + toX computer.keyboard
toY : Keyboard -> Number

Turn the UP and DOWN arrows into a number.

toY { up = False, down = False, ... } == 0
toY { up = True , down = False, ... } == 1
toY { up = False, down = True , ... } == -1
toY { up = True , down = True , ... } == 0

This can be used to move characters around in games just like toX:

import Playground exposing (..)


main =
    game view update ( 0, 0 )


view computer ( x, y ) =
    [ square blue 40
        |> move x y
    ]


update computer ( x, y ) =
    ( x + toX computer.keyboard
    , y + toY computer.keyboard
    )
toXY : Keyboard -> ( Number, Number )

If you just use toX and toY, you will move diagonal too fast. You will go right at 1 pixel per update, but you will go up/right at 1.41421 pixels per update.

So toXY turns the arrow keys into an (x,y) pair such that the distance is normalized:

toXY { up = True , down = False, left = False, right = False, ... } == (1, 0)
toXY { up = True , down = False, left = False, right = True , ... } == (0.707, 0.707)
toXY { up = False, down = False, left = False, right = True , ... } == (0, 1)

Now when you go up/right, you are still going 1 pixel per update.

import Playground exposing (..)


main =
    game view update ( 0, 0 )


view computer ( x, y ) =
    [ square green 40
        |> move x y
    ]


update computer ( x, y ) =
    let
        ( dx, dy ) =
            toXY computer.keyboard
    in
    ( x + dx, y + dy )

Colors

rgb : Number -> Number -> Number -> Color

RGB stands for Red-Green-Blue. With these three parts, you can create any color you want. For example:

brightBlue =
    rgb 0.1 0.6 1


brightGreen =
    rgb 0.6 1 0.05


brightPurple =
    rgb 0.4 0.1 0.8

For rgb each numer is expected to be a floating point number between 0 and 1. Also see rgb255, where each number needs to be an integer between 0 and 255.

It can be hard to figure out what numbers to pick, so try using a color picker like paletton to find colors that look nice together. Once you find nice colors, click on the color previews to get their RGB values.

rgb255 : Number -> Number -> Number -> Color

RGB stands for Red-Green-Blue. With these three parts, you can create any color you want. For example:

brightBlue =
    rgb255 18 147 216


brightGreen =
    rgb255 119 244 8


brightPurple =
    rgb255 94 28 221

For rgb255 each number needs to be an integer between 0 and 255. Also see rgb, where each numer is expected to be a floating point number between 0 and 1.

It can be hard to figure out what numbers to pick, so try using a color picker like paletton to find colors that look nice together. Once you find nice colors, click on the color previews to get their RGB values.

red : Color
orange : Color
yellow : Color
green : Color
blue : Color
purple : Color
brown : Color

Light Colors

lightRed : Color
lightOrange : Color
lightYellow : Color
lightGreen : Color
lightBlue : Color
lightPurple : Color
lightBrown : Color

Dark Colors

darkRed : Color
darkOrange : Color
darkYellow : Color
darkGreen : Color
darkBlue : Color
darkPurple : Color
darkBrown : Color

Shades of Grey

white : Color
lightGrey : Color
grey : Color
darkGrey : Color
charcoal : Color
darkCharcoal : Color
black : Color

Alternate Spellings of Gray

lightGray : Color
gray : Color
darkGray : Color

Numbers

type alias Number =
Float

A number like 1 or 3.14 or -120.

Configurations

configuration : Configuration memory

Use configuration to configure a picture, animation or game.

polytest =
    "obj/polytest.obj.txt"


main =
    configuration
        |> withObjUrls [ polytest ]
        |> configuredAnimation view


view time =
    [ if spin 1 time > 180 then
        objFile red polytest
            |> scale 0.5
            |> moveZ 100


      else
        cube green 100
            |> moveZ 50
    ]
withCamera : (memory -> Camera) -> Configuration memory -> Configuration memory

Configure the camera; a function that given the memory outputs a camera.

main =
    configuration
        |> withCamera camera
        |> configuredGame view update init


camera memory =
    eyesAt 500 500 500
        |> lookAt 0 0 0
withObjUrls : List String -> Configuration memory -> Configuration memory

Configure the list of obj file urls (obj files hold 3d models made with tools like Blender or found online).

polytest =
    "obj/polytest.obj.txt"


main =
    configuration
        |> withObjUrls [ polytest ]
        |> configuredGame view update init
configuredPicture : List Shape -> Configuration memory -> Program () Picture Msg

Create a configured picture - see configuration.

configuredAnimation : (Time -> List Shape) -> Configuration () -> Program () Animation Msg

Create a configured animation - see configuration.

(Computer -> memory -> List Shape)
-> (Computer -> memory -> memory)
-> memory
-> Configuration memory
-> Program () (Game memory) Msg

Create a configured game - see configuration.

type alias Configuration memory =
{ camera : Maybe (memory -> Camera)
, network : Maybe Connection
, objUrls : List String
}

Configuration type to hold customizations for camera and keep a list of obj file urls to load at init.

type alias Connection =
{ server : String
, name : String
, sendIntervalInSeconds : Number
}

A network Connection with server url, sender name, and the send interval in seconds.

Cameras (views)

isometric : Camera

Create an isometric camera

orbit : Number -> Number -> Number -> Camera

Create a camera orbiting the target set with lookAt, with a specified azimuth, elevation (in degrees) and distance

viewFrom : Shape -> Camera

Return a camera with the location and orientation of the specified shape. As if the shape would be the eyes! 8)

eyesAt : Number -> Number -> Number -> Camera

Create a camera looking from a point x y z, towards the origin (0, 0, 0)

lookAt : Number -> Number -> Number -> Camera -> Camera

Modify a camera to look at a specific point x y z

pan : Number -> Camera -> Camera

Pan the camera for a specified number of degrees.

tilt : Number -> Camera -> Camera

Tilt the camera for a specified number of degrees.

shift : Number -> Number -> Number -> Camera -> Camera

Shift the camera along the x, y, and z axis (in centimeters).

zoom : Number -> Camera -> Camera

Let the camera zoom in (factor > 1) or out (factor < 1, while greater than 0 - if not, the zoom factor will be just 1).

Naming and calculations

withName : String -> Shape -> Shape

Name a shape. This lets you set a name for a shape, so you can detect when it is clicked.

import Playground exposing (..)


main =
    game view update {}


view computer memory =
    [ square
        (if computer.mouse |> clickedName "little square" then
            red


         else
            green
        )
        30
        |> withName "little square"
    ]


update computer memory =
    memory
nameOf : Shape -> String

Return the name of the given shape; if no name was set it returns an empty string "".

whereIs : String -> Shape -> List ( Number, Number, Number )

Finds out where named shapes are within a scene (another shape, maybe a group).

center : Shape -> ( Number, Number, Number )

Extracts the position from any shape.

extent : Shape -> Number

Calculates the extent from origin (radius) of a sphere that roughly circumscribes the (group of) shape(s). TODO: Needs a refactor where offset centers are taken into account within a group.

extents : Shape -> ( Number, Number, Number )

Calculates the extents per axis of any (group of) shape(s). Extent in this case means from the center of the object to its edge (a "radius"), so it can directly be used in calculations from the origin of the objects.

positionOf : Shape -> ( Number, Number, Number )

Returns the position of a shape, as a tuple (x, y, z).

Physics

Physics world

Create an empty physics simulated world to add playground shapes to. Use it for example like this:

init =
    { world =
        emptyWorld
            |> withGravity 9.81
            |> withShapes
                [ square black 500
                ]
            |> withDynamicShapes
                [ cylinder blue 50 100 |> move 100 100 100 |> withWeight (kilograms 10)
                , cube yellow 50 |> move 60 90 300
                , block red 50 50 100 |> move 100 -100 150
                , sphere green 50 |> move 70 80 400
                ]
    }
withGravity : Number -> World Shape -> World Shape

Add gravity (meters per second squared) to the simulated world.

withShapes : List Shape -> World Shape -> World Shape

Add static shapes to the simulated world. They will stay where they are put.

withDynamicShapes : List Shape -> World Shape -> World Shape

Add dynamic shapes to the simulated world. These shapes will have weight. They are subject to gravity and other forces.

simulate : World Shape -> World Shape

Simulate the world. For use in the update function:

update computer memory =
    { memory
        | world = simulate memory.world
    }
simulateFor : Duration -> World Shape -> World Shape

Simulate the world with a step of a specified duration.

shapesFromWorld : World Shape -> List Shape

Get the shapes from the simulated world to be able to render them inside a view for example:

view computer memory =
    shapesFromWorld memory.world
shapeNamed : String -> World Shape -> Maybe Shape

Search the world for a shape with the specified name. Return Nothing if no shape is found, and Just shape when it was found. It returns only the first shape found.

Physics shape properties

withWeight : Mass -> Shape -> Shape

Set the weight (actually the mass) for a shape. For example:

cylinder blue 50 100 |> withWeight (kilograms 10)
withMass : Mass -> Shape -> Shape

Set the mass for a shape. For example:

cylinder blue 50 100 |> withMass (kilograms 10)
kilograms : Number -> Mass

Specify mass (weight) in kilograms.

grams : Number -> Mass

Specify mass (weight) in grams.

weightOf : Shape -> Mass

Returns the weight of a shape as a Mass value (set with withWeigth or withMass).

massOf : Shape -> Mass

Returns the mass of a shape as a Mass value (set with withMass).

inKilograms : Mass -> Number

Return a mass (weight) in kilograms.

inGrams : Mass -> Number

Return a mass (weight) in grams.

withFriction : Number -> Shape -> Shape

Set the amount of friction for a shape. The default friction is 0.3.

frictionOf : Shape -> Number

Return the set amount of friction for the given shape. If not set this value is 0.3, the physics calculations default.

withBounciness : Number -> Shape -> Shape

Set the amount of bounciness for a shape. The default bounciness is 0.

bouncinessOf : Shape -> Number

Return the set amount of bounciness for the given shape. If not set this value is 0, the physics calculations default.

Physics updates and actions

updateWorldShapes : (Shape -> List Action) -> World Shape -> World Shape

Update the shapes added to the physics world using actions such as pushForward.

updateShapeNamed : String -> List Action -> World Shape -> World Shape

Update the shape(s) with the specified name using actions such as pushForward and transform.

moveTo : Number -> Number -> Number -> Action
moveBy : Vector3d Meters WorldCoordinates -> Action

Move a shape that was added to the physics world by a specified translation relative to the world.

moveIn : Direction3d BodyCoordinates -> Length -> Action

Move a shape that was added to the physics world in a specified direction relative to the shape.

moveForward : Number -> Action

Move a shape that was added to the physics world forward along its x-axis (so it is relative to the current orientation of the shape).

rotateAround : Axis3d Meters WorldCoordinates -> Angle -> Action

Rotate a shape that was added to the physics world along a specified axis relative to the shape.

pushForward : Number -> Action

Push a shape that was added to the physics world forward (in the direction of the x-axis of the shape).

pushBackward : Number -> Action

Push a shape that was added to the physics world backward (in the opposite direction of the x-axis of the shape).

pushLeft : Number -> Action

Push a shape that was added to the physics world the left (in the opposite direction of the y-axis of the shape).

pushRight : Number -> Action

Push a shape that was added to the physics world to the right (in the direction of the y-axis of the shape).

pushUp : Number -> Action

Push a shape that was added to the physics world up (in the direction of the z-axis of the shape).

pushDown : Number -> Action

Push a shape that was added to the physics world down (in the opposite direction of the z-axis of the shape).

{ force : Force
, direction : Direction3d BodyCoordinates
, at : Point3d Meters BodyCoordinates
}
-> Action

Push a shape that was added to the physics world along a specified axis relative to the shape, with an amount of force (Newtons), at a specific point on the shape (specified relative to the shape).

transform : List (Shape -> Shape) -> Action

Transform a shape that was added to the physics world using the familiar transforms of the playground, such as roll, pitch, yaw, move and scale.

Physics constraints

lockPositionTo : String -> Shape -> Shape

Connect a shape to another shape with the specified name via a constraint that keeps the position of the shape relative to the named shape fixed.

keepDistanceTo : String -> Shape -> Shape

Connect a shape to another shape with the specified name via a constraint that keeps the distance of the shape to the named shape fixed.

hingeTo : String -> Shape -> Shape

Connect a shape to another shape with the specified name via a hinge constraint that keeps the relative positions and allows rotation along the y-axes of the shapes (relative to the individual shapes).

Playground Scene3d embeds

entity : ObjLibrary -> Shape -> Entity ObjCoordinates

Add a 3D shape to a Scene3D scene as an entity.

Playground Picture embeds

pictureInit : List Shape -> () -> ( Picture, Cmd Msg )

Picture init function

pictureView : Picture -> List Shape -> Html Msg

Picture view function

pictureUpdate : List Shape -> Msg -> Picture -> ( Picture, Cmd Msg )

Picture update function

pictureSubscriptions : Picture -> Sub Msg

Picture subscriptions

type alias Picture =
{ screen : Screen
, font : Maybe Font
, objFiles : ObjLibrary
}

Picture model

Playground Animation embeds

(Time -> List Shape)
-> Configuration ()
-> ()
-> ( Animation, Cmd Msg )

Animation init

animationView : Animation -> (Time -> List Shape) -> Html Msg

Animation view

Animation update function

Animation subscriptions

The type for animations.

type alias AnimationMsg =
Msg

Animation message alias

Playground Game embeds

gameInit : memory -> Configuration memory -> () -> ( Game memory, Cmd Msg )

Game init function

(memory -> Camera)
-> (Computer -> memory -> List Shape)
-> Game memory
-> Html Msg

Game view function

gameUpdate : (Computer -> memory -> memory) -> Msg -> Game memory -> Game memory

Game update function

gameSubscriptions : Game memory -> Sub Msg

Game subscriptions

type Game memory

Game model containing the visibility status, custom data (memory) and the Computer state record.

type alias GameMsg =
Msg

Game message alias