feat: drop-out for drum-like instruments

This commit is contained in:
xtex 2023-07-30 10:17:21 +08:00
parent 0aee57947d
commit 726a0337c5
Signed by: xtex
GPG Key ID: B918086ED8045B91
2 changed files with 25 additions and 5 deletions

View File

@ -1,5 +1,6 @@
package quaedam.projection.music package quaedam.projection.music
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument
import kotlin.math.abs import kotlin.math.abs
import kotlin.random.Random import kotlin.random.Random
import kotlin.random.nextInt import kotlin.random.nextInt
@ -8,17 +9,32 @@ import kotlin.random.nextInt
* The composer for music. * The composer for music.
* rhythmRandom is used for a better rhythm sync between different instruments. * rhythmRandom is used for a better rhythm sync between different instruments.
*/ */
class Composer(val noteRandom: Random, val rhythmRandom: Random) { class Composer(val noteRandom: Random, val rhythmRandom: Random, val instrument: NoteBlockInstrument) {
data class Note(val note: Int, val volume: Float, val time: Int) data class Note(val note: Int, val volume: Float, val time: Int)
val baseTime = arrayOf(5, 5, 3, 3, 4, 4, 2, 2, 8).random(rhythmRandom) val baseTime = arrayOf(5, 5, 3, 3, 4, 4, 2, 2, 8).random(rhythmRandom)
val baseNote = noteRandom.nextInt(5..19) val baseNote = noteRandom.nextInt(5..19)
fun composeMusic() = decorate( val mayDropOut = instrument in arrayOf(
(0..rhythmRandom.nextInt(5)).flatMap { composeSection() } NoteBlockInstrument.BASEDRUM,
NoteBlockInstrument.HAT,
NoteBlockInstrument.SNARE,
) )
fun composeMusic(): List<Note> {
var note = (0..rhythmRandom.nextInt(4)).flatMap { composeSection() }
note = decorate(note)
if (mayDropOut && rhythmRandom.nextInt(3) != 0) {
val dropRate = rhythmRandom.nextInt(2..4)
note = note.chunked(dropRate).map {
val first = it.first()
Note(first.note, first.volume, it.sumOf { note -> note.time })
}
}
return note
}
fun decorate(notes: List<Note>) = notes.map { fun decorate(notes: List<Note>) = notes.map {
if (noteRandom.nextInt(4) == 0) { if (noteRandom.nextInt(4) == 0) {
doDecorate(it) doDecorate(it)

View File

@ -31,14 +31,18 @@ class MusicPlayer(val seed: Long, val level: Level, val pos: BlockPos, val start
tag.getLong(TAG_STARTED_AT) tag.getLong(TAG_STARTED_AT)
) )
var notes = Composer(Random(seed), Random(startedAt / 20 * 15)).composeMusic().toMutableList() var notes = Composer(
noteRandom = Random(seed),
rhythmRandom = Random(startedAt / 20 * 15),
instrument = level.getBlockState(pos).getValue(BlockStateProperties.NOTEBLOCK_INSTRUMENT)
).composeMusic().toMutableList()
val totalTime = notes.sumOf { it.time }.toLong() val totalTime = notes.sumOf { it.time }.toLong()
var remainingTime = totalTime var remainingTime = totalTime
val isEnd get() = remainingTime <= 0 || notes.isEmpty() val isEnd get() = remainingTime <= 0 || notes.isEmpty()
var noteTime = 0 var noteTime = 0
init { init {
var currentRemaining = totalTime - (level.gameTime - startedAt) val currentRemaining = totalTime - (level.gameTime - startedAt)
while (remainingTime > currentRemaining) { while (remainingTime > currentRemaining) {
// seek to current position // seek to current position
remainingTime -= fetchNote().time remainingTime -= fetchNote().time