diff --git a/extra/pong/pong.factor b/extra/pong/pong.factor new file mode 100644 index 0000000000..befb64a7a7 --- /dev/null +++ b/extra/pong/pong.factor @@ -0,0 +1,195 @@ + +USING: kernel accessors locals math math.intervals math.order + namespaces sequences threads + ui + ui.gadgets + ui.gestures + ui.render + calendar + multi-methods + multi-method-syntax + combinators.short-circuit.smart + combinators.cleave.enhanced + processing.shapes + flatland ; + +IN: pong + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: clamp-to-interval ( x interval -- x ) + [ from>> first max ] [ to>> first min ] bi ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +TUPLE: < ; +TUPLE: < ; + +TUPLE: < { speed initial: 10 } ; + +: computer-move-left ( computer -- ) dup speed>> move-left-by ; +: computer-move-right ( computer -- ) dup speed>> move-right-by ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +TUPLE: < + { diameter initial: 20 } + { bounciness initial: 1.2 } + { max-speed initial: 10 } ; + +: above-lower-bound? ( ball field -- ? ) bottom 50 - above? ; +: below-upper-bound? ( ball field -- ? ) top 50 + below? ; + +: in-bounds? ( ball field -- ? ) + { + [ above-lower-bound? ] + [ below-upper-bound? ] + } && ; + +:: bounce-change-vertical-velocity ( BALL -- ) + + BALL vel>> y neg + BALL bounciness>> * + + BALL max-speed>> min + + BALL vel>> (y!) ; + +:: bounce-off-paddle ( BALL PADDLE -- ) + + BALL bounce-change-vertical-velocity + + BALL x PADDLE center x - 0.25 * BALL vel>> (x!) + + PADDLE top BALL pos>> (y!) ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: mouse-x ( -- x ) hand-loc get first ; + +:: valid-paddle-interval ( PADDLE PLAY-FIELD -- interval ) + + PLAY-FIELD [ left ] [ right ] bi PADDLE width - [a,b] ; + +:: align-paddle-with-mouse ( PADDLE PLAY-FIELD -- ) + + mouse-x + + PADDLE PLAY-FIELD valid-paddle-interval + + clamp-to-interval + + PADDLE pos>> (x!) ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +! Protocol for drawing PONG objects + +GENERIC: draw ( obj -- ) + +METHOD: draw ( -- ) [ bottom-left ] [ dim>> ] bi rectangle ; +METHOD: draw ( -- ) [ pos>> ] [ diameter>> 2 / ] bi circle ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +USE: syntax ! Switch back to core 'TUPLE:' instead of the one provided + ! by multi-methods + +TUPLE: < gadget draw closed ; + +M: pref-dim* ( -- dim ) drop { 400 400 } ; +M: draw-gadget* ( -- ) draw>> call ; +M: ungraft* ( -- ) t >>closed drop ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: make-draw-closure ( -- closure ) + + ! Establish some bindings + + [let | PLAY-FIELD [ T{ { pos { 0 0 } } { dim { 400 400 } } } ] + BALL [ T{ { pos { 50 50 } } { vel { 3 4 } } } ] + + PLAYER [ T{ { pos { 200 396 } } { dim { 75 4 } } } ] + COMPUTER [ T{ { pos { 200 0 } } { dim { 75 4 } } } ] | + + ! Define some internal words in terms of those bindings ... + + [wlet | align-player-with-mouse [ ( -- ) + PLAYER PLAY-FIELD align-paddle-with-mouse ] + + move-ball [ ( -- ) BALL 1 move-for ] + + player-blocked-ball? [ ( -- ? ) + BALL PLAYER { [ above? ] [ in-between-horizontally? ] } && ] + + computer-blocked-ball? [ ( -- ? ) + BALL COMPUTER { [ below? ] [ in-between-horizontally? ] } && ] + + bounce-off-wall? [ ( -- ? ) + BALL PLAY-FIELD in-between-horizontally? not ] | + + ! Note, we're returning a quotation. + ! The quotation closes over the bindings established by the 'let'. + ! Thus the name of the word 'make-draw-closure'. + ! This closure is intended to be placed in the 'draw' slot of a + ! gadget. + + [ + + BALL PLAY-FIELD in-bounds? + [ + align-player-with-mouse + + move-ball + + ! computer reaction + + BALL COMPUTER to-the-left-of? [ COMPUTER computer-move-left ] when + BALL COMPUTER to-the-right-of? [ COMPUTER computer-move-right ] when + + ! check if ball bounced off something + + player-blocked-ball? [ BALL PLAYER bounce-off-paddle ] when + computer-blocked-ball? [ BALL COMPUTER bounce-off-paddle ] when + bounce-off-wall? [ BALL reverse-horizontal-velocity ] when + + ! draw the objects + + COMPUTER draw + PLAYER draw + BALL draw + + ] + when + + ] ] ] ( -- closure ) ; ! The trailing stack effect here is a workaround. + ! The stack effects in the wlet expression throw + ! off the effect for the whole word, so we reset + ! it to the correct one here. + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +:: pong-loop-step ( PONG -- ? ) + PONG closed>> + [ f ] + [ PONG relayout-1 25 milliseconds sleep t ] + if ; + +:: start-pong-thread ( PONG -- ) [ [ PONG pong-loop-step ] loop ] in-thread ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: play-pong ( -- ) + + new-gadget + make-draw-closure >>draw + dup "PONG" open-window + + start-pong-thread ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: play-pong-main ( -- ) [ play-pong ] with-ui ; + +MAIN: play-pong-main \ No newline at end of file