Написание "println" исправляет мой код, как?

Я пытался что-то в моей лекции 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" может решить эту проблему?

2 ответа

Решение

Обратный отсчет от 100 до 0 выполняется практически за нулевое время, и это, по сути, то, что вы делаете перед удалением эллипса. Причина, по которой вы видите эллипс при добавлении println, заключается в том, что для его печати требуется небольшое количество времени. Сто раз, и вы получили эллипс на пару миллисекунд.

То, что вы хотите сделать, это заменить необработанный обратный отсчет фактическим таймером. Секундомер сделает эту работу. (По-видимому, DateTime, который я ранее предлагал, не совсем точен, когда составляет несколько миллисекунд) Я все это время думал на C#. В Java, использование System.currentTimeMillis() это путь.

ниндзя: я предоставлю код позже сегодня, если вам это нужно

РЕДАКТИРОВАТЬ: Прямо сейчас, вы по существу делаете это:

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(), чтобы учесть время, которое занимают ваши команды рендеринга.

Другие вопросы по тегам