Jump to content
This forum will be closing down. Please move to the respective dedicated project forums.

Rhythm game mechanics (audio/body velocity sync)


Recommended Posts

Hi everyone,


I want to make a basic rhythm game in Phaser where the user has to hit specified keys to 'catch' the incoming notes while staying in rythm. So far the main game area roughly looks like this:





The idea is that the key must be hit (and the corresponding note played) when the note sprite fully overlaps the key sprite, and the score is calculated based of how close the note sprite is to the top edge of the key sprite. I have an array of percussion loops with various BPMs I made in a DAW  which change after each level to increase the difficulty. When the level starts this function is called:

beginPlaying: function(l){this.noteCount = 25;this.currentLoop = this.loops[l];this.currentLoop.play();this.maxInterval = this.currentLoop.durationMS/4;this.timer.add(0, this.generateNotes, this);this.timer.start();},

generateNotes function goes like this:

generateNotes: function(){if(this.noteCount > 0){var num = this.game.rnd.integerInRange(0, 4);var note = this.notes.create(this.noteFlags.getAt(num).x, this.game.height - 20, 'note');this.game.physics.arcade.enable(note);var distance = note.y - this.noteFlags.getAt(num).y;note.body.velocity.y = -(distance/(this.currentLoop.duration/2));this.noteCount--;this.timer.add(this.maxInterval, this.generateNotes, this);}},

I'm planning to make it more complicated by spawning notes not only at maxInterval, but so far I'm facing a problem: even though the first few notes seem to land perfectly in rhythm with the currentLoop, later they stop keeping up with the drums and the whole thing goes completely out of sync. I suppose this has something to do with the sound duration in ms and the fact that this.maxInterval is not a whole number.  


I tried rounding the numbers using Math.round and Math.floor and I also tried alternative methods of calculating note positions, like 

n.y -= (distance/(this.currentLoop.duration/2))/60;

called using this.notes.forEachAlive method from the update function. Right now I'm completely lost (I guess that's the price you pay when you start programming while not being very good at maths smile.png). Is there any way to deal with the audio/velocity sync problem? I would very much appreciate any suggestions :)



Link to comment
Share on other sites

A general answer.


Incremental movements (e.g. y += (velocity * deltaAge)) will tend towards cumulative variations over time, and therefore become out of sync with a linear thread of the same age (e.g. the audio).

This will become more apparent as the game continues.


Instead, define position using overall duration instead (e.g. y = startOffset + (velocity * age) ).


Working backwards so the notes land on the beat should be trivial if you know the bpm - and some minor correction is often needed to make it feel "perfect" (to allow for visual and input lag).

Link to comment
Share on other sites


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...