【问题标题】:Delay boolean from switching back to false延迟布尔值从切换回 false
【发布时间】:2013-09-13 04:00:53
【问题描述】:

所以,我正在开发一款需要节拍检测的游戏。在这一点上,我有工作节拍检测代码,但它在它自己的独立 java 小程序中,而我正在努力解决问题,所以我不会在游戏代码中造成任何问题。我的问题是,当代码检测到节拍时,它会切换回不比用户点击屏幕快的节拍。

我创建了一个简单的布尔值,只要发生节拍,它就会将 isBeat 从 false 切换为 true,并且我打印出单词“True”和“False”。当程序运行时,你几乎看不到“True”这个词,因为它只在屏幕上出现了几分之一秒。有什么办法可以延迟 isBeat 从 true 到 false 的切换?

基本上在这一点上,我希望“True”(意味着刚刚发生的节拍)这个词在屏幕上保留 1 秒钟。 1 秒过去后,它会切换到“False”并等待下一个节拍。 1 秒有点长,但我现在可以通过这种方式更好地测试它。它不能简单地延迟更改屏幕上的绘图,但它需要延迟整个布尔值的切换,因为我将在最终游戏中使用 isBeat 布尔值。当节拍发生时,isBeat 将切换为 true,并在切换回 false 之前给玩家一小段时间来点击屏幕。屏幕上不会出现任何文字让他们知道像现在这样发生了节拍。

这里是代码。这是使用 minim 库以及 eclipse 内部的处理。

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() 的方法,但要么我做错了,要么它也不打算按照我想要的方式工作。似乎是一个我无法弄清楚的简单问题......

【问题讨论】:

    标签: java android boolean delay beat-detection


    【解决方案1】:

    我认为你的代码中有逻辑错误

    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);
    

    除此之外,我不建议使用 sleep 或 wait 之类的东西,因为它会在等待的时间内挂起线程。

    我可以给你的一个建议是使用当前时间的额外条件

    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);
            .
            .
       }
    

    【讨论】:

    • 这就是为什么你应该几乎总是使用带有 if/for/while 语句的块,即使它是一行。很容易错过这样的事情。同样,如果只是一个常规的 else 块,我会做第二个。最后,不需要做== true,只需将变量本身放入块中,它就会被正确评估。
    【解决方案2】:

    一个非常简单的方法是这样的:

    声明一个成员变量

    private long lastBeatAt = 0;
    

    然后用它来存储最后一拍的时间戳:

    if (beat.isSnare() == true)
    {
        isBeat = true;
        beatCount++;
        lastBeatAt = System.currentTimeMillis();
    }
    else if (System.currentTimeMillis() > lastBeatAt + 1000) 
    {
        isBeat = false;
    }
    

    当然,这不会导致 isBeat 精确到一秒,但它会很接近,具体取决于调用 draw() 的频率。

    【讨论】:

      猜你喜欢
      • 2020-08-01
      • 1970-01-01
      • 2021-08-03
      • 2021-09-02
      • 2016-05-27
      • 1970-01-01
      • 2017-11-23
      • 2017-09-27
      • 1970-01-01
      相关资源
      最近更新 更多