This repository has been archived by the owner on Jan 30, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Test.lhs
118 lines (97 loc) · 3.66 KB
/
Test.lhs
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
First, some qualified imports
> import qualified Data.Maybe as DM
> import qualified Data.Map as DMap
> import qualified System.Random as R
> import qualified Control.Monad as CM
> import qualified Graphics.UI.SDL as SDL
> import qualified Graphics.UI.SDL.Image as SDLi
These are the assets for the terrain
> artFilePaths = [ "art/64x74_blue.png",
> "art/64x74_green.png",
> "art/64x74_white.png",
> "art/64x74_brown.png" ]
Data types for the definition of the terrain
> data TerrainType = TTh_Blue | TTh_Green | TTh_White | TTh_Brown
> deriving (Bounded, Eq, Enum, Ord, Show)
>
> type Point = (Int, Int)
> type TerrainSurfaces = [(TerrainType, SDL.Surface)]
> type TerrainMap = DMap.Map Point TerrainType
All the terrain types
> terrainTypes :: [TerrainType]
> terrainTypes = [minBound..maxBound]
Terrain types can be random too...
> instance R.Random TerrainType where
> randomR (a,b) = (onFst toEnum) . (R.randomR (fromEnum a, fromEnum b))
> where onFst f (a,b) = (f a,b)
> random = R.randomR (minBound, maxBound)
Create a 2D random map
> makeRandomMap :: Int -> Int -> IO TerrainMap
> makeRandomMap w h = do
> tiles <- CM.replicateM (w*h) R.randomIO
> return $ DMap.fromAscList (zip [(x,y) | x <- [1..w], y <- [1..h]] tiles)
Load the assets
> loadArt :: [String] -> IO TerrainSurfaces
> loadArt paths = do
> tileSurfs <- mapM SDLi.load paths
> return $ zip terrainTypes tileSurfs
Blit the surface of the terrain tile to another surface (e.g. the main screen)
> drawTile :: SDL.Surface -> TerrainSurfaces -> TerrainMap -> Point -> IO ()
> drawTile mainSurf terrainSurfs tm (x,y) = do
> let sr = Just (SDL.Rect 0 0 64 74)
> let dr = Just $ getHexmapOffset 64 74 x y
> let tt = DM.fromJust $ DMap.lookup (x,y) tm
> let terrainSurf = DM.fromJust $ lookup tt terrainSurfs
> SDL.blitSurface terrainSurf sr mainSurf dr
> return ()
Ooops... missing function here: calculate the rectangle of a tile given its
map coordinates
> getHexmapOffset :: Int -> Int -> Int -> Int -> SDL.Rect
> getHexmapOffset tileW tileH x y =
> SDL.Rect adjX adjY 0 0
> where
> baseAdjX = (tileW * (x-1))
> baseAdjY = (tileH * (y-1))
> quarterH = tileH `div` 4
> halfW = tileW `div` 2
> adjX = if odd y
> then baseAdjX + halfW
> else baseAdjX
> adjY = baseAdjY - ((y-1) * quarterH)
===============================================================================
The main thingy
> main :: IO ()
> main = do
> SDL.init [SDL.InitEverything]
> SDL.setVideoMode 640 480 32 []
> SDL.setCaption "Video Test!" "video test"
>
> mainSurf <- SDL.getVideoSurface
> tileSurfs <- loadArt artFilePaths
>
> randomMap <- makeRandomMap 9 8
>
> mapM_ (drawTile mainSurf tileSurfs randomMap) $ DMap.keys randomMap
> SDL.flip mainSurf
>
> eventLoop
> mapM_ freeSurf tileSurfs
> SDL.quit
> print "done"
> where
> freeSurf (_, s) = SDL.freeSurface s
> eventLoop = SDL.waitEventBlocking >>= checkEvent
> checkEvent (SDL.KeyUp _) = return ()
> checkEvent (SDL.MouseMotion x y xr yr) =
> putStrLn ("MouseMotion X:" ++ show x ++ " Y:" ++ show y ++
> " RX:" ++ show xr ++ " RY:" ++ show yr)
> >> eventLoop
> checkEvent (SDL.MouseButtonDown x y b) =
> putStrLn ("MouseBDown X:" ++ show x ++ " Y:" ++ show y ++
> " B:" ++ show b)
> >> eventLoop
> checkEvent (SDL.MouseButtonUp x y b) =
> putStrLn ("MouseBUp X:" ++ show x ++ " Y:" ++ show y ++
> " B:" ++ show b)
> >> eventLoop
> checkEvent _ = eventLoop