-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplayer.elm
153 lines (133 loc) · 4.03 KB
/
player.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
module Player where
import Color exposing (..)
import Graphics.Collage exposing (..)
type alias Player =
{ name : String
, position : Position
, vel : Float
, angle : Float
, width : Float
, color : Color
, lastPositions : List Position
, state : PlayerState
, totalScore : Int
, roundScore : Int
}
type PlayerState = Alive | KilledBy Player | Waiting
type alias Vector2D = { x: Float, y: Float}
type alias Position = Vector2D
type alias Keys = { x: Int, y: Int}
distance : Position -> Position -> Float
distance p1 p2 = sqrt <| ((p2.x - p1.x) ^ 2) + ((p2.y - p1.y) ^2)
updatePlayer : Float -> List Player -> Keys -> Player -> Player
updatePlayer dt players keys player =
case player.state of
Alive ->
player
|> rotatePlayer dt keys
|> movePlayer dt
|> addPosition
|> handleCollision players
Waiting ->
player
|> rotatePlayer dt keys
|> movePlayer dt
_ -> player
rotatePlayer : Float -> Keys -> Player -> Player
rotatePlayer dt keys player =
{ player |
angle <- player.angle + dt * degrees ((toFloat keys.x) * player.vel)
}
movePlayer : Float -> Player -> Player
movePlayer dt player =
{ player |
position <- {
x = player.position.x + dt * (sin player.angle) * player.vel
,y = player.position.y + dt * (cos player.angle) * player.vel
}
}
addPosition : Player -> Player
addPosition player =
{ player |
lastPositions <- player.position :: player.lastPositions
}
handleCollision : List Player -> Player -> Player
handleCollision players player =
List.foldl collide player players
collide : Player -> Player -> Player
collide player2 player1 =
let
positions = if player1.name == player2.name then
List.drop 20 player1.lastPositions
else
player2.lastPositions
playerWidths = (player1.width + player2.width) / 2
distanceToPlayer1 = (\position -> (distance player1.position position) - playerWidths)
distancesToPlayer1 = List.map distanceToPlayer1 positions
treshold = 0.001
collision = List.any (\distance -> distance < treshold) distancesToPlayer1
in
{ player1 |
state <- if collision then KilledBy player2 else player1.state
}
readyPlayer : Player -> Player
readyPlayer player =
{ player |
state <- Alive
}
resetPlayer : Player -> Player
resetPlayer player =
{ player |
position <- { x = 100
, y = 100
}
, lastPositions <- []
, state <- Waiting
}
calculateScores : List Player -> List Player
calculateScores players =
List.map (calculateScore players) players
calculateScore : List Player -> Player -> Player
calculateScore players player =
{ player |
roundScore <- List.length <| List.filter (killedBy player) players
totalScore <- List.length <| List.filter (killedBy player) players
}
killedBy : Player -> Player -> Bool
killedBy player2 player1 =
case player1.state of
KilledBy p -> p.name == player2.name
_ -> False
initPlayer : Player
initPlayer =
{ name = "defaultPlayer"
, position = { x = 0
, y = 0
}
, vel = 4
, width = 10
, angle = 0
, color = Color.black
, lastPositions = []
, state = Waiting
, roundScore = 0
, totalScore = 0
}
drawPlayer : Player -> Form
drawPlayer player =
let
positionToTuple = (\position -> (position.x, position.y))
lineStyle = { defaultLine |
width <- player.width
, color <- player.color
, cap <- Round
}
in
if List.isEmpty player.lastPositions then
circle (player.width / 2)
|> filled player.color
|> move (positionToTuple player.position)
else
List.map positionToTuple player.lastPositions
|> path
|> traced lineStyle