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 ;
7 FROM: multi-methods => GENERIC: METHOD: ;
11 ! Inspired by this Ruby/Shoes version by why: http://gist.github.com/26431
13 ! Which was based on this Nodebox version: http://billmill.org/pong.html
16 : clamp-to-interval ( x interval -- x )
17 [ from>> first max ] [ to>> first min ] bi ;
19 TUPLE: play-field < rectangle ;
21 TUPLE: paddle < rectangle ;
23 TUPLE: computer < paddle { speed initial: 10 } ;
25 : computer-move-left ( computer -- ) dup speed>> move-left-by ;
27 : computer-move-right ( computer -- ) dup speed>> move-right-by ;
30 { diameter initial: 20 }
31 { bounciness initial: 1.2 }
32 { max-speed initial: 10 } ;
34 : above-lower-bound? ( ball field -- ? ) bottom 50 - above? ;
36 : below-upper-bound? ( ball field -- ? ) top 50 + below? ;
38 : in-bounds? ( ball field -- ? )
40 [ above-lower-bound? ]
41 [ below-upper-bound? ]
44 :: bounce-change-vertical-velocity ( BALL -- )
50 :: bounce-off-paddle ( BALL PADDLE -- )
51 BALL bounce-change-vertical-velocity
52 BALL x PADDLE center x - 0.25 * BALL vel>> (x!)
53 PADDLE top BALL pos>> (y!) ;
55 : mouse-x ( -- x ) hand-loc get first ;
57 :: valid-paddle-interval ( PADDLE PLAY-FIELD -- interval )
58 PLAY-FIELD [ left ] [ right ] bi PADDLE width - [a,b] ;
60 :: align-paddle-with-mouse ( PADDLE PLAY-FIELD -- )
62 PADDLE PLAY-FIELD valid-paddle-interval
66 ! Protocol for drawing PONG objects
68 GENERIC: draw ( obj -- )
70 METHOD: draw { paddle } [ bottom-left ] [ dim>> ] bi draw-rectangle ;
72 METHOD: draw { ball } [ pos>> ] [ diameter>> 2 / ] bi draw-circle ;
74 TUPLE: pong-gadget < gadget paused field ball player computer ;
78 T{ play-field { pos { 0 0 } } { dim { 400 400 } } } clone >>field
79 T{ ball { pos { 50 50 } } { vel { 3 4 } } } clone >>ball
80 T{ paddle { pos { 200 396 } } { dim { 75 4 } } } clone >>player
81 T{ computer { pos { 200 0 } } { dim { 75 4 } } } clone >>computer ;
83 M: pong-gadget pref-dim* ( <pong> -- dim ) drop { 400 400 } ;
85 M: pong-gadget ungraft* ( <pong> -- ) t >>paused drop ;
87 M:: pong-gadget draw-gadget* ( PONG -- )
92 :: iterate-system ( GADGET -- )
93 GADGET field>> :> FIELD
95 GADGET player>> :> PLAYER
96 GADGET computer>> :> COMPUTER
98 BALL FIELD in-bounds? [
100 PLAYER FIELD align-paddle-with-mouse
106 BALL COMPUTER to-the-left-of? [ COMPUTER computer-move-left ] when
107 BALL COMPUTER to-the-right-of? [ COMPUTER computer-move-right ] when
109 ! check if ball bounced off something
111 ! player-blocked-ball?
112 BALL PLAYER { [ above? ] [ in-between-horizontally? ] } 2&&
113 [ BALL PLAYER bounce-off-paddle ] when
115 ! computer-blocked-ball?
116 BALL COMPUTER { [ below? ] [ in-between-horizontally? ] } 2&&
117 [ BALL COMPUTER bounce-off-paddle ] when
120 BALL FIELD in-between-horizontally? not
121 [ BALL reverse-horizontal-velocity ] when
123 ] [ t GADGET paused<< ] if ;
125 :: start-pong-thread ( GADGET -- )
130 [ GADGET iterate-system GADGET relayout-1 25 milliseconds sleep t ]
135 MAIN-WINDOW: pong-window
137 pong [ >>gadgets ] [ start-pong-thread ] bi ;