-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathView.elm
129 lines (113 loc) · 4.5 KB
/
View.elm
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
120
121
122
123
124
125
126
127
128
129
module View exposing (..)
import Time exposing (Time)
import Svg exposing (..)
import Svg.Attributes exposing (..)
import Svg.Events exposing (..)
import Msg exposing (..)
import Model exposing (..)
import Types exposing (Block(..), Pos)
import Definitions exposing (..)
blockToUrl : Block -> String
blockToUrl block =
case block of
BFloor ->
"./img/ground.gif"
BWall ->
"./img/wall.gif"
BVoid ->
""
render : (Int, Int) -> String -> Svg Msg
render (x_, y_) image_path =
let
(x__, y__) = getScreenPos (x_, y_)
in
if image_path == "" then
svg [] []
else
image [ xlinkHref image_path, x <| toString x__, y <| toString y__
, width "32px", height "32px" ] []
tile : Tile -> Svg Msg
tile tile =
render tile.pos (blockToUrl tile.block)
hole : Pos -> Svg Msg
hole pos =
render pos "./img/hole.gif"
player : Bool -> Bool -> Pos -> Svg Msg
player frame holed pos =
let
crazy = if holed then "crazy_" else ""
url_path = "./img/player_" ++ crazy ++ (if frame then "1" else "2") ++ ".gif"
in
render pos url_path
box : Bool -> Pos -> Svg Msg
box correct pos =
render pos (if correct then "./img/box_hole.gif" else "./img/box.gif")
drawLevel : Bool -> Time -> Level -> Svg Msg
drawLevel draw_animation time_passed level =
svg [ width "500", height "500", viewBox "0 0 500 500" ]
<| [ text_ [ x "24", y "15", fill "black" ] [ text "Sokoban" ] ]
++ (List.map tile level.tiles)
++ (List.map hole level.holes)
++ (List.map (\bpos -> box (List.any ((==) bpos) level.holes) bpos) level.boxes)
++ [ player draw_animation (List.any ((==) level.player) level.holes) level.player
, text_ [ x "24", y "32", fill "black" ] [ text <| "Steps: " ++ toString level.steps ]
, text_ [ x "104", y "32", fill "black" ]
[ time_passed
|> flip (/) 10
|> round
|> toFloat
|> flip (/) 100
|> toString
|> (++) "Time: "
|> text
]
]
drawLevelIcon : Bool -> LevelInfo -> Svg Msg
drawLevelIcon selected levelInfo =
let
(x_, y_) = iconIdToPos levelInfo.id
(sX, sY) = (x_ * 70, y_ * 70)
color = if levelInfo.unlocked then "yellow" else "gray"
in
svg []
[ rect [ x <| toString <| sX + levelInfo.failStep, y <| toString sY, width "48px"
, height "48px", fill color, stroke "black" ] []
, text_ [ x <| toString <| sX + 16 + (if levelInfo.id < 10 then 4 else 0)
, y <| toString <| sY + 28, fill "black" ]
[ text <| toString <| levelInfo.id ]
, text_ [ x <| toString <| sX - 4, y <| toString <| sY + 64
, fill "black", fontSize "12"
, if levelInfo.beat && levelInfo.bestStep > 0 then
visibility "show"
else
visibility "hidden"
]
[ text <| "S " ++ (toString <| levelInfo.bestStep) ]
, text_ [ x <| toString <| sX + 24, y <| toString <| sY + 64
, fill "black", fontSize "12"
, if levelInfo.beat && levelInfo.bestTime > 0 then
visibility "show"
else
visibility "hidden"
]
[ text <| "T " ++ (toString <| levelInfo.bestTime)]
, rect [ x <| toString <| sX - 4, y <| toString <| sY - 4, width "56px"
, height "56px", stroke "blue", fill "none"
, visibility <| if selected then "show" else "hidden" ] []
]
drawMenu : Model -> Svg Msg
drawMenu model =
svg [ width "500", height "500" ] <|
[ text_ [ x "50", y "50", fill "black" ] [ text "Choose a level" ] ]
++ (List.map (\level -> drawLevelIcon (model.selected == level.id) level) model.levels)
view : Model -> Svg Msg
view model =
svg
[ width "500", height "500", fill "blue" ]
[ text_ [ x "24", y "15", fill "black" ]
[ text "Sokoban - WASD to walk, R to restart and M to go back to menu" ]
, if model.state == GSMenu then
drawMenu model
else
drawLevel model.player_animation (model.time - model.timeStart) model.current
]