编写 "println" 修复了我的代码,如何?

Writing "println" fixes my code, how?

我在 CS 讲座中尝试了一些东西然后突然遇到了一个有趣的问题。

这是我的主要代码,

public void run(){
    setSize(800, 600);

    for(int i=0; i<= 30; i++){
        elips el = new elips();
        el.setFilled(true);
        el.setColor(Color.RED);
        elipsler.add(el);
        add(el);
    }

    while(!stopthat){
        for(int i=0; i< elipsler.size() -1; i++){
            elipsler.get(i).cdRemove();

            println("asd");

            if(elipsler.get(i).canRemove == true){
                remove(elipsler.get(i));
                elipsler.remove(i);
                elips el = new elips();
                el.setFilled(true);

                add(el);
                elipsler.add(el);
            }
        }
    }
}

那是我的椭圆 class。

public class elips extends GOval{
    static int x, y, w, h;
    int cd;
    public boolean canRemove = false;
    Random rand = new Random();

    public elips(){
        super(x, y, w, h);
        canRemove = false;
        cd = rand.nextInt(100);
        x = rand.nextInt(780) + 20;
        y = rand.nextInt(580) + 20;
        w = rand.nextInt(80) + 20;
        h = rand.nextInt(80) + 20;
    }

    public void cdRemove(){
        if(this.cd <= 0){
            this.canRemove = true;
        }else{
            this.cd--;
        }
    }
}

如您所见,我正在创建椭圆并给它们 "remove cooldown",冷却结束后,椭圆会消失。问题是如果我删除 println("asd") 行,代码将无法正常工作。也就是说,如果我删除该行,省略号会同时出现和消失(冷却无效)。

所以我想知道"println"行如何解决这个问题?

从 100 倒数到 0 的时间几乎为零,这基本上就是您在删除椭圆之前所做的事情。添加 println 时看到椭圆的原因是因为打印需要一些时间。一百次,你得到几毫秒的椭圆。

您要做的是用某种实际计时器替换原始倒计时。 Stopwatch 就可以了。 (显然,我之前建议的 DateTime 在精确到几毫秒时并不那么准确) 我一直在用 C# 思考。在 java 中,使用 System.currentTimeMillis() 是可行的方法。

ninja:如果您需要,我会在今天晚些时候提供代码

编辑: 现在,您实际上是在这样做:

add ellipse
for(int i = 0; i < 100; i++)
{
    // nothing happening in here, this entire loop takes zero time
}
remove ellipse

println:

add ellipse
for(int i = 0; i < 100; i++)
{
    println("asd"); 
    // something happening in here, this entire loop takes a little bit of time
}
remove ellipse

这种冷却系统会以不止一种方式成为问题:

  • 每个滴答声所花费的时间会有所不同(有时会很大),具体取决于 运行 在
  • 上的计算机
  • 您基本上是在锁定整个应用程序。如果你想做一些与此平行的事情,你将不得不创建一个单独的线程,或者你所做的任何事情都会影响每个滴答之间的时间,从而改变冷却时间,同时也会受到与所有椭圆相同的冷却时间的影响合并。
  • 你实际上并不是在测量时间。

所以,这是一个测量时间的选项:

public class elips extends GOval{
    static int x, y, w, h;
    int cd;
    public boolean canRemove = false;
    Random rand = new Random();

    long timeStart;

    public elips(){
        super(x, y, w, h);
        canRemove = false;
        cd = rand.nextInt(100);
        x = rand.nextInt(780) + 20;
        y = rand.nextInt(580) + 20;
        w = rand.nextInt(80) + 20;
        h = rand.nextInt(80) + 20;

        timeStart = System.currentTimeMillis();
    }

    public void cdRemove(){
        if(System.currentTimeMillis() > timeStart + cd)
            this.canRemove = true;
    }
}

并且:

public void run(){
    setSize(800, 600);

    for(int i=0; i<= 30; i++){
        elips el = new elips();
        el.setFilled(true);
        el.setColor(Color.RED);
        elipsler.add(el);
        add(el);
    }

    while(!stopthat){
        // now you can do stuff here that will not be delayed by the ellipse cooldowns
        // neither will it become part of the ellipse cooldowns 
        for(int i=0; i< elipsler.size() -1; i++){
            elipsler.get(i).cdRemove();


            if(elipsler.get(i).canRemove == true){
                remove(elipsler.get(i));
                elipsler.remove(i);
                elips el = new elips();
                el.setFilled(true);

                add(el);
                elipsler.add(el);
            }
        }
    }
}

这可能会有一些变化,我的校对很快就读完了。

编辑 2:我在用 C# 考虑秒表等,现在解决了。

println("asd"); 是相当昂贵的操作。没有它,上面的循环会在不到 10 毫秒的时间内完成,这对于人眼来说是一种快速的方式。

使用 println(),循环需要更长的时间,让您看到会发生什么。

制作动画时,您需要将动画循环与计时器同步,以确保每秒不会超过 60 帧,因为人眼速度太慢,看不到那么快。

一个简单的修复方法是将 println() 替换为 Thead.sleep(1000/50); 以获得每秒 50 帧(大致)。如果你想要一个流畅的动画,你需要使用 Timer.scheduleAtFixedRate() 来计算你的渲染命令所花费的时间。