nateabele/elm-3d-playground/2.0.0

NOTE: the latest version is 2.1.0

Playground3D

Contains most of the usual suspects from elm-playground, just 3D-ified.

Camera3d Meters coordinates
-> Scene coordinates
-> Scene coordinates

Configure the camera for the scene

withLighting : Lighting coordinates -> Scene coordinates -> Scene coordinates

Set the lighting for the scene

withShadow : Bool -> Shape -> Shape

Add a shadow to a shape.

type alias Scene coordinates =
{ camera : Camera3d Meters coordinates
, clipDepth : Length
, background : Background coordinates
, shapes : List Shape
, lighting : Lighting coordinates
}

A scene is a collection of shapes, camera, lighting, and background

type Shape

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

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

yellow : Color

The color yellow

black : Color

The color black

blue : Color

The color blue

box : Material -> Number -> Number -> Number -> Shape

Create a box, like a cube or other shape

brown : Color

The color brown

charcoal : Color

The color charcoal

darkBlue : Color

The color dark blue

darkBrown : Color

The color dark brown

darkCharcoal : Color

The color darkCharcoal

darkGray : Color
darkGreen : Color

The color dark green

darkGrey : Color

The color dark grey

darkOrange : Color

The color dark orange

darkPurple : Color

The color dark purple

darkRed : Color

The color dark red

darkYellow : Color

The color dark yellow

group : List Shape -> Shape

Group shapes together.

import Playground3D exposing (..)


main =
    picture
        [ group [ sphere red 10, sphere blue 10 ] ]
lightBlue : Color

The color light blue

lightBrown : Color

The color light brown

The color light charcoal

lightGray : Color
lightGreen : Color

The color light green

lightGrey : Color

The color light grey

lightOrange : Color

The color light orange

lightPurple : Color

The color light purple

lightRed : Color

The color light red

lightYellow : Color

The color light yellow

type Lighting coordinates
= Unlit
| Sunny (Direction3d coordinates) CastShadows

Different types of lighting that the scene can have

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

Move a shape in one or more directions

moveBack : Number -> Shape -> Shape

Move a shape back

moveDown : Number -> Shape -> Shape

Move a shape down

moveForward : Number -> Shape -> Shape

Move a shape forward

moveLeft : Number -> Shape -> Shape

Move a shape left

moveRight : Number -> Shape -> Shape

Move a shape right

moveUp : Number -> Shape -> Shape

Move a shape up

moveX : Number -> Shape -> Shape

Move a shape left or right

moveY : Number -> Shape -> Shape

Move a shape up or down

moveZ : Number -> Shape -> Shape

Move a shape forward or backward

orange : Color

The color orange

purple : Color

The color purple

red : Color

The color red

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 18 147 216


brightGreen =
    rgb 119 244 8


brightPurple =
    rgb 94 28 221

Each number needs to be 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.

rotate : Number -> Shape -> Shape

Rotate shapes in degrees.

import Playground exposing (..)


main =
    picture
        [ words black "These words are tilted!"
            |> rotate 10
        ]

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

grey : Color

The color grey

gray : Color
green : Color

The color green

(Computer -> memory -> Scene coordinates)
-> (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!

scale : Number -> Shape -> Shape

Scale a shape

scene : List Shape -> Scene coordinates

Create a scene by giving it some shapes. Using other functions, you can set the camera and lighting.

white : Color

The color white

type alias Computer =
{ 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 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.

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

Information about the mouse

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 Time =
Posix

The current time.

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

type alias Number =
Float

A number like 1 or 3.14 or -120.

sphere : Material -> Number -> Shape

Create a sphere

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
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 )
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
    )
glowing : Color -> Float -> Material

Create a glowing material from a color and intensity value that can be applied to a shape. The intensity value controls how brightly the material glows.

flat : Color -> Material

Create a material from a color, that can be applied to a shape