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
( Basics.Float, Basics.Float )
( Basics.Float
, Basics.Float
, Basics.Float
)
shape : BasicShape -> { o | color : Color, position : Float2, size : Float2 } -> Renderable
A colored shape, great for prototyping
A representation of a basic shape to use when rendering a ColoredShape
rectangle : BasicShape
BasicShape constructor for a rectangle
triangle : BasicShape
BasicShape constructor for a triangle
circle : BasicShape
BasicShape constructor for a circle
ring : BasicShape
BasicShape constructor for a ring
shapeZ : BasicShape -> { o | color : Color, position : Float3, size : Float2 } -> Renderable
The same, but with 3d position.
shapeWithOptions : BasicShape -> { o | color : Color, position : Float3, size : Float2, rotation : Basics.Float, pivot : Float2 } -> Renderable
A colored shape, that can also be rotated
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.
sprite : { o | texture : Maybe WebGL.Texture.Texture, position : Float2, size : Float2 } -> Renderable
A sprite.
spriteZ : { o | texture : Maybe WebGL.Texture.Texture, position : Float3, size : Float2 } -> Renderable
A sprite with 3d position
spriteWithOptions : { o | texture : Maybe WebGL.Texture.Texture, position : Float3, size : Float2, tiling : Float2, rotation : Basics.Float, pivot : Float2 } -> Renderable
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!
animatedSprite : { o | texture : Maybe WebGL.Texture.Texture, position : Float3, size : Float2, bottomLeft : Float2, topRight : Float2, numberOfFrames : Basics.Int, duration : Basics.Float } -> Renderable
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!
animatedSpriteWithOptions : { o | texture : Maybe WebGL.Texture.Texture, position : Float3, size : Float2, bottomLeft : Float2, topRight : Float2, rotation : Basics.Float, pivot : Float2, numberOfFrames : Basics.Int, duration : Basics.Float } -> Renderable
the same with rotation
manuallyManagedAnimatedSpriteWithOptions : { o | texture : Maybe WebGL.Texture.Texture, position : Float3, size : Float2, bottomLeft : Float2, topRight : Float2, rotation : Basics.Float, pivot : Float2, numberOfFrames : Basics.Int, currentFrame : Basics.Int } -> Renderable
The same as animated sprite, but you control what frame to display.
parallaxScroll : { o | scrollSpeed : Float2, z : Basics.Float, tileWH : Float2, texture : Maybe WebGL.Texture.Texture } -> Renderable
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.
parallaxScrollWithOptions : { o | scrollSpeed : Float2, z : Basics.Float, tileWH : Float2, offset : Float2, texture : Maybe WebGL.Texture.Texture } -> Renderable
Same but with an offset parameter that you can use to position the background.
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.
customFragment : MakeUniformsFunc u -> { b | fragmentShader : WebGL.Shader {} { u | cameraProj : Math.Matrix4.Mat4, transform : Math.Matrix4.Mat4 } { vcoord : Math.Vector2.Vec2 }, pivot : Float2, position : Float3, rotation : Basics.Float, size : Float2 } -> Renderable
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
{ cameraProj : Math.Matrix4.Mat4
, time : Basics.Float
, transform : Math.Matrix4.Mat4 } -> { a | cameraProj : Math.Matrix4.Mat4
, transform : Math.Matrix4.Mat4
}
Just an alias, needed when you want to use customFragment
veryCustom : ({ camera : Game.TwoD.Camera.Camera, screenSize : ( Basics.Float, Basics.Float ), time : Basics.Float } -> WebGL.Entity) -> Renderable
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
}
)
renderTransparent : WebGL.Shader attributes uniforms varyings -> WebGL.Shader {} uniforms varyings -> WebGL.Mesh attributes -> uniforms -> WebGL.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 : Basics.Float -> Game.TwoD.Camera.Camera -> Float2 -> Renderable -> WebGL.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