xturtle 0.0.7 → 0.0.8
raw patch · 7 files changed
+183/−181 lines, 7 files
Files
- src/Graphics/X11/Turtle.hs +49/−84
- src/Graphics/X11/TurtleDraw.hs +0/−90
- src/Graphics/X11/TurtleInput.hs +3/−1
- src/Graphics/X11/TurtleMove.hs +79/−0
- src/Graphics/X11/TurtleShape.hs +45/−0
- src/Graphics/X11/TurtleState.hs +4/−2
- xturtle.cabal +3/−4
src/Graphics/X11/Turtle.hs view
@@ -2,6 +2,7 @@ Turtle, openField,+-- closeField, newTurtle, shape,@@ -27,51 +28,57 @@ xturtleVersion ) where -import Graphics.X11.TurtleDraw-import Graphics.X11.TurtleInput-import Control.Concurrent-import Control.Monad+import Graphics.X11.TurtleMove(+ Field, Layer, Character,+ forkIOX, openField, -- closeField,+ addCharacter, addLayer, layerSize,+ moveTurtle+ )+import Graphics.X11.TurtleInput(+ TurtleInput(..), TurtleState,+ getTurtleStates, getPosition, getPendown, undonum+ )+import Graphics.X11.TurtleShape(lookupShape, classic)+import Control.Concurrent(Chan, writeChan, threadDelay)+import Control.Monad(replicateM_, zipWithM_) import Prelude hiding(Left)-import Data.IORef-import Control.Arrow(second)+import Data.IORef(IORef, newIORef, readIORef, modifyIORef) xturtleVersion :: (Int, String)-xturtleVersion = (1, "0.0.7")+xturtleVersion = (14, "0.0.8") data Turtle = Turtle {+ layer :: Layer,+ character :: Character, inputChan :: Chan TurtleInput, states :: [TurtleState],- stateNow :: IORef Int,- layer :: Layer,- character :: Character+ stateIndex :: IORef Int } newTurtle :: Field -> IO Turtle newTurtle f = do ch <- addCharacter f l <- addLayer f- (c, sts) <- getTurtleStates classic- sn <- newIORef 1+ (ic, sts) <- getTurtleStates classic+ si <- newIORef 1 let t = Turtle {- inputChan = c,+ inputChan = ic, layer = l, character = ch, states = sts,- stateNow = sn+ stateIndex = si }- _ <- forkIOX $ for2M_ sts $ turtleDraw ch l+ _ <- forkIOX $ zipWithM_ (moveTurtle ch l) sts $ tail sts return t sendCommand :: Turtle -> TurtleInput -> IO ()-sendCommand Turtle{inputChan = c, stateNow = sn} ti = do- modifyIORef sn (+ 1)+sendCommand Turtle{inputChan = c, stateIndex = si} ti = do+ modifyIORef si (+ 1) writeChan c ti threadDelay 10000 shape :: Turtle -> String -> IO ()-shape t "turtle" = sendCommand t $ Shape turtle-shape t "classic" = sendCommand t $ Shape classic-shape _ name = error $ "There is no shape named " ++ name+shape t = sendCommand t . Shape . lookupShape shapesize :: Turtle -> Double -> IO () shapesize t = sendCommand t . ShapeSize@@ -84,6 +91,15 @@ left t = sendCommand t . Left right t = left t . negate +goto :: Turtle -> Double -> Double -> IO ()+goto t x y = sendCommand t $ Goto x y++home :: Turtle -> IO ()+home t = goto t 0 0 >> sendCommand t (Rotate 0)++clear :: Turtle -> IO ()+clear t = sendCommand t Clear+ circle :: Turtle -> Double -> IO () circle t r = do forward t (r * pi / 36)@@ -92,77 +108,26 @@ forward t (r * pi / 36) sendCommand t $ Undonum 74 -home :: Turtle -> IO ()-home t = goto t 0 0 >> rotate t 0+penup, pendown :: Turtle -> IO ()+penup = flip sendCommand Penup+pendown = flip sendCommand Pendown -clear :: Turtle -> IO ()-clear t@Turtle{layer = l} = do- left t 0- clearLayer l+undo :: Turtle -> IO ()+undo t = readIORef (stateIndex t)+ >>= flip replicateM_ (sendCommand t Undo) . undonum . (states t !!) +windowWidth, windowHeight :: Turtle -> IO Double+windowWidth = fmap fst . layerSize . layer+windowHeight = fmap snd . layerSize . layer+ position :: Turtle -> IO (Double, Double)-position Turtle{stateNow = sn, states = s} =- fmap (getPosition . (s !!)) $ readIORef sn+position Turtle{stateIndex = si, states = s} =+ fmap (getPosition . (s !!)) $ readIORef si distance :: Turtle -> Double -> Double -> IO Double distance t x0 y0 = do (x, y) <- position t return $ ((x - x0) ** 2 + (y - y0) ** 2) ** (1 / 2) -windowWidth, windowHeight :: Turtle -> IO Double-windowWidth = fmap fst . layerSize . layer-windowHeight = fmap snd . layerSize . layer--pendown, penup :: Turtle -> IO ()-pendown = flip sendCommand Pendown-penup = flip sendCommand Penup- isdown :: Turtle -> IO Bool-isdown Turtle{states = s, stateNow = sn} =- fmap (getPendown . (s !!)) $ readIORef sn--goto :: Turtle -> Double -> Double -> IO ()-goto t x y = sendCommand t $ Goto x y--rotate :: Turtle -> Double -> IO ()-rotate t = sendCommand t . Rotate--undo :: Turtle -> IO ()-undo t = do- un <- getUndoNum t- replicateM_ un $ sendCommand t Undo--getUndoNum :: Turtle -> IO Int-getUndoNum Turtle{states = s, stateNow = sn} =- fmap (undonum . (s!!)) $ readIORef sn--for2M_ :: [a] -> (a -> a -> IO b) -> IO ()-for2M_ xs f = zipWithM_ f xs $ tail xs--classic :: [(Double, Double)]-classic = clssc ++ reverse (map (second negate) clssc)- where- clssc = [- (- 10, 0),- (- 16, 6),- (0, 0)- ]--turtle :: [(Double, Double)]-turtle = ttl ++ reverse (map (second negate) ttl)- where- ttl = [- (- 10, 0),- (- 8, - 3),- (- 10, - 5),- (- 7, - 9),- (- 5, - 6),- (0, - 8),- (4, - 7),- (6, - 10),- (8, - 7),- (7, - 5),- (10, - 2),- (13, - 3),- (16, 0)- ]+isdown t = fmap (getPendown . (states t !!)) $ readIORef $ stateIndex t
− src/Graphics/X11/TurtleDraw.hs
@@ -1,90 +0,0 @@-module Graphics.X11.TurtleDraw (- Field,- Layer,- Character,-- forkIOX,- openField,- addLayer,- addCharacter,- layerSize,-- turtleDraw,-- clearLayer-) where--import Graphics.X11.TurtleState(TurtleState(..))-import Graphics.X11.WindowLayers(- Field, Layer, Character,- forkIOX, openField, addLayer, addCharacter, layerSize, clearLayer,- drawLine, drawCharacter, drawCharacterAndLine, undoLayer- )--import Control.Concurrent(threadDelay)-import Control.Monad(when, forM_)-import Control.Arrow((***))--step :: Double-step = 10--moveSpeed :: Int-moveSpeed = 50000--stepDir :: Double-stepDir = 5--rotateSpeed :: Int-rotateSpeed = 10000--turtleDraw, turtleDrawNotUndo, turtleDrawUndo ::- Character -> Layer -> TurtleState -> TurtleState -> IO ()-turtleDraw c l t0 t1 = if undo t1- then turtleDrawUndo c l t0 t1- else turtleDrawNotUndo c l t0 t1-turtleDrawUndo c l t0 t1 = do- let p0@(x0, y0) = position t0- p1@(x1, y1) = position t1- lineOrigin = if line t0 then Just p1 else Nothing- when (line t0) $ undoLayer l- forM_ (getDirections (direction t0) (direction t1)) $ \d -> do- drawTurtle c (shape t1) (size t1) d p0 Nothing- threadDelay rotateSpeed- forM_ (getPoints x0 y0 x1 y1) $ \p -> do- drawTurtle c (shape t1) (size t1) (direction t1) p lineOrigin- threadDelay moveSpeed- drawTurtle c (shape t1) (size t1) (direction t1) p1 lineOrigin-turtleDrawNotUndo c l t0 t1 = do- let p0@(x0, y0) = position t0- p1@(x1, y1) = position t1- lineOrigin = if line t1 then Just p0 else Nothing- forM_ (getDirections (direction t0) (direction t1)) $ \d -> do- drawTurtle c (shape t1) (size t1) d p0 Nothing- threadDelay rotateSpeed- forM_ (getPoints x0 y0 x1 y1) $ \p -> do- drawTurtle c (shape t1) (size t1) (direction t1) p lineOrigin- threadDelay moveSpeed- drawTurtle c (shape t1) (size t1) (direction t1) p1 lineOrigin- when (line t1) $ drawLine l x0 y0 x1 y1--getPoints :: Double -> Double -> Double -> Double -> [(Double, Double)]-getPoints x1 y1 x2 y2 = zip [x1, x1 + dx .. x2 - dx] [y1, y1 + dy .. y2 - dy]- where- len = ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** (1/2)- dx = (x2 - x1) * step / len- dy = (y2 - y1) * step / len--getDirections :: Double -> Double -> [Double]-getDirections ds de = [ds, ds + dd .. de - dd]- where- dd = if de > ds then stepDir else - stepDir--drawTurtle :: Character -> [(Double, Double)] -> Double -> Double ->- (Double, Double) -> Maybe (Double, Double) -> IO ()-drawTurtle c sh s d (px, py) org = do- let sp = map (((+ px) *** (+ py)) . rotatePoint . ((* s) *** (* s))) sh- maybe (drawCharacter c sp)- (\(x0, y0) -> (drawCharacterAndLine c sp x0 y0 px py)) org- where- rotatePoint (x, y) = let rad = d * pi / 180 in- (x * cos rad - y * sin rad, x * sin rad + y * cos rad)
src/Graphics/X11/TurtleInput.hs view
@@ -26,6 +26,7 @@ | Penup | Pendown | Undo+ | Clear | Forward Double | Left Double | Undonum Int@@ -51,10 +52,11 @@ nextTurtle t Pendown = (clearState t){pendown = True} nextTurtle t Penup = (clearState t){pendown = False} nextTurtle t (Undonum un) = (clearState t){undonum = un}+nextTurtle t (Clear) = (clearState t){clear = True} nextTurtle _ _ = error "not defined" clearState :: TurtleState -> TurtleState-clearState t = t{line = False, undo = False, undonum = 1}+clearState t = t{line = False, undo = False, undonum = 1, clear = False} inputToTurtle :: [TurtleState] -> TurtleState -> [TurtleInput] -> [TurtleState] inputToTurtle [] ts0 (Undo : tis) = ts0 : inputToTurtle [] ts0 tis
+ src/Graphics/X11/TurtleMove.hs view
@@ -0,0 +1,79 @@+module Graphics.X11.TurtleMove (+ Field,+ Layer,+ Character,++ forkIOX,+ openField,+ closeField,+ addLayer,+ addCharacter,+ layerSize,++ moveTurtle+) where++import Graphics.X11.TurtleState(TurtleState(..))+import Graphics.X11.WindowLayers(+ Field, Layer, Character,+ forkIOX, openField, closeField,+ addLayer, addCharacter, layerSize, clearLayer,+ drawLine, drawCharacter, drawCharacterAndLine, undoLayer+ )++import Control.Concurrent(threadDelay)+import Control.Monad(when, forM_)+import Control.Arrow((***))++type Pos = (Double, Double)++step :: Double+step = 10++moveSpeed :: Int+moveSpeed = 50000++stepDir :: Double+stepDir = 5++rotateSpeed :: Int+rotateSpeed = 10000++moveTurtle :: Character -> Layer -> TurtleState -> TurtleState -> IO ()+moveTurtle c l t0 t1 = do+ when (undo t1 && line t0) $ undoLayer l+ forM_ (getDirections (direction t0) (direction t1)) $ \d -> do+ drawTurtle c (shape t1) (size t1) d p0 Nothing+ threadDelay rotateSpeed+ forM_ (getPositions x0 y0 x1 y1) $ \p -> do+ drawTurtle c (shape t1) (size t1) (direction t1) p lineOrigin+ threadDelay moveSpeed+ drawTurtle c (shape t1) (size t1) (direction t1) p1 lineOrigin+ when (not (undo t1) && line t1) $ drawLine l x0 y0 x1 y1+ when (clear t1) $ clearLayer l+ where+ (tl, to) = if undo t1 then (t0, t1) else (t1, t0)+ lineOrigin = if line tl then Just $ position to else Nothing+ p0@(x0, y0) = position t0+ p1@(x1, y1) = position t1++getPositions :: Double -> Double -> Double -> Double -> [Pos]+getPositions x0 y0 x1 y1 = zip [x0, x0 + dx .. x1 - dx] [y0, y0 + dy .. y1 - dy]+ where+ dist = ((x1 - x0) ** 2 + (y1 - y0) ** 2) ** (1/2)+ dx = step * (x1 - x0) / dist+ dy = step * (y1 - y0) / dist++getDirections :: Double -> Double -> [Double]+getDirections ds de = [ds, ds + dd .. de - dd]+ where+ dd = if de > ds then stepDir else - stepDir++drawTurtle :: Character -> [Pos] -> Double -> Double -> Pos -> Maybe Pos -> IO ()+drawTurtle c sh s d (px, py) org = do+ let sp = map (((+ px) *** (+ py)) . rotatePoint . ((* s) *** (* s))) sh+ maybe (drawCharacter c sp)+ (\(x0, y0) -> (drawCharacterAndLine c sp x0 y0 px py)) org+ where+ rotatePoint (x, y) = let rad = d * pi / 180 in+ (x * cos rad - y * sin rad, x * sin rad + y * cos rad)
+ src/Graphics/X11/TurtleShape.hs view
@@ -0,0 +1,45 @@+module Graphics.X11.TurtleShape(+ lookupShape,+ classic+ ) where++import Control.Arrow(second)+import Data.Maybe(fromMaybe)++lookupShape :: String -> [(Double, Double)]+lookupShape sn = fromMaybe (error errMsg) $ lookup sn shapeList+ where errMsg = "There is no shape named " ++ sn++shapeList :: [(String, [(Double, Double)])]+shapeList = [+ ("classic", classic),+ ("turtle", turtle)+ ]++classic :: [(Double, Double)]+classic = clssc ++ reverse (map (second negate) clssc)+ where+ clssc = [+ (- 10, 0),+ (- 16, 6),+ (0, 0)+ ]++turtle :: [(Double, Double)]+turtle = ttl ++ reverse (map (second negate) ttl)+ where+ ttl = [+ (- 10, 0),+ (- 8, - 3),+ (- 10, - 5),+ (- 7, - 9),+ (- 5, - 6),+ (0, - 8),+ (4, - 7),+ (6, - 10),+ (8, - 7),+ (7, - 5),+ (10, - 2),+ (13, - 3),+ (16, 0)+ ]
src/Graphics/X11/TurtleState.hs view
@@ -11,7 +11,8 @@ pendown :: Bool, line :: Bool, undo :: Bool,- undonum :: Int+ undonum :: Int,+ clear :: Bool } deriving Show initialTurtleState :: [(Double, Double)] -> TurtleState@@ -23,5 +24,6 @@ pendown = True, line = False, undo = False,- undonum = 1+ undonum = 1,+ clear = False }
xturtle.cabal view
@@ -2,7 +2,7 @@ cabal-version: >= 1.6 name: xturtle-version: 0.0.7+version: 0.0.8 stability: experimental author: Yoshikuni Jujo <PAF01143@nifty.ne.jp> maintainer: Yoshikuni Jujo <PAF01143@nifty.ne.jp>@@ -32,6 +32,5 @@ Exposed-modules: Graphics.X11.Turtle Build-depends: base > 3 && < 5, yjtools >= 0.9.13, convertible, X11 Ghc-options: -Wall- Other-modules: Graphics.X11.WindowLayers,- Graphics.X11.TurtleInput,- Graphics.X11.TurtleDraw, Graphics.X11.TurtleState+ Other-modules: Graphics.X11.WindowLayers, Graphics.X11.TurtleInput,+ Graphics.X11.TurtleMove, Graphics.X11.TurtleState, Graphics.X11.TurtleShape