所以,我正在开发一款需要节拍检测的游戏。 在这一点上,我有工作节拍检测代码,但它在它自己的独立 java 小程序中,同时我正在努力解决问题,这样我就不会在游戏代码中引起任何问题。 我的问题是,当代码检测到节拍时,它会切换回不比用户点击屏幕快的节拍。
我创建了一个简单的布尔值,每当节拍发生时,它就会将isBeat从false切换到true,并且我正在打印出单词"True"和"False"。 当程序运行时,您几乎看不到"True"一词,因为它只在屏幕上显示几分之一秒。 有没有办法延迟isBeat从真到假的切换?
基本上在这一点上,我希望"True"这个词(意味着刚刚发生的节拍)在屏幕上停留 1 秒钟。 1 秒过后,它将切换到"False"并等待下一个节拍。 1 秒有点长,但我现在能够以这种方式更好地测试它。 它不能延迟简单地更改屏幕上的绘图,但它需要延迟整个布尔值的切换,因为我将在最终游戏中使用 isBeat 布尔值。 当节拍发生时,isBeat 将切换到 true,并在切换回 false 之前给玩家一小段时间来点击屏幕。 屏幕上不会出现任何文本,让他们知道像现在这样发生了节拍。
这是代码。 这是使用最小库以及日食内部的处理。
import processing.core.*;
import ddf.minim.*;
import ddf.minim.analysis.*;
public class MyProcessingSketch extends PApplet {
Minim minim;
AudioPlayer song;
BeatDetect beat;
BeatListener bl;
float kickSize, snareSize, hatSize;
float playPos, playLen, xpos;
int kickCount = 0;
int snareCount = 0;
int hatCount = 0;
int beatCount = 0;
boolean isBeat = false;
public void setup()
{
size(600, 500);
minim = new Minim(this);
song = minim.loadFile("mainmenumusic.mp3");
song.play();
playPos = song.position();
playLen = song.length();
xpos = (playPos / playLen) * width;
beat = new BeatDetect(song.bufferSize(), song.sampleRate());
beat.setSensitivity(24);
kickSize = snareSize = hatSize = 16;
bl = new BeatListener(beat, song);
textFont(createFont("Helvetica", 16));
textAlign(CENTER);
}
public void draw()
{
background(0);
fill(255);
beat.detect(song.mix);
if(beat.isKick()) kickSize = 32;
if(beat.isKick()) kickCount++;
if(beat.isSnare()) snareSize = 32;
if(beat.isSnare()) snareCount++;
if(beat.isSnare() == true)
{
isBeat = true;
beatCount++;
}
else
{
isBeat = false;
}
if(beat.isHat()) hatSize = 32;
if(beat.isHat()) hatCount++;
textSize(kickSize);
text("isBeat", width/4, height/4);
if(isBeat == true)
text("True", width/4, height/2);
if(isBeat == false);
text("False", width/4, height/2);
textSize(snareSize);
text("SNARE", width/2, height/4);
text(snareCount, width/2, height/2);
textSize(hatSize);
text("HAT", 3*width/4, height/4);
text(hatCount, 3*width/4, height/2);
kickSize = constrain((int) (kickSize * 0.95), 16, 32);
snareSize = constrain((int) (snareSize * 0.95), 16, 32);
hatSize = constrain((int) (hatSize * 0.95), 16, 32);
}
public void stop()
{
song.close();
minim.stop();
super.stop();
}
}
我已经做了一些谷歌搜索并尝试了一些类似wait()的东西,但要么我都做错了,要么它也不打算按照我想要的方式工作。 似乎是一个我无法弄清楚的简单问题...
我认为您的代码中有逻辑错误
if(isBeat == true)
text("True", width/4, height/2);
if(isBeat == false); // <---- here you have ; so
text("False", width/4, height/2); //<---- this will always be executed even if isBeat == true
textSize(snareSize);
text("SNARE", width/2, height/4);
除此之外,我不建议使用睡眠或等待之类的东西,因为它会在等待期间挂起线程。
我可以给你的一个建议是使用利用当前时间的额外条件
long previous_beat = System.currentTimeMillis(); //<--- class variable
.
.
public void draw()
{
.
.
textSize(kickSize);
text("isBeat", width/4, height/4);
if(isBeat == true || previous_beat+10*1000> System.currentTimeMillis())
{
text("True", width/4, height/2);
previous_beat = System.currentTimeMillis();
}
else if(isBeat == false)
text("False", width/4, height/2);
textSize(snareSize);
text("SNARE", width/2, height/4);
.
.
}
一个非常简单的方法是:
声明成员变量
private long lastBeatAt = 0;
然后使用它来存储上次节拍的时间戳:
if (beat.isSnare() == true)
{
isBeat = true;
beatCount++;
lastBeatAt = System.currentTimeMillis();
}
else if (System.currentTimeMillis() > lastBeatAt + 1000)
{
isBeat = false;
}
当然,这不会导致 isBeat 的一秒为真,但根据调用 draw() 的频率,它会很接近。