on master help sign in
Add frame rate example.
commitc94777f33a8501ae1a8164667f8d8aec1f3cbf3f authorevancz <info@elm-lang.org> dateThu 28 Jun 2012, 12:55 (14 years ago) parent48fbba6
3 files changed+121
Examples/elm-js/FrameRate/FrameRate.elm+67 Examples/elm-js/FrameRate/FrameRateHelp.js+39 Examples/elm-js/FrameRate/README.txt+15
Examples/elm-js/FrameRate/FrameRate.elmnew file+67
@@ -0,0 +1,67 @@
1+
2+module FrameRate where
3+
4+import Data.Maybe (mapMaybe)
5+import Foreign.JavaScript
6+import Signal.Keyboard.Raw
7+import Signal.Input
8+
9+
10+foreign import jsevent "trigger" (castIntToJSNumber 0)
11+ jsTime :: Signal JSNumber
12+
13+foreign export jsevent "finished"
14+ done :: Signal JSBool
15+
16+foreign export jsevent "desiredFPS"
17+ desiredFPS :: Signal JSNumber
18+
19+desiredFPS = constant (castIntToJSNumber 30)
20+
21+time = lift castJSNumberToFloat jsTime
22+
23+
24+-- Calculate FPS based on incoming times.
25+
26+getFPS ts =
27+ let len = length ts in
28+ if len > 1 then (len-1) / (head ts - last ts) else 0
29+truncate n = castJSNumberToInt (castFloatToJSNumber $ 100 * n) / 100
30+fps = lift (truncate . getFPS) (foldp (\t ts -> take 10 (t:ts)) [0] time)
31+
32+
33+-- Use time and keyboard input to determine the
34+-- position of the black square.
35+
36+addVecs (x1,y1) (x2,y2) = (x1+x2, y1+y2)
37+scaleBy s (x,y) = (x*s, y*s)
38+
39+addKey k (x,y) =
40+ if k < 37 || k > 40 then (x,y) else
41+ if k `mod` 2 == 1 then (x + k - 38, y)
42+ else (x, y + k - 39)
43+
44+velocity = lift (foldl addKey (0,0)) keysDown
45+
46+timestep = lift snd $ foldp (\t1 (t0,d) -> (t1, t1-t0)) (0,0) time
47+
48+delta = dropIf (\(x,y) -> x == 0 && y == 0) (0,0) $
49+ lift (scaleBy 100) (lift2 scaleBy timestep velocity)
50+
51+position = foldp addVecs (0,0) delta
52+
53+
54+-- Display moving square and FPS on screen.
55+
56+screen pos actual desired =
57+ flow down [ collage 400 400 [ outlined black (rect 40 40 pos) ]
58+ , plainText "Move the square around with the arrow keys."
59+ , text $ toText "Actual frames per second: " ++ show actual
60+ , text $ toText "Desired frames per second: " ++ show desired
61+ ]
62+
63+
64+game = lift3 screen position fps desiredFPS
65+done = lift (\_ -> castBoolToJSBool True) game
66+
67+main = game
Examples/elm-js/FrameRate/FrameRateHelp.jsnew file+39
@@ -0,0 +1,39 @@
1+
2+var FrameRate = function() {
3+
4+var desiredFPS = 40;
5+var msPerFrame = 1000 / desiredFPS;
6+
7+// Set the desired rate of frames per second.
8+// Default is 40 if no desiredFPS event is triggered.
9+document.addEventListener('desiredFPS', function(e) {
10+ console.log(e.value);
11+ desiredFPS = e.value;
12+ msPerFrame = 1000 / desiredFPS;
13+ });
14+
15+
16+var date = new Date();
17+var startTime = date.getTime();
18+var frameStart = startTime;
19+var frameEnd = startTime;
20+var timeoutID = 0;
21+
22+// Trigger time events to try to maintain the desired FPS.
23+document.addEventListener('finished', function(evt) {
24+ clearTimeout(timeoutID);
25+ date = new Date();
26+ frameEnd = date.getTime();
27+ var diff = frameEnd - frameStart;
28+ var waitTime = Math.max(msPerFrame-diff,3);
29+ timeoutID = setTimeout(function() {
30+ date = new Date();
31+ frameStart = date.getTime();
32+ e = document.createEvent('Event');
33+ e.initEvent('trigger', true, true);
34+ e.value = (frameStart - startTime) / 1000;
35+ document.dispatchEvent(e);
36+ }, waitTime);
37+ });
38+
39+}();
Examples/elm-js/FrameRate/README.txtnew file+15
@@ -0,0 +1,15 @@
1+
2+Use the arrow keys to move the square around.
3+
4+
5+To compile this example yourself use:
6+
7+ elm --import-js="FrameRateHelp.js" FrameRate.elm
8+
9+This compiles the Elm file and includes the necessary JavaScript code.
10+It produces a self-contained HTML file.
11+
12+
13+Note: Not all browsers like reading the elm-runtime-x.y.z.js file from
14+an absolute path, so you may have to specify a relative path with
15+the --runtime flag (e.g. --runtime="../../../elm/elm-runtime-0.3.5.js").