1 USING: accessors alien.c-types alien.data arrays calendar colors
2 combinators combinators.short-circuit flatland generalizations
3 grouping kernel locals math math.intervals math.order
4 math.rectangles math.vectors namespaces opengl opengl.gl
5 opengl.glu processing.shapes sequences sequences.generalizations
6 shuffle threads ui ui.gadgets ui.gestures ui.render ;
9 ! Inspired by this Ruby/Shoes version by why: http://gist.github.com/26431
11 ! Which was based on this Nodebox version: http://billmill.org/pong.html
14 : clamp-to-interval ( x interval -- x )
15 [ from>> first ] [ to>> first ] bi clamp ;
17 TUPLE: play-field < rectangle ;
19 TUPLE: paddle < rectangle ;
21 TUPLE: computer < paddle { speed initial: 10 } ;
23 : computer-move-left ( computer -- ) dup speed>> move-left-by ;
25 : computer-move-right ( computer -- ) dup speed>> move-right-by ;
28 { diameter initial: 20 }
29 { bounciness initial: 1.2 }
30 { max-speed initial: 10 } ;
32 : above-lower-bound? ( ball field -- ? ) bottom 50 - above? ;
34 : below-upper-bound? ( ball field -- ? ) top 50 + below? ;
36 : in-bounds? ( ball field -- ? )
38 [ above-lower-bound? ]
39 [ below-upper-bound? ]
42 :: bounce-change-vertical-velocity ( BALL -- )
48 :: bounce-off-paddle ( BALL PADDLE -- )
49 BALL bounce-change-vertical-velocity
50 BALL x PADDLE center x - 0.25 * BALL vel>> (x!)
51 PADDLE top BALL pos>> (y!) ;
53 : mouse-x ( -- x ) hand-loc get first ;
55 :: valid-paddle-interval ( PADDLE PLAY-FIELD -- interval )
56 PLAY-FIELD [ left ] [ right ] bi PADDLE width - [a,b] ;
58 :: align-paddle-with-mouse ( PADDLE PLAY-FIELD -- )
60 PADDLE PLAY-FIELD valid-paddle-interval
64 ! Protocol for drawing PONG objects
66 GENERIC: draw ( obj -- )
68 M: paddle draw [ bottom-left ] [ dim>> ] bi draw-rectangle ;
70 M: ball draw [ pos>> ] [ diameter>> 2 / ] bi draw-circle ;
72 TUPLE: pong-gadget < gadget paused field ball player computer ;
76 T{ play-field { pos { 0 0 } } { dim { 400 400 } } } clone >>field
77 T{ ball { pos { 50 50 } } { vel { 3 4 } } } clone >>ball
78 T{ paddle { pos { 200 396 } } { dim { 75 4 } } } clone >>player
79 T{ computer { pos { 200 0 } } { dim { 75 4 } } } clone >>computer ;
81 M: pong-gadget pref-dim* ( <pong> -- dim ) drop { 400 400 } ;
83 M: pong-gadget ungraft* ( <pong> -- ) t >>paused drop ;
85 M:: pong-gadget draw-gadget* ( PONG -- )
90 :: iterate-system ( GADGET -- )
91 GADGET field>> :> FIELD
93 GADGET player>> :> PLAYER
94 GADGET computer>> :> COMPUTER
96 BALL FIELD in-bounds? [
98 PLAYER FIELD align-paddle-with-mouse
104 BALL COMPUTER to-the-left-of? [ COMPUTER computer-move-left ] when
105 BALL COMPUTER to-the-right-of? [ COMPUTER computer-move-right ] when
107 ! check if ball bounced off something
109 ! player-blocked-ball?
110 BALL PLAYER { [ above? ] [ in-between-horizontally? ] } 2&&
111 [ BALL PLAYER bounce-off-paddle ] when
113 ! computer-blocked-ball?
114 BALL COMPUTER { [ below? ] [ in-between-horizontally? ] } 2&&
115 [ BALL COMPUTER bounce-off-paddle ] when
118 BALL FIELD in-between-horizontally? not
119 [ BALL reverse-horizontal-velocity ] when
121 ] [ t GADGET paused<< ] if ;
123 :: start-pong-thread ( GADGET -- )
128 [ GADGET iterate-system GADGET relayout-1 25 milliseconds sleep t ]
133 MAIN-WINDOW: pong-window
135 pong [ >>gadgets ] [ start-pong-thread ] bi ;