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 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! Inspired by this Ruby/Shoes version by why: http://gist.github.com/26431 ! ! Which was based on this Nodebox version: http://billmill.org/pong.html ! by Bill Mill. ! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! : 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 paused field ball player computer ; : pong ( -- gadget ) new-gadget T{ { pos { 0 0 } } { dim { 400 400 } } } clone >>field T{ { pos { 50 50 } } { vel { 3 4 } } } clone >>ball T{ { pos { 200 396 } } { dim { 75 4 } } } clone >>player T{ { pos { 200 0 } } { dim { 75 4 } } } clone >>computer ; M: pref-dim* ( -- dim ) drop { 400 400 } ; M: ungraft* ( -- ) t >>paused drop ; ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! M:: draw-gadget* ( PONG -- ) PONG computer>> draw PONG player>> draw PONG ball>> draw ; ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :: iterate-system ( GADGET -- ) [let | FIELD [ GADGET field>> ] BALL [ GADGET ball>> ] PLAYER [ GADGET player>> ] COMPUTER [ GADGET computer>> ] | [wlet | align-player-with-mouse [ ( -- ) PLAYER 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 FIELD in-between-horizontally? not ] stop-game [ ( -- ) t GADGET (>>paused) ] | BALL 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 ] [ stop-game ] if ] ] ( gadget -- ) ; ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :: start-pong-thread ( GADGET -- ) f GADGET (>>paused) [ [ GADGET paused>> [ f ] [ GADGET iterate-system GADGET relayout-1 25 milliseconds sleep t ] if ] loop ] in-thread ; ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! : pong-window ( -- ) pong [ "PONG" open-window ] [ start-pong-thread ] bi ; : pong-main ( -- ) [ pong-window ] with-ui ; MAIN: pong-window