Zinggi/elm-2d-game/4.0.0

NOTE: the latest version is 4.1.0

Game.TwoD.Render

2D rendering module

This module provides a way to render commonly used objects in 2d games like simple sprites and sprite animations.

It also provides colored shapes which can be great during prototyping. The simple shapes can easily be replaced by nicer looking textures later.

suggested import:

import Game.TwoD.Render as Render exposing (Renderable)

Most functions to render something come in 3 forms:

thing, thingZ, thingWithOptions

The first is the most common one where you can specify the size, the position in 2d and some more.

The second one is the same as the first, but with a 3d position. The z position goes from -1 to 1, everything outside this will be invisible. This can be used to put something in front or behind regardless of the render order.

The last one gives you all possible options, e.g. the rotation , the pivot point of the rotation (normalized from 0 to 1), etc.

TODO: insert picture to visualize coordinate system.

A representation of something that can be rendered. To actually render a Renderable onto a web page use the Game.TwoD.* functions

Basic Shapes

-> { o | color : Color, position : Float2, size : Float2 }

A colored shape, great for prototyping

A representation of a basic shape to use when rendering a ColoredShape

BasicShape constructor for a rectangle

BasicShape constructor for a triangle

BasicShape constructor for a circle

BasicShape constructor for a ring

-> { o | color : Color, position : Float3, size : Float2 }

The same, but with 3d position.

-> { o
| color : Color
, position : Float3
, size : Float2
, rotation : Float
, pivot : Float2
}

A colored shape, that can also be rotated

With texture

Textures are Maybe values because you can never have a texture at the start of your game. You first have to load your textures. In case you pass a Nothing as a value for a texture, A gray rectangle will be displayed instead.

For loading textures I suggest using the game-resources library.

NOTE: Texture dimensions should be a power of 2, e.g. (2^n)x(2^m), like 4x16, 16x16, 512x256, etc. Non power of two texture are possible, but not encouraged.

{ o
| texture : Maybe Texture
, position : Float2
, size : Float2
}

A sprite.

{ o
| texture : Maybe Texture
, position : Float3
, size : Float2
}

A sprite with 3d position

{ o
| texture : Maybe Texture
, position : Float3
, size : Float2
, tiling : Float2
, rotation : Float
, pivot : Float2
}

A sprite with tiling and rotation.

spriteWithOptions { config | tiling = ( 3, 5 ) }

will create a sprite with a texture that repeats itself 3 times horizontally and 5 times vertically. TODO: picture!

Animated

{ o
| texture : Maybe Texture
, position : Float3
, size : Float2
, bottomLeft : Float2
, topRight : Float2
, numberOfFrames : Int
, duration : Float
}

An animated sprite. bottomLeft and topRight define a sub area from a texture where the animation frames are located. It's a normalized coordinate from 0 to 1.

TODO: picture!

{ o
| texture : Maybe Texture
, position : Float3
, size : Float2
, bottomLeft : Float2
, topRight : Float2
, rotation : Float
, pivot : Float2
, numberOfFrames : Int
, duration : Float
}

the same with rotation

{ o
| texture : Maybe Texture
, position : Float3
, size : Float2
, bottomLeft : Float2
, topRight : Float2
, rotation : Float
, pivot : Float2
, numberOfFrames : Int
, currentFrame : Int
}

The same as animated sprite, but you control what frame to display.

Background

{ o
| scrollSpeed : Float2
, z : Float
, tileWH : Float2
, texture : Maybe Texture
}

Used for scrolling backgrounds. This probably wont satisfy all possible needs for a scrolling background, but it can give you something that looks nice quickly.

{ o
| scrollSpeed : Float2
, z : Float
, tileWH : Float2
, offset : Float2
, texture : Maybe Texture
}

Same but with an offset parameter that you can use to position the background.

Custom

These are useful if you want to write your own GLSL shaders. When writing your own shaders, you might want to look at Game.TwoD.Shaders and Game.TwoD.Shapes for reusable parts.

MakeUniformsFunc u
-> { b
| fragmentShader :
Shader
{}
{ u | cameraProj : Mat4, transform : Mat4 }
{ vcoord : Vec2 }
, pivot : Float2
, position : Float3
, rotation : Float
, size : Float2
}

This allows you to write your own custom fragment shader. To learn about writing shaders, I recommend this free book.

The type signature may look terrifying, but this is still easier than using veryCustom or using WebGL directly. It handles the vertex shader for you, e.g. your object will appear at the expected location once rendered.

For the fragment shader, you have the vec2 varying vcoord; variable available, which can be used to sample a texture (texture2D(texture, vcoord);). It's a vector that goes from (0,0) to (1,1)

The MakeUniformsFunc allows you to pass along any additional uniforms you may need. In practice, this might look something like this:

makeUniforms { cameraProj, transform, time } =
    { cameraProj = cameraProj, transform = transform, time = time, myUniform = someVector }


render =
    customFragment makeUniforms
        { fragmentShader = frag, position = p, size = s, rotation = 0, pivot = ( 0, 0 ) }


frag =
    [glsl|


precision mediump float;


varying vec2 vcoord;
uniform vec2 myUniform;


void main () {
  gl_FragColor = vcoord.yx + myUniform;
}
|]

Don't pass the time along if your shader doesn't need it.

Here is a small example that draws a circle: https://ellie-app.com/LSTb2NnkDWa1/0

type alias MakeUniformsFunc a =
{ cameraProj : Mat4
, time : Float
, transform : Mat4
}
-> { a | cameraProj : Mat4, transform : Mat4 }

Just an alias, needed when you want to use customFragment

( { camera : Camera
, screenSize : ( Float, Float )
, time : Float
}
-> Entity
)

This allows you to specify your own attributes, vertex shader and fragment shader by using the WebGL library directly. If you use this you have to calculate the transformations yourself. (You can use Shaders.makeTransform)

If you need a square as attributes, you can take the one from Game.TwoD.Shapes

veryCustom
    (\{ camera, screenSize, time } ->
        WebGL.entity myVert
            myFrag
            Shapes.unitSquare
            { u_crazyFrog = frogTexture
            , transform = Shaders.makeTransform ( x, y, z ) 0 ( 2, 4 ) ( 0, 0 )
            , cameraProj = Camera.view camera screenSize
            }
    )
Shader attributes uniforms varyings
-> Shader {} uniforms varyings
-> Mesh attributes
-> uniforms
-> Entity

This can be used inside veryCustom instead of WebGL.entity. It's a customized blend function that works well with textures with alpha.

toWebGl : Float -> Camera -> Float2 -> Renderable -> Entity

Converts a Renderable to a WebGL.Entity. You don't need this unless you want to slowly introduce this library in a project that currently uses WebGL directly.

toWebGl time camera ( w, h ) renderable