feat: drop-out for drum-like instruments
This commit is contained in:
parent
0aee57947d
commit
726a0337c5
@ -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)
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user