summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Chausse <benjamin@chausse.xyz>2023-02-14 16:34:40 -0500
committerBenjamin Chausse <benjamin@chausse.xyz>2023-02-14 16:34:40 -0500
commit6983e53daae8cab25ff113c7b5ccd3b31f39fcbb (patch)
tree5832db5c367b99ced3eb25591e325961630c7404
parent8edabf33e46e1d2e5f69bbf856cf7f3595a4efa6 (diff)
Basic Song and chord structure
-rw-r--r--chord.cpp52
-rw-r--r--chord.h45
-rw-r--r--song.cpp54
-rw-r--r--song.h32
4 files changed, 183 insertions, 0 deletions
diff --git a/chord.cpp b/chord.cpp
new file mode 100644
index 0000000..8c6be33
--- /dev/null
+++ b/chord.cpp
@@ -0,0 +1,52 @@
+#include "chord.h"
+
+Chord::Chord(int btn, int startTime, int endTime) {
+ start = startTime;
+ end = endTime;
+ for (int i=0; i<5; i++) {
+ notes[i] = false;
+ }
+ notes[btn] = true;
+};
+
+Chord::~Chord() {};
+
+void Chord::change(int button) {
+ notes[button] = !notes[button];
+};
+
+void Chord::setEnd(int endTime) {
+ end = endTime;
+};
+
+void Chord::setRenderStart(int renderTime) {
+ renderStart = start - renderTime;
+};
+
+bool* Chord::getNotes() {
+ return notes;
+};
+
+int Chord::getStart() {
+ return start;
+};
+
+int Chord::getEnd() {
+ return end;
+};
+
+int Chord::getRenderStart() {
+ return renderStart;
+};
+
+std::regex Chord::getRegex() {
+ // empty string
+ std::string regex = "";
+ // true becomes "t" and false becomes "f"
+ // this is used to create a string of 5 characters
+ // which can be used as a regex
+ for (int i=0; i<5; i++) {
+ regex += notes[i] ? "t" : "f";
+ }
+ return std::regex(regex);
+};
diff --git a/chord.h b/chord.h
new file mode 100644
index 0000000..83bbfaf
--- /dev/null
+++ b/chord.h
@@ -0,0 +1,45 @@
+#ifndef __CHORD_H__
+#define __CHORD_H__
+
+#include <regex>
+
+// Chords are used to represent a set of notes that are played together.
+// For this guitar hero implementation, a single note is technically a chord.
+// This analogy is used to make sure that simultaneous notes are always grouped
+// under a single chord since they have information in common (start/end time).
+
+#define BUTTON1 0 // green
+#define BUTTON2 1 // red
+#define BUTTON3 2 // yellow
+#define BUTTON4 3 // blue
+#define BUTTON5 4 // orange
+
+
+class Chord {
+ private:
+ bool notes[5]; // which buttons are pressed
+ int start; // when to play in ms (relative to song start)
+ int end; // when to stop playing in ms (relative to song start)
+ int renderStart; // when to render (no need to define on construction)
+ public:
+ // Chords are initialized with a single button.
+ // Other notes are added as notes with the same "start" are encountered
+ // in .chart files.
+ // End time is initialized to 0 but can be changed if the .chart indicates
+ // that the chord is held for longer than the default 1/16th note.
+ Chord(int btn, int startTime, int endTime);
+ ~Chord();
+ void change(int button); // change note in existing chord
+ void setEnd(int endTime); // set the end time of the chord
+ void setRenderStart(int renderTime); // sets when to start rendering
+ bool* getNotes(); // get the notes in the chord
+ int getStart(); // get the start time of the chord
+ int getEnd(); // get the end time of the chord
+ int getRenderStart(); // get the render time of the chord
+ std::regex getRegex(); // regex for this chord
+ // compares the player's input to
+ // the expected chord
+};
+
+#include "chord.cpp"
+#endif // __CHORD_H__
diff --git a/song.cpp b/song.cpp
new file mode 100644
index 0000000..0f34782
--- /dev/null
+++ b/song.cpp
@@ -0,0 +1,54 @@
+#include "song.h"
+
+Song::Song(std::string chartFile) {
+ // TODO: import and parse chartFile
+}
+
+Song::~Song() {};
+
+void Song::consolidate() {
+ int totalSize = chords.size();
+ // Check each chord against every other chord
+ for (int i=0; i<totalSize; i++) {
+ // Get the start and end times of the current chord
+ int start = chords[i].getStart();
+ int end = chords[i].getEnd();
+ // Check the current chord against every following chord
+ for (int j=i+1; j<totalSize; j++) {
+ // If the start and end times match:
+ if (chords[j].getStart() == start && chords[j].getEnd() == end) {
+ // Append those notes to the first encountered chord (i)
+ for (int k=0; k<5; k++) {
+ // If this note is set in the second chord, change it in the first
+ if (chords[j].getNotes()[k]) {
+ chords[i].change(k);
+ }
+ }
+ // Remove the second chord from the vector
+ chords.erase(chords.begin()+j);
+ // Decrement the total size of the vector
+ totalSize--;
+ }
+ }
+ }
+}
+
+std::string Song::getTitle() {
+ return title;
+}
+
+std::string Song::getArtist() {
+ return artist;
+}
+
+int Song::getDuration() {
+ return duration;
+}
+
+std::string Song::getAudioFile() {
+ return audioFile;
+}
+
+std::vector<Chord> Song::getChords() {
+ return chords;
+}
diff --git a/song.h b/song.h
new file mode 100644
index 0000000..e4b2389
--- /dev/null
+++ b/song.h
@@ -0,0 +1,32 @@
+#ifndef __SONG_H__
+#define __SONG_H__
+
+#include "chord.h"
+#include <vector>
+
+// Contains a song for a guitar hero clone
+class Song {
+ private:
+ std::string title;
+ std::string artist;
+ int duration; // in ms
+ std::string audioFile; // path to audio file
+ std::vector<Chord> chords;
+ public:
+ Song(std::string chartFile);
+ ~Song();
+ void consolidate(); // merges chords with the same start/end times
+ // into a single chord
+ Chord operator[](int index);
+ int size();
+
+ std::string getTitle();
+ std::string getArtist();
+ int getDuration();
+ std::string getAudioFile();
+ std::vector<Chord> getChords();
+};
+
+#include "song.cpp"
+#endif // __SONG_H__
+