Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[ ] When user keydown, play sound and style
[x] Confirm the key is being pressed
[x] Play audio
[ ] Apply style to pressed key

[x] Show game over or game won based on game state
[x] Display a H2
[x] Include in the h2, the message from the state
[x] create a state which contains a string, default will be empty
[x] pass the state to piano as prop
[x] once gameOver, change state value to 'Game over'
[x] if game won, change state value to 'game won'S
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
<title>Piano Key Press Count</title>
</head>
<body>
<div id="root"></div>
Expand Down
9 changes: 8 additions & 1 deletion src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ body {
height: 300px;
width: 60px;
border: 2px solid black;
display: flex;
justify-content: center;
align-items: center;
}

.key.flat {
Expand All @@ -33,6 +36,10 @@ body {
background-color: rgb(184, 184, 18)
}

.key.flat.selectedKey, .selectedKey {
.key.selectedKey {
background-color: grey;
}

.letter {
color: rgb(78, 113, 209);
}
24 changes: 19 additions & 5 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,39 @@
import "./App.css"
import Piano from "./components/Piano.jsx"
import { useState } from "react"
import { useEffect, useState } from "react"
import { playSequence } from "./components/helpers"

function App() {
const App = () => {
const [gameStarted, setGameStarted] = useState(false)
const [score, setScore] = useState(0)
const [resultMessage, setResultMessage] = useState("")

function toggleGame() {
const toggleGame = () => {
setGameStarted((prevState) => !prevState)
setScore(0)
}

useEffect(() => {
if (gameStarted) playSequence()
}, [gameStarted])

return (
<div>
{gameStarted && <h1>Keys Pressed {score} Times</h1>}
{gameStarted && <h1>Player score: {score}</h1>}
{gameStarted && <h2>{resultMessage}</h2>}
<button onClick={toggleGame}>
{gameStarted ? "Stop" : "Start"} Game
</button>
<Piano setScore={setScore} />

<Piano
gameStarted={gameStarted}
setScore={setScore}
setResultMessage={setResultMessage}
/>
</div>
)
}



export default App
20 changes: 12 additions & 8 deletions src/components/Key.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
const Key = ({ note, selectedNote }) => {
const keyClassName = note.length >= 3 ? "key flat" : "key"
const selectedClassName = note === selectedNote ? "selectedKey" : ""

return <div className={`${keyClassName} ${selectedClassName}`}></div>
}

export default Key
const Key = ({ note, selectedNote, letter }) => {
const keyClassName = note.length >= 3 ? "key flat" : "key"
const selectedClassName = note === selectedNote ? "selectedKey" : ""

return (
<div className={`${keyClassName} ${selectedClassName}`} data-note={note}>
<span className="letter">{letter}</span>
</div>
)
}

export default Key
77 changes: 43 additions & 34 deletions src/components/Piano.jsx
Original file line number Diff line number Diff line change
@@ -1,56 +1,65 @@
import Key from "./Key"
import { useEffect, useState } from "react"
import { NOTES, keyMap, songs } from "./constants"
import {
isUserSequenceCorrect,
playAudio,
validateUserInput,
styleKey
} from "./helpers"

const Piano = ({ setScore }) => {
const Piano = ({ gameStarted, setScore, setResultMessage }) => {
const [selectedNote, setSelectedNote] = useState("")
const [userInputArr, setUserInputArr] = useState([])
const [sequenceCount, setSequenceCount] = useState(0)

function handleKeyDown(event) {
const userInput = event.key.toLowerCase()
for (let key in keyMap) {
if (userInput === key) {
setSelectedNote(keyMap[userInput])
setScore((currentScore) => currentScore + 1)
}
}
const userNote = keyMap[userInput]
if (!userNote) return
styleKey(userNote)
playAudio(userNote)

if (!gameStarted) return
validateUserInput({
setScore,
sequenceCount,
userNote,
setUserInputArr,
setSequenceCount,
setResultMessage
})
}

useEffect(() => {
window.addEventListener("keydown", handleKeyDown)
return () => {
window.removeEventListener("keydown", handleKeyDown)
}
}, [])

useEffect(playAudio, [selectedNote])

function playAudio() {
if (!selectedNote) return
}, [gameStarted, sequenceCount])

const noteAudio = new Audio()
noteAudio.src = `assets/Notes/${selectedNote}.mp3`
noteAudio.play()
}

function playSequence() {
let time = 0
for (let i = 0; i <= 1; i++) {
setTimeout(
() =>
window.dispatchEvent(
new KeyboardEvent("keydown", { key: songs[0][i] })
),
time
)
time += 1500
}
}
useEffect(() => playAudio(selectedNote), [selectedNote])
useEffect(() => isUserSequenceCorrect(userInputArr, setResultMessage))

return (
<div className="piano" onClick={playSequence}>
<div className="piano">
<audio src={`assets/Notes/${selectedNote}.mp3`}></audio>
{/* {NOTES.map((note, index) => (
<Key
key={`key-${index}`}
note={note}
selectedNote={selectedNote}
keyMap={keyMap}
/>
))} */}
{/* <audio src={`assets/Notes/${selectedNote}.mp3`}></audio> */}
{NOTES.map((note, index) => (
<Key key={`key-${index}`} note={note} selectedNote={selectedNote} />
{Object.keys(keyMap).map((note, index) => (
<Key
key={`key-${index}`}
note={keyMap[note]}
selectedNote={selectedNote}
letter={note}
/>
))}
</div>
)
Expand Down
146 changes: 129 additions & 17 deletions src/components/constants.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,134 @@
const NOTES = ['C4', 'Db4', 'D4', 'Eb4', 'E4', 'F4', 'Gb4', 'G4', 'Ab4', 'A4', 'Bb4', 'B4',];
// const secondOctave = [ 'C5', 'Db5', 'D5', 'Eb5', 'E5', 'F5', 'Gb5', 'G5', 'Ab5', 'A5', 'Bb5', 'B5' ]
const songs = [
['z', 'x', 'c']
const NOTES = [
"C4",
"Db4",
"D4",
"Eb4",
"E4",
"F4",
"Gb4",
"G4",
"Ab4",
"A4",
"Bb4",
"B4"
]
// const secondOctave = [ 'C5', 'Db5', 'D5', 'Eb5', 'E5', 'F5', 'Gb5', 'G5', 'Ab5', 'A5', 'Bb5', 'B5' ]
// const songs = ["C4", "Db4", "D4"]

// ----------------------
const songs = ["G4", "A4", "G4", "C4", "B4"] // Happy birthday Right

// keys = b, n, b, z, m, b, n, b, x, z, b, c, z, m, n, v, c, z, x - Happy birthday cheatkey

const songs3 = ["C4", "G4", "C4", "F4", "C4", "G4", "C4"] // Happy Birthday Left

const songs4 = [
"C4",
"G4",
"F4",
"E4",
"D4",
"C4",
"G4",
"F4",
"E4",
"D4",
"C4",
"G4",
"F4",
"E4",
"F4",
"D4",
"C4",
"G4",
"F4",
"E4",
"D4",
"C4",
"G4",
"F4",
"E4",
"F4",
"E4",
"D4",
"C4",
"D4",
"E4",
"D4",
"F4",
"E4",
"D4",
"C4",
"G4",
"D4",
"F4",
"E4",
"D4",
"C4",
"C4",
"C4",
"D4",
"E4",
"D4",
"E4",
"D4",
"C4",
"A4",
"G4",
"G4",
"F4",
"D4",
"C4",
"G4",
"F4",
"E4",
"D4",
"C4",
"G4",
"F4",
"E4",
"D4",
"C4",
"G4",
"E4",
"D4",
"C4",
"G4",
"F4",
"E4",
"D4",
"C4",
"G4",
"F4",
"E4",
"D4",
"C4",
"G4",
"F4",
"E4",
"F4",
"D4",
"C4",
"C4",
"C4"
] // Star Wars Right

const songs5 = ["G4", "A4", "B4", "G4", "A4", "B4", "G4", "A4", "C4", "G4"] // Star Wars Left
// ----------------------

const keyMap = {
z: 'C4',
s: 'Db4',
x: 'D4',
d: 'Eb4',
c: 'E4',
v: 'F4',
g: 'Gb4',
b: 'G4',
h: 'Ab4',
n: 'A4',
j: 'Bb4',
m: 'B4',
z: "C4",
s: "Db4",
x: "D4",
d: "Eb4",
c: "E4",
v: "F4",
g: "Gb4",
b: "G4",
h: "Ab4",
n: "A4",
j: "Bb4",
m: "B4"
}

export {NOTES, keyMap, songs}
export { NOTES, keyMap, songs }
Loading