1

我在我的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);
            }
        }
    }
}

这就是我的椭圆类。

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

如您所见,我正在创建椭圆并给它们“移除冷却时间”,并且在冷却结束后椭圆会销毁。问题是如果我删除 println("asd") 行,代码将无法正常工作。也就是说,如果我删除那条线,椭圆会同时出现和消失(冷却不起作用)。

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

4

2 回答 2

2

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

您想要做的是用某种实际的计时器替换原始倒计时。秒表可以完成这项工作。(显然,我之前建议的 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# 思考,现在修复了。

于 2015-02-18T13:12:17.047 回答
0

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

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

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

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

于 2015-02-18T13:47:26.037 回答