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 を追加するときに楕円が表示される理由は、印刷に少し時間がかかるためです。100 回実行すると、数ミリ秒分の楕円が得られます。

あなたがしたいことは、生のカウントダウンをある種の実際のタイマーに置き換えることです。ストップウォッチは仕事をするでしょう。(明らかに、以前に提案した 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# で考えていましたが、修正されました。

于 2015-02-18T13:12:17.047 に答える
0

println("asd");かなり高価な操作です。それがなければ、上記のループは 10 ミリ秒未満で完了します。

を使用するprintln()と、ループにかかる時間が大幅に長くなり、何が起こるかを確認できます。

アニメーションを実行するときは、アニメーション ループをタイマーに同期させて、1 秒あたり 60 フレームを超えないようにする必要があります。

簡単な修正は、 を に置き換えて、println()毎秒Thead.sleep(1000/50);50 フレーム (およそ) を取得することです。スムーズなアニメーションが必要な場合は、Timer.scheduleAtFixedRate()を使用して、レンダリング コマンドにかかる時間を考慮する必要があります。

于 2015-02-18T13:47:26.037 に答える