java - Clojure snake skips positions -


i'm clojure beginner , i've been playing around snake game code presented here https://github.com/stuarthalloway/programming-clojure/blob/master/src/examples/snake.clj. when run game snake seems skip positions while moving, doesn't go square square expected. when turn snake , hold down direction key starts behave , moves square square, release key starts skipping again. guess has way swing draws on components or handles events, haven't been able figure out or debug it. snake move square square without skipping when i'm not holding down key. here code, it's same link gave small modifications regarding space , walls:

(ns app.core   (:import (java.awt color dimension)            (javax.swing jpanel jframe timer joptionpane windowconstants)            (java.awt.event actionlistener keylistener))   (:use app.util.import-static)) (import-static java.awt.event.keyevent vk_left vk_right vk_up vk_down)  ; --------------------------------------------------------------------- ; functional model ; --------------------------------------------------------------------- ; constants describe time, space , motion (def width 19) (def height 10) (def point-size 25) (def turn-millis 150) (def win-length 500) (def dirs {vk_left  [-1 0]            vk_right [1 0]            vk_up    [0 -1]            vk_down  [0 1]})  ; math functions game board (defn add-points [& pts]   (vec (apply map + pts)))  (defn point-to-screen-rect [pt]   (map #(* point-size %)        [(pt 0) (pt 1) 1 1]))  ; function creating apple (defn create-apple []   {:location [(rand-int width) (rand-int height)]    :color (color. 210 50 90)    :type :apple})  ; function creating snake (defn create-snake []   {:body (list [1 1])    :dir [1 0]    :type :snake    :color (color. 15 160 70)})  ; function moving snake (defn move [{:keys [body dir] :as snake} & grow]   (assoc snake :body (cons (add-points (first body) dir)                            (if grow body (butlast body)))))  ; function checking if player won (defn win? [{body :body}]   (>= (count body) win-length))  ; function checking if player lost game, ; means head of snake has overlaped ; body (defn head-overlaps-body? [{[head & body] :body}]   (contains? (set body) head))  (defn out-of-bounds? [{[head] :body}]   (or (< (head 0) 0)       (> (head 0) width)       (< (head 1) 0)       (> (head 1) height)))  (defn lose? [snake]   (or (head-overlaps-body? snake) (out-of-bounds? snake)))  ; function checking if snake eats apple ; (check if head location equals apple location) (defn eats? [{[snake-head] :body} {apple :location}]   (= snake-head apple))  ; function changes direction (defn turn [snake newdir]   (assoc snake :dir newdir))  ; --------------------------------------------------------------------- ; mutable model ; --------------------------------------------------------------------- ; function resets game state (defn reset-game [snake apple]   (dosync (ref-set snake (create-snake))           (ref-set apple (create-apple)))   nil)  ; function updating direction of snake (defn update-direction [snake newdir]   (when newdir (dosync (alter snake turn newdir))))  ; function updating positions of snake , apple (defn update-positions [snake apple]   (dosync     (if (eats? @snake @apple)       (do (ref-set apple (create-apple))           (alter snake move :grow))       (alter snake move)))   nil)  ; --------------------------------------------------------------------- ; gui ; --------------------------------------------------------------------- ; function making point on screen (defn fill-point [g pt color]   (let [[x y width height] (point-to-screen-rect pt)]     (.setcolor g color)     (.fillrect g x y width height)))   ; function painting snakes , apples (defmulti paint (fn [g object & _] (:type object)))  (defmethod paint :apple [g {:keys [location color]}]   (fill-point g location color))  (defmethod paint :snake [g {:keys [body color]}]   (doseq [point body]     (fill-point g point color)))  ; game panel (defn game-panel [frame snake apple]   (proxy [jpanel actionlistener keylistener] []     (paintcomponent [g]       (proxy-super paintcomponent g)       (paint g @snake)       (paint g @apple))     (actionperformed [e]       (update-positions snake apple)       (when (lose? @snake)         (reset-game snake apple)         (joptionpane/showmessagedialog frame "game over!"))       (when (win? @snake)         (reset-game snake apple)         (joptionpane/showmessagedialog frame "you win!"))       (.repaint this))     (keypressed [e]       (update-direction snake (dirs (.getkeycode e))))     (getpreferredsize []       (dimension. (* (inc width) point-size)                   (* (inc height) point-size)))     (keyreleased [e])     (keytyped [e])))  ; main game function (defn game []   (let [snake (ref (create-snake))         apple (ref (create-apple))         frame (jframe. "snake")         panel (game-panel frame snake apple)         timer (timer. turn-millis panel)]     (doto panel       (.setfocusable true)       (.addkeylistener panel))     (doto frame       (.add panel)       (.pack)       (.setvisible true)       (.setresizable false)       (.setdefaultcloseoperation windowconstants/exit_on_close))     (.start timer)     [snake, apple, timer])) 

edit:

also tried implementation here http://java.ociweb.com/mark/programming/clojuresnake.html , has same problem. it's swing related problem. considering using the seesaw library since wrapper swing problem stay.


Comments

Popular posts from this blog

node.js - Using Node without global install -

How to access a php class file from PHPFox framework into javascript code written in simple HTML file? -

java - Null response to php query in android, even though php works properly -