-
Notifications
You must be signed in to change notification settings - Fork 1
/
level.fnl
217 lines (185 loc) · 8.36 KB
/
level.fnl
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
(local hud (require "hud"))
(local ship (require "ship"))
(local planet (require "planet"))
(local vortex (require "vortex"))
(local lume (require "lume"))
(local util (require "util"))
(var tracking-info nil)
(var bg-music nil)
(var victory-music nil)
(var level-switcher nil)
(var level-replay nil)
(defn find-mouse-intersect-planet [planets]
(let [x (love.mouse.getX)
y (love.mouse.getY)]
(lume.first
(lume.filter planets
(fn [p]
(let [[x1 y1 x2 y2] (planet.bounds p)]
(when (and (<= x1 x x2)
(<= y1 y y2))
p)))))))
(defn launch-level [level]
(set level.state :in-flight))
(defn reset-level [level]
(set level.state :awaiting-launch)
(set level.duration 0)
(set level.ship (ship.create level.level-info.ship.vx
level.level-info.ship.vy))
(set level.resource-score 0)
(set level.survival-score-offered 0)
(each [k p (ipairs level.planets)]
(planet.reset p)))
(defn trigger-game-over [level]
;; when game is over due to crash, first the game state goes to
;; :crash, we need to tell the ship that it needs to animate to crash
(set level.state :crashed)
(ship.trigger-crash level.ship))
(defn finish-level [level]
(ship.fall-into-vortex level.ship
[level.level-info.vortex.x
level.level-info.vortex.y])
(set level.state :complete))
{:load (fn [switcher replay]
(planet.load)
(ship.load)
(hud.load)
(set level-switcher switcher)
(set level-replay replay)
(set bg-music (love.audio.newSource "assets/alone.mp3"))
(: bg-music :setLooping true)
(set victory-music (love.audio.newSource "assets/victory.mp3"))
(: victory-music :setVolume 0.3))
:create (fn [level-info]
(let [planets []]
(each [k p (ipairs level-info.planets)]
(table.insert planets
(planet.create p.size
p.distance
p.resources
p.tile)))
(util.pp planets)
{:ship (ship.create level-info.ship.vx level-info.ship.vy)
:duration 0
:level-info level-info
:state :awaiting-launch
:speed-up 1
:resource-score 0
:survival-score-offered 0
:planets planets
:vortex (vortex.create level-info.vortex.x
level-info.vortex.y
level-info.vortex.radius)}))
:keypressed (fn [level key unicode]
(if
(= key "s")
(let [new-s (+ level.speed-up 1)]
(set level.speed-up
(if (> new-s 4) 1 new-s)))
(and (= key "space")
(= level.state :awaiting-launch))
(launch-level level)
(and (= key "space")
(= level.state :in-flight))
(reset-level level)
(and (= key "space")
(= level.state :in-flight))
(reset-level level)
(and (= key "space")
(= level.state :crashed))
(reset-level level)
(and (= key "space")
(= level.state :complete))
(level-switcher)
(and (= key "r")
(= level.state :complete))
(level-replay)))
:update (fn [level tt]
;; play music if we are not paying
(when (and (not (: bg-music :isPlaying))
(= level.state :awaiting-launch))
(: victory-music :stop)
(: bg-music :play))
;; stop music when complete
(when (and (: bg-music :isPlaying)
(= level.state :complete))
(: victory-music :play)
(: bg-music :stop))
(let [t (* tt level.speed-up)]
;; when we're inflight update the duration
(when (= level.state :in-flight)
;; survival score
(set level.survival-score-offered
(math.min
10000
(+ level.survival-score-offered (math.floor (* tt 1000)))))
(set level.duration (+ level.duration tt))
;; apply any forces due to gravity on the ship
(ship.apply-planetary-forces level.ship level.planets)
(ship.update-forces level.ship t))
;; when we're awaiting launch, allow players to adjust orbital positions
(when (= level.state :awaiting-launch)
;; if mouse is down on one of our planets then we need to track the mouse
;; movement to allow the planet to move
;;
(if (love.mouse.isDown 1)
(when (not tracking-info)
(let [p (find-mouse-intersect-planet level.planets)]
(when p
(print "found planet:" p)
(love.mouse.setGrabbed true)
(planet.mark-highlight p)
(set tracking-info {:planet p
:x (love.mouse.getX)
:y (love.mouse.getY)}))))
(when tracking-info
(love.mouse.setGrabbed false)
(planet.unmark-highlight tracking-info.planet)
(set tracking-info nil)))
;; when the mouse is being tracked, we need to know how much the mouse is moving
;; so we can pass that info down to our planets
(when tracking-info
(let [mx (love.mouse.getX)
my (love.mouse.getY)
dx (- tracking-info.x mx)
dy (- tracking-info.y my)]
(planet.adjust-position tracking-info.planet dx dy)
(tset tracking-info :x mx)
(tset tracking-info :y my))))
;; update each planet and the ship
(each [k p (ipairs level.planets)]
(planet.update p t))
(ship.update level.ship t)
(vortex.update level.vortex t))
;; check for collisions
;; did we reach the end by hitting the vortex
(let [vortex-bounds (vortex.center-and-radius level.vortex)
ship-bounds (ship.center-and-radius level.ship)]
(when (and (util.sphere-collision vortex-bounds ship-bounds)
(= level.state :in-flight))
;; we reached the vortex
(finish-level level)))
;; check the ship bounds against bounds of each planet, each planet may report that some
;; of the resources where collided against or a full collision happened
(let [ship-center-and-radius (ship.center-and-radius level.ship)
coll-status (lume.map level.planets
(fn [p]
(planet.collide p ship-center-and-radius)))
full-collide? (lume.first (lume.filter coll-status
(fn [s] (= s "full-collide"))))
resource-collides (# (lume.filter coll-status
(fn [s] (= s "resource-collide"))))]
;; if there's a resource collision add score
(set level.resource-score
(+ level.resource-score (* 50000 resource-collides)))
(when (and (= level.state :in-flight)
full-collide?)
(trigger-game-over level))))
:reset (fn [level]
(reset-level level))
:draw (fn [level]
(each [k p (ipairs level.planets)]
(planet.draw p))
(ship.draw level.ship)
(vortex.draw level.vortex)
(hud.draw level))}