summaryrefslogtreecommitdiff
path: root/vfg/src/music.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vfg/src/music.cpp')
-rwxr-xr-xvfg/src/music.cpp148
1 files changed, 74 insertions, 74 deletions
diff --git a/vfg/src/music.cpp b/vfg/src/music.cpp
index 096e630..29b1ef6 100755
--- a/vfg/src/music.cpp
+++ b/vfg/src/music.cpp
@@ -2,18 +2,11 @@
//event times & durations are absolute integer milliseconds
//---------------------------------------------------------------------------------------------------------------------------------------------
-note::note(int n,int v,int d){
- num=n;
- velocity=v;
- duration=d;
- activated=false;
-}
-//---------------------------------------------------------------------------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------------------------------------------------------
musicscore::musicscore() {
timeframe=2000;
flake.loadImage("flake.png");
flake.setAnchorPercent(0.5,0.5);
+ missedLast=false;
}
void musicscore::parseMidi(string filename){
// millis = 60000 / (BPM * PPQ)
@@ -86,10 +79,9 @@ void musicscore::parseMidi(string filename){
while (++iter2 != events.end()) {
if ((iter1->second->num==iter2->second->num)&&(iter2->second->duration==128)) {
iter1->second->duration=iter2->first-iter1->first;
- iter1->second->updown=iter1->second->num<n?-1:iter1->second->num==n?0:1;
n=iter1->second->num;
notes[iter1->first]=iter1->second;
- printf("%i: noteon %i %i %i\n",iter1->first,iter1->second->num,iter1->second->duration,iter1->second->updown);
+ //printf("%i: noteon %i %i\n",iter1->first,iter1->second->num,iter1->second->duration);
break;
}
}
@@ -98,97 +90,96 @@ void musicscore::parseMidi(string filename){
iter1 = notes.end();
iter1--;
printf("processed %s: length %f, %i notes in %f seconds\n",filename.c_str(),((float)(iter1->first+iter1->second->duration)*.001f),notes.size(),ofGetElapsedTimef()-wt);
-
-//decimate notes to generate flakes that can be interacted with
- int noteThresh=1000;
- note *lastNote=notes.begin()->second;
- int lastTime=0;
- stars[notes.begin()->first]=notes.begin()->second;
- for (iter1 = notes.begin(); iter1 != notes.end(); iter1++) {
- if ((iter1->second->num/5!=lastNote->num/5)||(iter1->first-lastTime>noteThresh)) {
- stars[iter1->first]=iter1->second;
+}
+void musicscore::makeFlakes(int threshStart,int threshEnd){
+ //decimate notes to generate flakes that can be interacted with
+ map<int,note*>::iterator iter;
+ note *lastNote=notes.begin()->second;
+ int lastTime=0;
+ iter = notes.end();
+ iter--;
+ float songDuration=iter->first;
+ flakes[notes.begin()->first]=notes.begin()->second;
+ for (iter = notes.begin(); iter != notes.end(); iter++) {
+ float songPos=((float)iter->first)/songDuration;
+ if ((iter->second->num/5!=lastNote->num/5)||(iter->first-lastTime>((songPos*threshEnd)+((1.0f-songPos)*threshStart)))) {
+ flakes[iter->first]=iter->second;
}
- lastNote=iter1->second;
- lastTime=iter1->first;
- }
-
- interactionThresh=200; //how long player has to respond
- missedTime=-1;
-
-
+ lastNote=iter->second;
+ lastTime=iter->first;
+ }
}
void musicscore::setTimeframe(int millis) {timeframe=millis;}
-void musicscore::draw() {
+void musicscore::draw(levelscore *levels) {
ofEnableAlphaBlending();
int scoreStart=ofGetElapsedTimeMillis()-startTime;
int scoreEnd=scoreStart+timeframe;
- //temporary drawing method 46h - 52h
+ //note drawing 46h - 52h
int numnotes=16;
int firstnote=70;
float widthStep=((float)ofGetWidth())/numnotes;
float heightStep=((float)ofGetHeight())/timeframe;
map<int,note*>::iterator iter;
- for (iter = notes.lower_bound(scoreStart); iter != notes.upper_bound(scoreEnd); ++iter) {
+ //draw notes for reference
+ for (iter = notes.lower_bound(scoreStart); iter != notes.upper_bound(scoreEnd); ++iter) {
int thisnote=iter->second->num-firstnote;
int thisstart=iter->first-scoreStart;
int thislength=iter->second->duration;
ofSetColor(ofColor::fromHsb(((float)thisnote*255)/numnotes,200,100));
ofRect(thisnote*widthStep,ofGetHeight()-(thisstart*heightStep),widthStep,-(thislength*heightStep));
-
- //different methods for generating flakes
- //ideally theres a variable clumping factor, this means pre-processing the flakes though
-
- //ofSetColor(ofColor::fromHsb(((float)thisnote*255)/numnotes,200,255));
-
- //flake.draw((thisnote+0.5f)*widthStep,ofGetHeight()-(thisstart*heightStep));
- //flake.draw((iter->second->updown*ofGetWidth()*0.33)+(ofGetWidth()*0.5),ofGetHeight()-(thisstart*heightStep));
- //flake.draw((((thisnote/5)*5)+3.5f)*widthStep,ofGetHeight()-(thisstart*heightStep));
}
- for (iter = stars.lower_bound(scoreStart-200); iter != stars.upper_bound(scoreEnd); ++iter) { //added extra 200ms for flake to leave screen
+ //draw flakes
+ for (iter = flakes.lower_bound(scoreStart-200); iter != flakes.upper_bound(scoreEnd); ++iter) { //extra 200ms for flake to leave screen
int thisnote=iter->second->num-firstnote;
int thisstart=iter->first-scoreStart;
int thislength=iter->second->duration;
-
- // check player interaction
- if (thisstart<interactionThresh) {
- //this star needs to be interacted with
- if (((thisnote/5)+1)==playerKey) {
- //success!
- iter->second->playerActivated();
- }
- }
if (iter->second->activated) ofSetColor(255,255,255);
else ofSetColor(ofColor::fromHsb(((float)thisnote*255)/numnotes,200,255));
flake.draw((((thisnote/5)*5)+3.5f)*widthStep,ofGetHeight()-(thisstart*heightStep),flake.getWidth()/2,flake.getHeight()/2);
}
- //check for unactivated stars. must be a better way
- missedTime=-1;
- for (iter = stars.upper_bound(scoreStart); iter != stars.lower_bound(0); --iter) {
- if (!iter->second->activated) missedTime=scoreStart-iter->first;
- else break;
+ //check for unactivated flakes within this segment: is there a more efficient way?
+ //is it the number of flakes they can lose per segment?
+ missedFlakes=0;
+ missedLast=false;
+ for (iter = flakes.lower_bound(levels->getLowerBound(levels->getLevel(scoreStart))); iter != flakes.upper_bound(scoreStart); ++iter){
+ if (!iter->second->activated) {
+ missedFlakes++;
+ }
+ missedLast=!iter->second->activated;
}
ofDisableAlphaBlending();
}
-void musicscore::playerControl(int key){
- //0-3 - 0 is off
- playerKey=key;
+void musicscore::playerControl(int key,int threshold){
+ map<int,note*>::iterator iter;
+ int scoreTime=ofGetElapsedTimeMillis()-startTime;
+ for (iter = flakes.lower_bound(scoreTime-threshold); iter != flakes.upper_bound(scoreTime+threshold); ++iter) {
+ iter->second->activate();
+ }
}
//---------------------------------------------------------------------------------------------------------------------------------------------
-song::song(string backfile,string melfile,string notefile) {
+song::song(string backfile,string melfile,string musfile,string lyricfile,string levelfile) {
backing.loadSound(backfile);
melody.loadSound(melfile);
- notes.parseMidi(notefile);
+ notes.parseMidi(musfile);
+ lyrics.load(lyricfile);
+ levels.load(levelfile);
isPlaying=false;
- missedInterval=5000;
+ keyThresh=200;
}
void song::setTimeframe(int millis) {notes.setTimeframe(millis);}
+void song::setKeythresh(int millis) {keyThresh=millis;}
+void song::setFlakeThresh(int tS,int tE) {
+ fThreshStart=tS;
+ fThreshEnd=tE;
+}
void song::play() {
backing.play();
melody.play();
startTime=ofGetElapsedTimeMillis();
notes.startTime=startTime;
isPlaying=true;
+ notes.makeFlakes(fThreshStart,fThreshEnd);
}
void song::stop() {
backing.stop();
@@ -200,24 +191,33 @@ void song::preRoll(long preroll) {
notes.startTime=startTime;
isPreroll=true;
isPlaying=true;
+ notes.makeFlakes(fThreshStart,fThreshEnd);
}
void song::draw(){
- //how to deal with end/ track length/ part of game?
- if (isPreroll) {
- if (startTime<ofGetElapsedTimeMillis()) {
- backing.play();
- melody.play();
- isPreroll=false;
+ int songTime=ofGetElapsedTimeMillis()-startTime;
+ if (isPlaying) {
+ if (isPreroll) {
+ if (startTime<ofGetElapsedTimeMillis()) {
+ backing.play();
+ melody.play();
+ isPreroll=false;
+ }
}
+ if (notes.missedLast) {
+ melody.setVolume(0.0f);
+ if (levels.getLives(songTime)) {
+ if (notes.missedFlakes>levels.getLives(songTime)) {
+ //work out score
+ stop();
+ }
+ }
+ }
+ else melody.setVolume(1.0f);
+ notes.draw(&levels);
}
- if (notes.missedTime>0) {
- if (notes.missedTime>missedInterval) stop();
- else melody.setVolume(0.0f); //1.0f-((float)notes.missedTime/(float)missedInterval));
- }
- else melody.setVolume(1.0f);
- notes.draw();
+
+ ofDrawBitmapString(ofToString((float)songTime/1000.0f,3)+" "+ofToString(levels.getLevel(songTime))+" "+ofToString(notes.missedFlakes)+" of "+ofToString(levels.getLives(songTime)),10,ofGetHeight()-15);
}
void song::playerControl(int key){
- //0-3 - 0 is off
- notes.playerControl(key);
+ notes.playerControl(key,keyThresh);
}