Skip to content

Commit 310ad11

Browse files
committed
Adding sound to the game
1 parent 6b46e7a commit 310ad11

1 file changed

Lines changed: 79 additions & 3 deletions

File tree

src/scittle/games/asteroids.cljs

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,70 @@
1515
;; Game Constants
1616
;; ============================================================================
1717

18+
;; ============================================================================
19+
;; Audio System (Web Audio API)
20+
;; ============================================================================
21+
22+
(def audio-context
23+
"Web Audio API context for sound generation"
24+
(when (exists? js/AudioContext)
25+
(js/AudioContext.)))
26+
27+
(defn play-tone
28+
"Plays a tone at the specified frequency for the given duration"
29+
[& {:keys [frequency duration volume]
30+
:or {frequency 440 duration 0.2 volume 0.3}}]
31+
(when audio-context
32+
(try
33+
(let [oscillator (.createOscillator audio-context)
34+
gain-node (.createGain audio-context)]
35+
(.connect oscillator gain-node)
36+
(.connect gain-node (.-destination audio-context))
37+
(set! (.-value (.-frequency oscillator)) frequency)
38+
(set! (.-value (.-gain gain-node)) volume)
39+
(.start oscillator)
40+
(.stop oscillator (+ (.-currentTime audio-context) duration)))
41+
(catch js/Error e
42+
(js/console.error "Audio error:" e)))))
43+
44+
(defn play-laser-sound
45+
"Plays a laser shooting sound"
46+
[]
47+
(play-tone :frequency 800 :duration 0.1 :volume 0.2))
48+
49+
(defn play-explosion-sound
50+
"Plays an explosion sound for asteroids and UFOs"
51+
[]
52+
(play-tone :frequency 100 :duration 0.2 :volume 0.3))
53+
54+
(defn play-thrust-sound
55+
"Plays a ship thrust/engine sound"
56+
[]
57+
(play-tone :frequency 150 :duration 0.08 :volume 0.15))
58+
59+
(defn play-hyperspace-sound
60+
"Plays a hyperspace jump sound with descending frequencies"
61+
[]
62+
;; Descending frequencies for warp effect
63+
(doseq [[idx freq] (map-indexed vector [880 660 440 220])]
64+
(js/setTimeout
65+
#(play-tone :frequency freq :duration 0.1 :volume 0.25)
66+
(* idx 50))))
67+
68+
(defn play-hit-sound
69+
"Plays a sound when the ship is hit"
70+
[]
71+
(play-tone :frequency 150 :duration 0.3 :volume 0.4))
72+
73+
(defn play-level-complete-sound
74+
"Plays a victory sound for completing a level"
75+
[]
76+
;; Ascending notes for victory
77+
(doseq [[idx freq] (map-indexed vector [523 659 784 1047])]
78+
(js/setTimeout
79+
#(play-tone :frequency freq :duration 0.2 :volume 0.25)
80+
(* idx 100))))
81+
1882
(def canvas-width 800)
1983
(def canvas-height 600)
2084
(def ship-size 10)
@@ -215,6 +279,7 @@
215279
(defn fire-bullet!
216280
"Fires a bullet from the ship"
217281
[]
282+
(play-laser-sound) ; Play laser sound
218283
(let [{:keys [x y angle]} (:ship @game-state)
219284
bullet-vx (* bullet-speed (Math/cos (- angle (/ Math/PI 2))))
220285
bullet-vy (* bullet-speed (Math/sin (- angle (/ Math/PI 2))))]
@@ -250,6 +315,7 @@
250315
"Hyperspace jump with risk"
251316
[]
252317
(when (<= (:hyperspace-cooldown @game-state) 0)
318+
(play-hyperspace-sound) ; Play hyperspace sound
253319
(let [new-x (rand-int canvas-width)
254320
new-y (rand-int canvas-height)
255321
died? (< (rand) 0.1)]
@@ -309,7 +375,7 @@
309375
(swap! game-state update :ufos conj (create-ufo))
310376
(swap! game-state assoc :ufo-timer (+ 900 (rand-int 900))))
311377

312-
;; Update ship
378+
;; Update ship
313379
(swap! game-state update :ship
314380
(fn [s]
315381
(let [new-vx (if (:thrusting s)
@@ -328,6 +394,11 @@
328394
(update :y #(wrap-position :value (+ % new-vy) :max-val canvas-height))
329395
(update :invulnerable #(max 0 (dec %)))))))
330396

397+
;; Play thrust sound (throttled to every 8 frames)
398+
(when (and (:thrusting ship)
399+
(= (mod (:frame-count @game-state) 8) 0))
400+
(play-thrust-sound))
401+
331402
;; Update bullets
332403
(swap! game-state update :bullets
333404
(fn [bs]
@@ -398,8 +469,9 @@
398469
:count 5
399470
:color "#FFFFFF"))))
400471

401-
;; Apply all collision effects at once
472+
;; Apply all collision effects at once
402473
(when (seq @hit-bullets)
474+
(play-explosion-sound) ; Play explosion sound for asteroid destruction
403475
(swap! game-state update :bullets #(vec (remove (fn [b] (contains? @hit-bullets b)) %)))
404476
(swap! game-state update :asteroids #(vec (remove (fn [a] (contains? @hit-asteroids a)) %)))
405477
;; Only add new asteroids if we're under the limit
@@ -435,6 +507,7 @@
435507
:color "#FF00FF"))))
436508

437509
(when (seq @hit-bullets)
510+
(play-explosion-sound) ; Play explosion sound for UFO destruction
438511
(swap! game-state update :bullets #(vec (remove (fn [b] (contains? @hit-bullets b)) %)))
439512
(swap! game-state update :ufos #(vec (remove (fn [u] (contains? @hit-ufos u)) %)))
440513
(swap! game-state update :score + @score-added)
@@ -445,6 +518,7 @@
445518
(doseq [asteroid asteroids]
446519
(when (check-collision :obj1 ship :obj2 asteroid
447520
:radius1 ship-size :radius2 (:size asteroid))
521+
(play-hit-sound) ; Play hit sound when ship is hit
448522
(swap! game-state update :lives dec)
449523
(swap! game-state update :particles
450524
#(vec (concat % (create-particles :x (:x ship)
@@ -462,6 +536,7 @@
462536
:when (:from-ufo bullet)]
463537
(when (check-collision :obj1 ship :obj2 bullet
464538
:radius1 ship-size :radius2 3)
539+
(play-hit-sound) ; Play hit sound when ship is hit by UFO bullet
465540
(swap! game-state update :bullets #(vec (remove (fn [b] (= b bullet)) %)))
466541
(swap! game-state update :lives dec)
467542
(swap! game-state update :particles
@@ -474,8 +549,9 @@
474549
(swap! game-state assoc :game-status :game-over)
475550
(swap! game-state update :high-score max (:score @game-state))))))
476551

477-
;; Check level complete
552+
;; Check level complete
478553
(when (empty? asteroids)
554+
(play-level-complete-sound) ; Play victory sound
479555
(swap! game-state update :level inc)
480556
(init-level! :level (:level @game-state))))))
481557

0 commit comments

Comments
 (0)