-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.hs
119 lines (106 loc) · 3.19 KB
/
main.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
110
111
112
113
114
115
116
117
118
119
import Data.Functor
import Data.Maybe (catMaybes)
import Data.Set
import System.IO (hFlush, stdout)
import Graphics.UI.SDL as SDL
import Graphics.UI.SDL.Mixer as MIX
import qualified Resources as R
data GameConfig = GameConfig
{ windowWidth :: Int
, windowHeight :: Int
}
defaultConfig = GameConfig 400 600
data Game = GameStruct
{ gameWindow :: Surface
, keyState :: Set SDLKey
, player :: (Int, Int)
, images :: R.Images
, frames :: Int
, bgm :: Music
}
initGame (GameConfig w h) = do
SDL.init [InitEverything]
MIX.openAudio 44100 AudioS16Sys 2 1024
music <- R.playBGM
window <- setVideoMode w h 16 [HWSurface, DoubleBuf]
img <- R.loadImages
return $ GameStruct
{ gameWindow = window
, keyState = empty
, player = (200, 500)
, images = img
, frames = 0
, bgm = music
}
quitGame (GameStruct { gameWindow = w
, images = imgs
, bgm = music
}) = do
freeSurface w
R.freeImages imgs
R.stopBGM music
MIX.closeAudio
quit
updateGame g0@(GameStruct {keyState = key}) = do
g1 <- stepGame <$> getEvents g0
render g1
if isQuit then return ()
else updateGame g1
where
isQuit = member SDLK_q key
getEvents g0@(GameStruct {keyState = sk}) = do
e <- pollEvent
case e of
KeyDown (Keysym key _ _) -> getEvents $ g0 {keyState = insert key sk}
KeyUp (Keysym key _ _) -> getEvents $ g0 {keyState = delete key sk}
NoEvent -> return g0
_ -> getEvents g0
stepGame g0@(GameStruct {keyState = keys}) = f g0
where
keyList :: [SDLKey]
keyList = toList keys
f :: Game -> Game
f = foldr1 (.) $
defaultStep :
( catMaybes
. (Prelude.map keyToAction)
) keyList
defaultStep g@(GameStruct {frames = f}) = g {frames = f+1}
keyToAction :: SDLKey -> Maybe (Game -> Game)
keyToAction key = case key of
SDLK_DOWN -> Just $ movePlayer 0 6
SDLK_UP -> Just $ movePlayer 0 (-6)
SDLK_RIGHT -> Just $ movePlayer 6 0
SDLK_LEFT -> Just $ movePlayer (-6) 0
_ -> Nothing
where
movePlayer :: Int -> Int -> Game -> Game
movePlayer x y g0@(GameStruct { player = (x0,y0)})
= g0 { player = (x0+x, y0+y) }
render
g0@(GameStruct { gameWindow = w
, player = (px, py)
, images = R.Images { R.backGround = bg
, R.player = p
}
, frames = f
})
= do bgRendering
red <- mapRGB windowPixelFormat maxBound 0 0
True <- blitSurface p Nothing w (Just $ Rect (px-16) (py-16) 0 0)
True <- fillRect w (Just $ Rect (px-1) (py-1) 3 3) red
-- delay 1000
SDL.flip w
return g0
where
bgRendering = do
let positionY = 2 * f `mod` 300
True <- blitSurface bg Nothing w (Just $ Rect 0 (positionY-300) 0 0)
True <- blitSurface bg Nothing w (Just $ Rect 0 positionY 0 0)
True <- blitSurface bg Nothing w (Just $ Rect 0 (positionY+300) 0 0)
return ()
windowPixelFormat = surfaceGetPixelFormat w
main = do
game <- initGame defaultConfig
updateGame game
quitGame game