/
MainCircleMouse.hs
109 lines (92 loc) · 2.98 KB
/
MainCircleMouse.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
{-# LANGUAGE Arrows #-}
import Data.IORef
import FRP.Yampa as Yampa
import Graphics.UI.SDL as SDL
-- Helper functions
import YampaSDL
width :: Num a => a
width = 640
height :: Num a => a
height = 480
-- | Reactimation.
--
-- This main function runs an FRP system by producing a signal, passing it
-- through a signal function, and consuming it.
--
-- The first two arguments to reactimate are the value of the input signal
-- at time zero and at subsequent times, together with the times between
-- samples.
--
-- The third argument to reactimate is the output consumer that renders
-- the signal.
--
-- The last argument is the actual signal function.
--
main = do
timeRef <- newIORef (0 :: Int)
controllerRef <- newIORef $ Controller (0,0)
reactimate (initGraphs >> readIORef controllerRef)
(\_ -> do
dtSecs <- yampaSDLTimeSense timeRef
mInput <- sdlGetController controllerRef
-- print (mInput)
return (dtSecs, Just mInput)
)
(\_ e -> display (e) >> return False)
player
-- * FRP stuff
-- | Player is going in circles around the input controller position
player :: SF Controller (Double, Double)
player = arr controllerPos >>> inCircles
-- | Coordinate of a body going in circles around another body.
inCircles :: SF (Double, Double) (Double, Double)
inCircles = proc (centerX, centerY) -> do
t <- time -< ()
let x = centerX + cos t * radius
y = centerY + sin t * radius
radius = 30
returnA -< (x,y)
-- * SDL stuff
-- ** Input subsystem
-- | Input controller
data Controller = Controller
{ controllerPos :: (Double, Double)
}
-- | Give a controller, refresh its state and return the latest value.
-- We need a non-blocking controller-polling function.
sdlGetController :: IORef Controller -> IO Controller
sdlGetController controllerState = do
state <- readIORef controllerState
e <- pollEvent
case e of
MouseMotion x y _ _ -> do writeIORef
controllerState
(Controller (fromIntegral x, fromIntegral y))
sdlGetController controllerState
_ -> return state
-- * Graphics
-- | Initialise rendering system.
initGraphs :: IO ()
initGraphs = do
-- Initialise SDL
SDL.init [InitVideo]
-- Create window
screen <- SDL.setVideoMode width height 16 [SWSurface]
SDL.setCaption "Test" ""
-- | Display a box at a position.
display :: (Double, Double) -> IO()
display (playerX, playerY) = do
-- Obtain surface
screen <- getVideoSurface
-- Paint screen green
let format = surfaceGetPixelFormat screen
bgColor <- mapRGB format 55 60 64
fillRect screen Nothing bgColor
-- Paint small red square, at an angle 'angle' with respect to the center
foreC <- mapRGB format 212 108 73
let side = 10
x = round playerX
y = round playerY
fillRect screen (Just (Rect x y side side)) foreC
-- Double buffering
SDL.flip screen