Merge: gamnit: use the same code to limit fps than mnit and fix errors
authorJean Privat <jean@pryen.org>
Wed, 9 Dec 2015 03:50:20 +0000 (22:50 -0500)
committerJean Privat <jean@pryen.org>
Wed, 9 Dec 2015 03:50:20 +0000 (22:50 -0500)
Fixed a few bugs in `mnit::mnit_fps`, a typo invalidated the value of `current_fps` and the use of long Ints were broken probably since they are tagged. Using floats should fix this last issue.

Finally, the goal of this PR is to copy the module `mnit::mnit_fps` to `gamnit::limit_fps` and adapt it to the gamnit framework. There is some code duplication, but the mnit version should be deleted with the engine when gamnit is completed.

Pull-Request: #1879
Reviewed-by: Jean Privat <jean@pryen.org>

contrib/crazy_moles/src/moles.nit
contrib/tinks/src/client/client.nit
examples/mnit_ballz/src/ballz_android.nit
examples/mnit_ballz/src/ballz_linux.nit
examples/mnit_dino/src/dino.nit
lib/core/time.nit
lib/gamnit/limit_fps.nit [new file with mode: 0644]
lib/mnit/mnit_fps.nit

index 27ca3ad..505ce49 100644 (file)
@@ -318,7 +318,7 @@ redef class App
        do
                super
 
-               maximum_fps = 50
+               maximum_fps = 50.0
        end
 
        redef fun frame_core(display)
index 8dad5eb..6975ed7 100644 (file)
@@ -80,7 +80,7 @@ redef class App
        redef fun on_create
        do
                super
-               maximum_fps = 60
+               maximum_fps = 60.0
                assets.assign_images_to_story context.game.story
        end
 
@@ -127,7 +127,7 @@ redef class App
                        return new LocalServerContext
                else
                        print "Connecting to:{address}:{port}"
-                       maximum_fps = 0
+                       maximum_fps = 0.0
 
                        # Args are: tinks server_address {port}
                        #var address = "riph" # args[0]
index dc934e7..0f46bfc 100644 (file)
@@ -38,7 +38,7 @@ redef class App
                gyroscope.enabled = true
                light.enabled = true
                proximity.enabled = true
-               maximum_fps = 50
+               maximum_fps = 50.0
                sensors_support_enabled = true
                super
        end
index 6f089a8..bd2e563 100644 (file)
@@ -29,7 +29,7 @@ redef class App
 
        redef fun run
        do
-               maximum_fps = 50
+               maximum_fps = 50.0
                super
        end
 
index df97ad5..27ced99 100644 (file)
@@ -39,7 +39,7 @@ redef class App
        do
                super
 
-               maximum_fps = 80
+               maximum_fps = 80.0
 
                var display = display
                assert display != null
index 6c99016..5fc37f2 100644 (file)
@@ -32,6 +32,16 @@ redef class Sys
        `}
 end
 
+redef class Float
+       # Sleep approximately `self` seconds
+       fun sleep `{
+               time_t s = self;
+               long ns = (self-s) * 1000000000.0;
+               const struct timespec req = {s, ns};
+               nanosleep(&req, NULL);
+       `}
+end
+
 # Time since epoch
 extern class TimeT `{time_t`}
 
diff --git a/lib/gamnit/limit_fps.nit b/lib/gamnit/limit_fps.nit
new file mode 100644 (file)
index 0000000..a300b54
--- /dev/null
@@ -0,0 +1,78 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Frame-rate control for applications
+module limit_fps
+
+import gamnit
+private import realtime
+
+redef class App
+       # Limit the frame-rate to a given frequency
+       #
+       # This basically limits how much `frame_core` is called per second.
+       # Zero (or a negative value) means no limit.
+       #
+       # Applications can modify this value even during the main-loop.
+       var maximum_fps = 60.0 is writable
+
+       # Current frame-rate
+       #
+       # Updated each 5 seconds.
+       var current_fps = 0.0
+
+       redef fun frame_full
+       do
+               super
+               limit_fps
+       end
+
+       # The clock for limit_fps
+       private var clock = new Clock
+
+       # Number of frames since the last deadline
+       #
+       # Used to compute `current_fps`.
+       private var frame_count = 0
+
+       # Deadline used to compute `current_fps`
+       private var frame_count_deadline = 0
+
+       # Check and sleep to maintain a frame-rate bellow `maximum_fps`
+       #
+       # Also periodically update `current_fps`
+       # Is automatically called at the end of `full_frame`.
+       fun limit_fps
+       do
+               var t = clock.total.sec
+               if t >= frame_count_deadline then
+                       var cfps = frame_count.to_f / 5.0
+                       self.current_fps = cfps
+                       frame_count = 0
+                       frame_count_deadline = t + 5
+               end
+               frame_count += 1
+
+               var mfps = maximum_fps
+               if mfps <= 0.0 then return
+               var lapse = clock.lapse
+               var dt = lapse.to_f
+               var target_dt = 1.0 / mfps
+               if dt < target_dt then
+                       var sleep_t = target_dt - dt
+                       sleep_t.sleep
+                       clock.lapse
+               end
+       end
+end
index 2b2abf1..3841bc6 100644 (file)
@@ -24,7 +24,7 @@ redef class App
        # Zero (or a negative value) means no limit.
        #
        # Applications can modify this value even during the main-loop.
-       var maximum_fps = 60 is writable
+       var maximum_fps = 60.0 is writable
 
        # Current frame-rate
        # Updated each 5 seconds.
@@ -53,7 +53,7 @@ redef class App
        do
                var t = clock.total.sec
                if t >= frame_count_deadline then
-                       var cfps = frame_count_deadline.to_f / 5.0
+                       var cfps = frame_count.to_f / 5.0
                        self.current_fps = cfps
                        frame_count = 0
                        frame_count_deadline = t + 5
@@ -61,15 +61,14 @@ redef class App
                frame_count += 1
 
                var mfps = maximum_fps
-               if mfps <= 0 then return
-               var dt = clock.lapse
-               var target_dt = 1000000000 / mfps
-               var sec = dt.sec
-               var nanosec = dt.nanosec
-               if sec == 0 and nanosec < target_dt then
-                       var sleep_t = target_dt - nanosec
-                       sys.nanosleep(0, sleep_t)
-                       dt = clock.lapse
+               if mfps <= 0.0 then return
+               var lapse = clock.lapse
+               var dt = lapse.to_f
+               var target_dt = 1.0 / mfps
+               if dt < target_dt then
+                       var sleep_t = target_dt - dt
+                       sleep_t.sleep
+                       clock.lapse
                end
        end
 end