realtime: 32 bits safe
[nit.git] / lib / gamnit / flat.nit
index d415ded..6487ed2 100644 (file)
@@ -43,6 +43,8 @@ import gamnit
 import gamnit::cameras
 import gamnit::limit_fps
 
+import android_two_fingers_motion is conditional(android)
+
 # Image to draw on screen
 class Sprite
 
@@ -52,14 +54,25 @@ class Sprite
        # Position of this sprite in world coordinates
        var center: Point3d[Float] is writable
 
-       # Rotation on the Z axis
+       # Rotation on the Z axis, where 0.0 points right and `0.5*pi` points up
        var rotation = 0.0 is writable
 
+       # Mirror `texture` horizontally, inverting each pixel on the X axis
+       var invert_x = false is writable
+
        # Scale applied to this sprite
        var scale = 1.0 is writable
 
        # Transparency applied to the texture on draw
-       var alpha = 1.0 is writable
+       fun alpha: Float do return tint[3]
+
+       # Transparency applied to the texture on draw
+       fun alpha=(value: Float) do tint[3] = value
+
+       # Tint applied to the texture on draw
+       #
+       # Require: `tint.length == 4`
+       var tint: Array[Float] = [1.0, 1.0, 1.0, 1.0] is writable
 
        private fun draw
        do
@@ -72,16 +85,19 @@ class Sprite
                simple_2d_program.color.array_enabled = false
                simple_2d_program.scale.array_enabled = false
 
-               simple_2d_program.translation.uniform(center.x, -center.y, center.z, 0.0)
-               simple_2d_program.color.uniform(1.0, 1.0, 1.0, alpha)
+               simple_2d_program.translation.uniform(center.x, center.y, center.z, 0.0)
+               simple_2d_program.color.uniform(tint[0], tint[1], tint[2], tint[3])
                simple_2d_program.scale.uniform scale
 
                simple_2d_program.use_texture.uniform true
                simple_2d_program.texture.uniform 0
-               simple_2d_program.tex_coord.array(texture.texture_coords, 2)
+               simple_2d_program.tex_coord.array(
+                       if invert_x then
+                               texture.texture_coords_invert_x
+                       else texture.texture_coords, 2)
                simple_2d_program.coord.array(texture.vertices, 3)
 
-               simple_2d_program.rotation.uniform new Matrix.rotation(rotation, 0.0, 0.0, 1.0)
+               simple_2d_program.rotation.uniform new Matrix.rotation(rotation, 0.0, 0.0, -1.0)
 
                glDrawArrays(gl_TRIANGLE_STRIP, 0, 4)
        end
@@ -114,7 +130,7 @@ redef class App
        # UI sprites to draw in reference to `ui_camera`, over world `sprites`
        var ui_sprites: Sequence[Sprite] = new List[Sprite]
 
-       private var clock = new Clock
+       private var clock = new Clock is lazy
 
        redef fun on_create
        do
@@ -152,12 +168,11 @@ redef class App
                # Prepare to draw
                for tex in all_root_textures do
                        tex.load
+                       gamnit_error = tex.error
+                       if gamnit_error != null then print_error gamnit_error
 
                        glTexParameteri(gl_TEXTURE_2D, gl_TEXTURE_MIN_FILTER, gl_LINEAR)
                        glTexParameteri(gl_TEXTURE_2D, gl_TEXTURE_MAG_FILTER, gl_LINEAR)
-
-                       gamnit_error = tex.error
-                       assert gamnit_error == null else print_error gamnit_error
                end
        end
 
@@ -184,10 +199,14 @@ redef class App
        end
 
        # Draw the whole screen, all `glDraw...` calls should be executed here
-       protected fun frame_core_draw(display: GamnitDisplay) do frame_core_flat display
+       protected fun frame_core_draw(display: GamnitDisplay)
+       do
+               frame_core_world_sprites display
+               frame_core_ui_sprites display
+       end
 
-       # Draw sprites in `sprites` and `ui_sprites`
-       protected fun frame_core_flat(display: GamnitDisplay)
+       # Draw world sprites from `sprites`
+       protected fun frame_core_world_sprites(display: GamnitDisplay)
        do
                simple_2d_program.use
 
@@ -200,6 +219,17 @@ redef class App
                # World sprites
                simple_2d_program.mvp.uniform world_camera.mvp_matrix
                for sprite in sprites do sprite.draw
+       end
+
+       # Draw UI sprites from `ui_sprites`
+       protected fun frame_core_ui_sprites(display: GamnitDisplay)
+       do
+               simple_2d_program.use
+
+               # Set constant configs
+               simple_2d_program.coord.array_enabled = true
+               simple_2d_program.tex_coord.array_enabled = true
+               simple_2d_program.color.array_enabled = false
 
                # Reset only the depth buffer
                glClear gl_DEPTH_BUFFER_BIT
@@ -212,6 +242,27 @@ redef class App
        # Main method to refine in clients to update game logic and `sprites`
        fun update(dt: Float) do end
 
+       # Display `texture` as a splash screen
+       #
+       # Load `texture` if needed and resets `ui_camera` to 1080 units on the Y axis.
+       fun show_splash_screen(texture: Texture)
+       do
+               texture.load
+
+               ui_camera.reset_height 1080.0
+
+               var splash = new Sprite(texture, ui_camera.center)
+               ui_sprites.add splash
+
+               var display = display
+               assert display != null
+               glClear gl_COLOR_BUFFER_BIT
+               frame_core_ui_sprites display
+               display.flip
+
+               ui_sprites.remove splash
+       end
+
        redef fun on_stop
        do
                # Clean up
@@ -251,6 +302,18 @@ redef class Texture
                for v in [c, d, a, b] do texture_coords.add_all v
                return texture_coords
        end
+
+       # Coordinates of this texture on the `root` texture, with the X axis inverted
+       private var texture_coords_invert_x: Array[Float] is lazy do
+               var a = [offset_left,  offset_bottom]
+               var b = [offset_right, offset_bottom]
+               var c = [offset_left,  offset_top]
+               var d = [offset_right, offset_top]
+
+               var texture_coords = new Array[Float]
+               for v in [d, c, b, a] do texture_coords.add_all v
+               return texture_coords
+       end
 end
 
 # Graphic program to display simple models with a texture, translation, rotation and scale
@@ -298,7 +361,7 @@ class Simple2dProgram
                uniform bool use_texture;
 
                // Texture to apply on this object
-               uniform sampler2D texture;
+               uniform sampler2D texture0;
 
                // Input from the vertex shader
                varying vec4 v_color;
@@ -307,7 +370,7 @@ class Simple2dProgram
                void main()
                {
                        if(use_texture) {
-                               gl_FragColor = v_color * texture2D(texture, v_coord);
+                               gl_FragColor = v_color * texture2D(texture0, v_coord);
                                if (gl_FragColor.a == 0.0) discard;
                        } else {
                                gl_FragColor = v_color;
@@ -322,7 +385,7 @@ class Simple2dProgram
        var use_texture = uniforms["use_texture"].as(UniformBool) is lazy
 
        # Visible texture unit
-       var texture = uniforms["texture"].as(UniformSampler2D) is lazy
+       var texture = uniforms["texture0"].as(UniformSampler2D) is lazy
 
        # Coordinates on the textures, per vertex
        var tex_coord = attributes["tex_coord"].as(AttributeVec2) is lazy