lib/gamnit flat: rotation follows the right hand rule on the Z axis
[nit.git] / lib / gamnit / flat.nit
index 90cefca..b74da82 100644 (file)
@@ -52,14 +52,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
@@ -68,16 +79,23 @@ class Sprite
                glActiveTexture gl_TEXTURE0
                glBindTexture(gl_TEXTURE_2D, texture.root.gl_texture)
 
-               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.array_enabled = false
+               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(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
@@ -110,7 +128,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
@@ -180,10 +198,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
 
@@ -196,6 +218,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
@@ -208,6 +241,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
@@ -247,6 +301,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