Sound and saving the best score
You'll learn to play a short sound effect when the game ends, and to save the best score on the phone so it is still there tomorrow.
Watch & read
Start with the required ones. The others are there when you need them.
Explanation
You want two things when the game ends: a short click, so the player feels the hit, and a best score that
does not reset to 0 every time the app is closed.
The sound. expo-audio plays sound files. useAudioPlayer loads one when the screen appears, and
you play it when you need it:
const hitSound = useAudioPlayer({ uri: HIT_SOUND_URL });hitSound.seekTo(0); // back to the start, in case it played beforehitSound.play();
Use a short, plain sound effect: a click, a tap or a thud, less than a second long. Older tutorials use
expo-av. That package was removed from recent versions of Expo, so use expo-audio.
The best score. State is forgotten when the app closes. AsyncStorage is a small notebook on the
phone that remembers text under a name, called a key. You met it when saving data for your habit
tracker. Two things to remember:
- It only stores strings. Save with
String(best), and turn it back withNumber(saved). - The first time, nothing is saved yet, so
getItemgives backnull.
function newBest(savedText, score) {const best = savedText === null ? 0 : Number(savedText);return Math.max(best, score);}
When the game ends, read the saved best, compare it with score, and save the bigger one.
People often compare the saved text straight away. "12" is text, not a number, and null is not
0. So Math.max or > can give a strange answer, or the best score shows as empty. Turn it into a
number first.
getItem and setItem are asynchronous, like fetch: they give back a promise. Use .then or
await, and set state when the value arrives.
When you read storage code, look for the key ("best"), the turn into a string when saving, and the turn
back into a number when loading.
Code tour
Click a line number with a ring to read the note for that line.
Practice
Short drills. Take your time and read the code before you answer.
1// Last time you played, the app saved "15" under "best".2let best = 0;34AsyncStorage.getItem("best").then((saved) => {5 best = Number(saved);6});78console.log(best);
newBest(savedText, score) gets what AsyncStorage.getItem gave back (a string like "12", or null the first time) and this game's score. It should return the best score as a number. Right now the best score comes back as text, or as null. Fix it.1import { useEffect, useRef, useState } from "react";2import { Animated, Pressable, StyleSheet, Text, View } from "react-native";3import { useAudioPlayer } from "expo-audio";4import AsyncStorage from "@react-native-async-storage/async-storage";56const SPEED = 10, SCREEN_WIDTH = 400, PLAYER_X = 50, JUMP_HEIGHT = 150;
Runs in the browser. Choose “My Device” in Snack to try it on your phone with Expo Go.
"bestScore", in all three places. After a reload, best starts again at 0, because nothing is saved under the new key yet.Quick check
3 questions. Each one explains itself after you answer.
- 1 / 3The app opens for the very first time. What does
AsyncStorage.getItem("best")give back? - 2 / 3Why do we save the best score with
String(best)? - 3 / 3Why call
hitSound.seekTo(0)beforehitSound.play()?
Explain it back
How confident are you with Sound and saving the best score?
Done
AsyncStorage and say what it shows the first time the app opens.