on master help sign in
Clean up Pong, now uses Time.fps and some of the recent syntax upgrades.
77912aeevancz
Examples/elm-js/Pong/Pong.elm+33−69
@@ -57,29 +57,9 @@ module Pong where
57
57
58import JavaScript
58import JavaScript
59import Keyboard.Raw
59import Keyboard.Raw
60−import Window as Win
61
60
62
61
63−------------------------------------------------------------------------
62+time = lift (\t -> t / 1000) (Time.fps 60)
64−------ Extracting timesteps from JavaScript ------
65−------------------------------------------------------------------------
66−
67−-- Export our desired FPS to JavaScript. We just want a steady 30 frames
68−-- per second for this game.
69−
70−desiredFPS = constant (castIntToJSNumber 30)
71−
72−foreign export jsevent "desiredFPS"
73− desiredFPS :: Signal JSNumber
74−
75−
76−-- Import the current time from JavaScript. Events will come in roughly
77−-- 30 times per second.
78−
79−foreign import jsevent "trigger" (castIntToJSNumber 0)
80− jsTime :: Signal JSNumber
81−
82−time = lift castJSNumberToFloat jsTime
83
63
84
64
85-- Determine the time that has elapsed since the last event. This is
65-- Determine the time that has elapsed since the last event. This is
@@ -117,11 +97,11 @@ defaultKeyInput = KeyInput False Neutral Neutral
117
97
118updateDirection upKey downKey key direction =
98updateDirection upKey downKey key direction =
119 case direction of
99 case direction of
120− { Up -> if key == downKey then Neutral else Up
100+ Up -> if key == downKey then Neutral else Up
121− ; Down -> if key == upKey then Neutral else Down
101+ Down -> if key == upKey then Neutral else Down
122− ; Neutral -> if key == upKey then Up else
102+ Neutral -> if key == upKey then Up else
123 if key == downKey then Down else Neutral
103 if key == downKey then Down else Neutral
124− }
104+
125
105
126updateDirection1 = updateDirection 87 83 -- 'w' for up and 's' for down
106updateDirection1 = updateDirection 87 83 -- 'w' for up and 's' for down
127updateDirection2 = updateDirection 38 40 -- 'UP' for up and 'DOWN' for down
107updateDirection2 = updateDirection 38 40 -- 'UP' for up and 'DOWN' for down
@@ -216,10 +196,9 @@ defaultGame = GameState BetweenRounds
216
196
217stepPaddle delta dir (Paddle y) =
197stepPaddle delta dir (Paddle y) =
218 case dir of
198 case dir of
219− { Up -> Paddle $ clamp 20 (gameHeight-20) (y - 200 * delta)
199+ Up -> Paddle $ clamp 20 (gameHeight-20) (y - 200 * delta)
220− ; Down -> Paddle $ clamp 20 (gameHeight-20) (y + 200 * delta)
200+ Down -> Paddle $ clamp 20 (gameHeight-20) (y + 200 * delta)
221− ; Neutral -> Paddle y
201+ Neutral -> Paddle y
222− }
223
202
224
203
225-- We must also step the ball forward. This is more complicated due to
204-- We must also step the ball forward. This is more complicated due to
@@ -241,14 +220,13 @@ stepVelocity velocity lowerCollision upperCollision =
241 if upperCollision then makeNegative velocity else velocity
220 if upperCollision then makeNegative velocity else velocity
242
221
243stepBall delta (Ball (x,y) (vx,vy)) (Paddle y1) (Paddle y2) =
222stepBall delta (Ball (x,y) (vx,vy)) (Paddle y1) (Paddle y2) =
244− let { hitPaddle1 = within 20 y1 y && within 8 25 x
223+ let hitPaddle1 = within 20 y1 y && within 8 25 x
245− ; hitPaddle2 = within 20 y2 y && within 8 (gameWidth - 25) x
224+ hitPaddle2 = within 20 y2 y && within 8 (gameWidth - 25) x
246− ; vx' = stepVelocity vx hitPaddle1 hitPaddle2
225+ vx' = stepVelocity vx hitPaddle1 hitPaddle2
247− ; vy' = stepVelocity vy (y < 7) (y > gameHeight - 7)
226+ vy' = stepVelocity vy (y < 7) (y > gameHeight - 7)
248− ; scored = x > gameWidth || x < 0
227+ scored = x > gameWidth || x < 0
249− ; x' = if scored then halfWidth else x + vx' * delta
228+ x' = if scored then halfWidth else x + vx' * delta
250− ; y' = if scored then halfHeight else y + vy' * delta
229+ y' = if scored then halfHeight else y + vy' * delta
251− }
252 in ( Ball (x',y') (vx',vy')
230 in ( Ball (x',y') (vx',vy')
253 , if x > gameWidth then 1 else 0
231 , if x > gameWidth then 1 else 0
254 , if x < 0 then 1 else 0 )
232 , if x < 0 then 1 else 0 )
@@ -259,15 +237,16 @@ stepBall delta (Ball (x,y) (vx,vy)) (Paddle y1) (Paddle y2) =
259
237
260stepGame (Input delta (KeyInput space dir1 dir2))
238stepGame (Input delta (KeyInput space dir1 dir2))
261 (GameState state (Score s1 s2) ball paddle1 paddle2) =
239 (GameState state (Score s1 s2) ball paddle1 paddle2) =
262− let { (ball',s1',s2') = if state == Play then stepBall delta ball paddle1 paddle2
240+ let (ball',s1',s2') = if state == Play then stepBall delta ball paddle1 paddle2
263− else (ball, 0, 0)
241+ else (ball, 0, 0)
242+ state' = case state of
264− ; state' = case state of { Play -> if s1' /= s2' then BetweenRounds else state
243+ Play -> if s1' /= s2' then BetweenRounds else state
265− ; BetweenRounds -> if space then Play else state }
244+ BetweenRounds -> if space then Play else state
266− } in GameState state'
245+ in GameState state'
267− (Score (s1+s1') (s2+s2'))
246+ (Score (s1+s1') (s2+s2'))
268− ball'
247+ ball'
269− (stepPaddle delta dir1 paddle1)
248+ (stepPaddle delta dir1 paddle1)
270− (stepPaddle delta dir2 paddle2)
249+ (stepPaddle delta dir2 paddle2)
271
250
272
251
273-- Now we put it all together. We have a signal of inputs that changes whenever there
252-- Now we put it all together. We have a signal of inputs that changes whenever there
@@ -296,14 +275,13 @@ gameState = foldp stepGame defaultGame input
296-- This function displays the current score and directions.
275-- This function displays the current score and directions.
297
276
298scoreBoard w inPlay p1 p2 =
277scoreBoard w inPlay p1 p2 =
299− let { code = text . monospace . toText
278+ let code = text . monospace . toText
300− ; stack top bottom = flow down [ code " ", code top, code bottom ]
279+ stack top bottom = flow down [ code " ", code top, code bottom ]
301− ; msg = width w . centeredText . monospace $ toText "Press SPACE to begin"
280+ msg = width w . centeredText . monospace $ toText "Press SPACE to begin"
302− ; board = flow right [ stack "W" "S", spacer 20 1
281+ board = flow right [ stack "W" "S", spacer 20 1
303− , text . Text.height 4 . toText $ show p1 ++ " " ++ show p2
282+ , text . Text.height 4 . toText $ show p1 ++ " " ++ show p2
304− , spacer 20 1, stack "&uarr;" "&darr;" ]
283+ , spacer 20 1, stack "&uarr;" "&darr;" ]
305− ; score = container w (heightOf board) midTop board
284+ score = container w (heightOf board) midTop board
306− }
307 in if inPlay then score else score `above` msg
285 in if inPlay then score else score `above` msg
308
286
309
287
@@ -324,18 +302,4 @@ display (w,h) (GameState state (Score p1 p2) (Ball pos _) (Paddle y1) (Paddle y2
324-- We can now define a view of the game (a signal of Elements) that changes
302-- We can now define a view of the game (a signal of Elements) that changes
325-- as the GameState changes. This is what the users will see.
303-- as the GameState changes. This is what the users will see.
326
304
327−view = lift2 display Win.dimensions gameState
305+main = lift2 display Window.dimensions gameState
328−
329−
330−-- Here we tell the JavaScript FPS manager that all of the computations for
331−-- this frame are complete. This allows the manager to calculate when the next
332−-- step should happen.
333−
334−done = lift (\_ -> castBoolToJSBool True) view
335−foreign export jsevent "finished"
336− done :: Signal JSBool
337−
338−
339−-- And finally, we display the view of the game to the user: Pong in Elm!
340−
341−main = view