diff --git a/extra/snake-game/constants/constants.factor b/extra/snake-game/constants/constants.factor deleted file mode 100644 index ce742958ce..0000000000 --- a/extra/snake-game/constants/constants.factor +++ /dev/null @@ -1,11 +0,0 @@ -! Copyright (C) 2015 Sankaranarayanan Viswanathan. -! See http://factorcode.org/license.txt for BSD license. -IN: snake-game.constants - -SYMBOLS: :left :right :up :down ; - -SYMBOLS: :head :body :tail ; - -CONSTANT: snake-game-dim { 12 10 } - -CONSTANT: snake-game-cell-size 20 diff --git a/extra/snake-game/game/game.factor b/extra/snake-game/game/game.factor index 70fdd9597c..f181157f0d 100644 --- a/extra/snake-game/game/game.factor +++ b/extra/snake-game/game/game.factor @@ -1,10 +1,16 @@ ! Copyright (C) 2015 Sankaranarayanan Viswanathan. ! See http://factorcode.org/license.txt for BSD license. -USING: accessors arrays combinators kernel make math random -sequences sets snake-game.constants snake-game.util sorting ; +USING: accessors arrays assocs combinators fry kernel make math +math.vectors random sequences sets sorting ; IN: snake-game.game +SYMBOLS: :left :right :up :down ; + +SYMBOLS: :head :body :tail ; + +CONSTANT: snake-game-dim { 12 10 } + TUPLE: snake-game snake snake-loc snake-dir food-loc { next-turn-dir initial: f } @@ -26,10 +32,33 @@ C: snake-part : ( -- snake-game ) snake-game new - >>snake - { 5 4 } clone >>snake-loc - :right >>snake-dir - { 1 1 } clone >>food-loc ; + >>snake + { 5 4 } clone >>snake-loc + :right >>snake-dir + { 1 1 } clone >>food-loc ; + +: ?roll-over ( x max -- x ) + { + { [ 2dup >= ] [ 2drop 0 ] } + { [ over neg? ] [ nip 1 - ] } + [ drop ] + } cond ; + +: move-loc ( loc dir -- loc ) + H{ + { :left { -1 0 } } + { :right { 1 0 } } + { :up { 0 -1 } } + { :down { 0 1 } } + } at v+ snake-game-dim [ ?roll-over ] 2map ; + +: opposite-dir ( dir -- dir ) + H{ + { :left :right } + { :right :left } + { :up :down } + { :down :up } + } at ; : game-loc>index ( loc -- n ) first2 snake-game-dim first * + ; @@ -37,22 +66,19 @@ C: snake-part : index>game-loc ( n -- loc ) snake-game-dim first /mod swap 2array ; -: snake-shape ( snake -- dirs ) - [ dir>> ] map ; - : grow-snake ( snake dir -- snake ) opposite-dir :head prefix dup second :body >>type drop ; : move-snake ( snake dir -- snake ) - dupd [ snake-shape but-last ] dip + [ dup but-last [ dir>> ] map ] dip opposite-dir prefix [ >>dir ] 2map ; : all-indices ( -- points ) - snake-game-dim first2 * ; + snake-game-dim product ; : snake-occupied-locs ( snake head-loc -- points ) - [ dir>> relative-loc ] accumulate nip ; + [ dir>> move-loc ] accumulate nip ; : snake-occupied-indices ( snake head-loc -- points ) snake-occupied-locs [ game-loc>index ] map natural-sort ; @@ -60,30 +86,23 @@ C: snake-part : snake-unoccupied-indices ( snake head-loc -- points ) [ all-indices ] 2dip snake-occupied-indices without ; -: snake-will-eat-food? ( snake-game dir -- ? ) - [ [ food-loc>> ] [ snake-loc>> ] bi ] dip - relative-loc = ; +: snake-will-eat-food? ( snake-game -- ? ) + [ food-loc>> ] [ snake-loc>> ] [ snake-dir>> ] tri move-loc = ; -: update-score ( snake-game -- ) - [ 1 + ] change-score - drop ; +: increase-score ( snake-game -- snake-game ) + [ 1 + ] change-score ; -: update-snake-shape ( snake-game dir growing? -- ) - [ [ grow-snake ] curry change-snake ] - [ [ move-snake ] curry change-snake ] - if drop ; +: update-snake-shape ( snake-game growing? -- snake-game ) + [ dup snake-dir>> ] dip + '[ _ _ [ grow-snake ] [ move-snake ] if ] change-snake ; -: update-snake-loc ( snake-game dir -- ) - [ relative-loc ] curry change-snake-loc drop ; +: update-snake-loc ( snake-game -- snake-game ) + dup snake-dir>> '[ _ move-loc ] change-snake-loc ; -: update-snake-dir ( snake-game dir -- ) - >>snake-dir drop ; - -: generate-food ( snake-game -- ) - [ - [ snake>> ] [ snake-loc>> ] bi - snake-unoccupied-indices random index>game-loc - ] keep food-loc<< ; +: generate-food ( snake-game -- snake-game ) + dup [ snake>> ] [ snake-loc>> ] bi + snake-unoccupied-indices random index>game-loc + >>food-loc ; : game-in-progress? ( snake-game -- ? ) [ game-over?>> ] [ paused?>> ] bi or not ; @@ -94,28 +113,24 @@ C: snake-part f >>next-turn-dir ] when* drop ; -: snake-will-eat-itself? ( snake-game dir -- ? ) - [ [ snake>> ] [ snake-loc>> ] bi ] dip relative-loc - [ snake-occupied-locs rest ] keep - swap member? ; +: snake-will-eat-itself? ( snake-game -- ? ) + [ snake>> ] [ snake-loc>> ] [ snake-dir>> ] tri move-loc + [ snake-occupied-locs rest ] keep swap member? ; : game-over ( snake-game -- ) t >>game-over? drop ; -: update-snake ( snake-game dir -- ) - 2dup snake-will-eat-food? - { - [ [ drop update-score ] [ 2drop ] if ] +: update-snake ( snake-game -- ) + dup snake-will-eat-food? { + [ [ increase-score ] when ] [ update-snake-shape ] [ drop update-snake-loc ] - [ drop update-snake-dir ] - [ nip [ generate-food ] [ drop ] if ] - } 3cleave ; + [ [ generate-food ] when ] + } cleave drop ; : do-game-step ( snake-game -- ) dup game-in-progress? [ dup ?handle-pending-turn - dup snake-dir>> - 2dup snake-will-eat-itself? - [ drop game-over ] [ update-snake ] if + dup snake-will-eat-itself? + [ game-over ] [ update-snake ] if ] [ drop ] if ; diff --git a/extra/snake-game/input/input.factor b/extra/snake-game/input/input.factor deleted file mode 100644 index 3534ccfbe7..0000000000 --- a/extra/snake-game/input/input.factor +++ /dev/null @@ -1,21 +0,0 @@ -! Copyright (C) 2015 Sankaranarayanan Viswanathan. -! See http://factorcode.org/license.txt for BSD license. -USING: assocs sets snake-game.constants ; -IN: snake-game.input - -: key-action ( key -- action ) - H{ - { "RIGHT" :right } - { "LEFT" :left } - { "UP" :up } - { "DOWN" :down } - } at ; - -: quit-key? ( key -- ? ) - HS{ "ESC" "q" "Q" } in? ; - -: pause-key? ( key -- ? ) - HS{ " " "SPACE" "p" "P" } in? ; - -: new-game-key? ( key -- ? ) - HS{ "ENTER" "RET" "n" "N" } in? ; diff --git a/extra/snake-game/snake-game.factor b/extra/snake-game/snake-game.factor index 39fca95b6e..17b469e9af 100644 --- a/extra/snake-game/snake-game.factor +++ b/extra/snake-game/snake-game.factor @@ -4,7 +4,7 @@ USING: accessors sets snake-game.ui ui ui.gadgets.status-bar ui.gadgets.worlds ; IN: snake-game : ( -- world-attributes ) - "Snake Game" >>title + "Snake Game" >>title [ { maximize-button resize-handles } without ] change-window-controls ; diff --git a/extra/snake-game/sprites/sprites.factor b/extra/snake-game/sprites/sprites.factor index 6af031bdde..26ff8438bd 100644 --- a/extra/snake-game/sprites/sprites.factor +++ b/extra/snake-game/sprites/sprites.factor @@ -28,46 +28,37 @@ IN: snake-game.sprites swap [ image ] 2dip sw sh image-part ] cartesian-map f join ; -: load-sprite-image ( filename -- image ) +: load-snake-image ( filename -- image ) "vocab:snake-game/_resources/%s" sprintf load-image ; -: make-texture ( image -- texture ) - { 0 0 } ; +: load-snake-texture ( file-name -- texture ) + load-snake-image { 0 0 } ; -: make-sprites ( filename cols rows -- seq ) - [ load-sprite-image ] 2dip generate-sprite-sheet - [ make-texture ] map ; +: load-sprite-textures ( filename cols rows -- seq ) + [ load-snake-image ] 2dip generate-sprite-sheet + [ { 0 0 } ] map ; : snake-head-textures ( -- assoc ) - "head.png" 1 4 make-sprites { "head-up" "head-right" "head-down" "head-left" } - [ swap 2array ] 2map ; - -:: assoc-with-value-like ( assoc key seq -- ) - key assoc at :> value - seq [ [ value ] dip assoc set-at ] each ; + "head.png" 1 4 load-sprite-textures zip ; : snake-body-textures ( -- assoc ) - "body.png" 3 2 make-sprites - { 1 2 3 4 5 6 } - [ swap 2array ] 2map - dup 1 { "body-right-up" "body-down-left" } assoc-with-value-like - dup 2 { "body-down-right" "body-left-up" } assoc-with-value-like - dup 3 { "body-right-right" "body-left-left" } assoc-with-value-like - dup 4 { "body-up-up" "body-down-down" } assoc-with-value-like - dup 5 { "body-up-right" "body-left-down" } assoc-with-value-like - dup 6 { "body-right-down" "body-up-left" } assoc-with-value-like - dup [ { 1 2 3 4 5 6 } ] dip [ delete-at ] curry each ; + { + "body-right-up" "body-down-right" "body-right-right" + "body-up-up" "body-up-right" "body-right-down" + } + { + "body-down-left" "body-left-up" "body-left-left" + "body-down-down" "body-left-down" "body-up-left" + } + "body.png" 3 2 load-sprite-textures '[ _ zip ] bi@ append ; : snake-tail-textures ( -- assoc ) - "tail.png" 2 2 make-sprites { "tail-down" "tail-left" "tail-up" "tail-right" } - [ swap 2array ] 2map ; + "tail.png" 2 2 load-sprite-textures zip ; : food-texture ( -- assoc ) - "food" "food.png" load-sprite-image make-texture - 2array 1array ; + "food" "food.png" load-snake-texture 2array 1array ; : background-texture ( -- assoc ) - "background" "background.png" load-sprite-image make-texture - 2array 1array ; + "background" "background.png" load-snake-texture 2array 1array ; diff --git a/extra/snake-game/ui/ui.factor b/extra/snake-game/ui/ui.factor index cd65345493..ec35c8bce1 100644 --- a/extra/snake-game/ui/ui.factor +++ b/extra/snake-game/ui/ui.factor @@ -1,13 +1,10 @@ ! Copyright (C) 2015 Sankaranarayanan Viswanathan. ! See http://factorcode.org/license.txt for BSD license. USING: accessors arrays assocs calendar combinators destructors -formatting kernel make math namespaces opengl opengl.textures -sequences sets snake-game.constants snake-game.game -snake-game.input snake-game.util snake-game.sprites timers -ui ui.gadgets ui.gadgets.worlds ui.gestures ui.render ; - -FROM: snake-game.util => screen-loc ; -FROM: snake-game.util => relative-loc ; +formatting kernel make math math.vectors namespaces opengl +opengl.textures sequences sets snake-game.game +snake-game.sprites timers ui ui.gadgets ui.gadgets.worlds +ui.gestures ui.render ; IN: snake-game.ui @@ -20,8 +17,12 @@ TUPLE: snake-gadget < gadget >>snake-game drop ; : ( -- snake-gadget ) - snake-gadget new - [ start-new-game ] keep ; + snake-gadget new [ start-new-game ] keep ; + +CONSTANT: snake-game-cell-size 20 + +: game-loc>screen-loc ( loc -- loc ) + [ snake-game-cell-size * ] map ; : lookup-texture ( key -- texture ) game-textures get at ; @@ -30,7 +31,7 @@ TUPLE: snake-gadget < gadget [ lookup-texture draw-texture ] with-translation ; : draw-sprite ( grid-loc key -- ) - swap screen-loc draw-sprite* ; + swap game-loc>screen-loc draw-sprite* ; : draw-food ( loc -- ) "food" draw-sprite ; @@ -39,17 +40,15 @@ TUPLE: snake-gadget < gadget { 0 0 } "background" draw-sprite ; : draw-snake-head ( loc facing-dir -- ) - dup name>> rest "head-" prepend - [ - [ screen-loc ] dip + dup name>> rest "head-" prepend [ + [ game-loc>screen-loc ] dip { { :right [ { -20 -10 } ] } { :down [ { -10 -20 } ] } { :up [ { -10 0 } ] } { :left [ { 0 -10 } ] } - } case offset - ] dip - swap draw-sprite* ; + } case v+ + ] dip swap draw-sprite* ; : draw-snake-body ( loc from-dir to-dir -- ) [ name>> rest ] bi@ "body-%s-%s" sprintf draw-sprite ; @@ -65,7 +64,7 @@ TUPLE: snake-gadget < gadget } case ; : next-snake-loc-from-dir ( loc from-dir snake-part -- new-loc new-from-dir ) - nip dir>> [ relative-loc ] keep ; + nip dir>> [ move-loc ] keep ; : draw-snake ( loc from-dir snake -- ) 3dup [ @@ -76,16 +75,15 @@ TUPLE: snake-gadget < gadget first draw-snake-part ; : generate-status-message ( snake-game -- str ) - [ score>> "Score: %d" sprintf ] + [ score>> ] [ { { [ dup game-over?>> ] [ drop "Game Over" ] } { [ dup paused?>> ] [ drop "Game Paused" ] } [ drop "Game In Progress" ] } cond - ] - bi 2array " -- " join ; - + ] bi "Score: %d -- %s" sprintf ; + : update-status ( gadget -- ) [ snake-game>> generate-status-message ] keep show-status ; @@ -98,6 +96,23 @@ TUPLE: snake-gadget < gadget : toggle-game-pause ( snake-gadget -- ) snake-game>> [ not ] change-paused? drop ; +: key-action ( key -- action ) + H{ + { "RIGHT" :right } + { "LEFT" :left } + { "UP" :up } + { "DOWN" :down } + } at ; + +: quit-key? ( key -- ? ) + HS{ "ESC" "q" "Q" } in? ; + +: pause-key? ( key -- ? ) + HS{ " " "SPACE" "p" "P" } in? ; + +: new-game-key? ( key -- ? ) + HS{ "ENTER" "RET" "n" "N" } in? ; + : ?handle-movement-key ( snake-game key -- ) key-action [ @@ -133,8 +148,8 @@ M: snake-gadget graft* M: snake-gadget ungraft* [ stop-timer f ] change-timer - dup textures>> values [ dispose ] each - f >>textures drop ; + [ values dispose-each f ] change-textures + drop ; M: snake-gadget pref-dim* drop snake-game-dim [ snake-game-cell-size * 20 + ] map ; diff --git a/extra/snake-game/util/util.factor b/extra/snake-game/util/util.factor deleted file mode 100644 index 50a64a5965..0000000000 --- a/extra/snake-game/util/util.factor +++ /dev/null @@ -1,45 +0,0 @@ -! Copyright (C) 2015 Sankaranarayanan Viswanathan. -! See http://factorcode.org/license.txt for BSD license. -USING: arrays assocs combinators kernel math sequences -snake-game.constants ; - -IN: snake-game.util - -: screen-loc ( loc -- loc ) - [ snake-game-cell-size * ] map ; - -: offset ( loc dim -- loc ) - [ + ] 2map ; - -: ?roll-over ( x max -- x ) - { - { [ 2dup >= ] [ 2drop 0 ] } - { [ over neg? ] [ nip 1 - ] } - [ drop ] - } cond ; - -: ?roll-over-x ( x -- x ) - snake-game-dim first ?roll-over ; - -: ?roll-over-y ( y -- y ) - snake-game-dim second ?roll-over ; - -: move ( loc dim -- loc ) - offset first2 - [ ?roll-over-x ] [ ?roll-over-y ] bi* 2array ; - -: relative-loc ( loc dir -- loc ) - { - { :left [ { -1 0 } move ] } - { :right [ { 1 0 } move ] } - { :up [ { 0 -1 } move ] } - { :down [ { 0 1 } move ] } - } case ; - -: opposite-dir ( dir -- dir ) - H{ - { :left :right } - { :right :left } - { :up :down } - { :down :up } - } at ;