2011-02-07 16 views
0

私は3D環境でシミュレーションを行っています。これまでのところ、私はすべての生き物の動きを持っていますが、それは「滑らか」ではありません。私はかなりのことを試みましたが、ひどく間違っていました。今私は何をすべきか分かりません。私はベクトル(ベクトルクラスではない)を実装することを考えていましたが、実際にどのように知っていません。Javaのスムーズな移動

import env3d.EnvObject; 
import java.util.ArrayList; 

abstract public class Creature extends EnvObject 
{ 

/** 
* Constructor for objects of class Creature 
*/ 
public Creature(double x, double y, double z) 
{ 
    setX(x); 
    setY(y); 
    setZ(z); 
    setScale(1); 
} 

public void move(ArrayList<Creature> creatures, ArrayList<Creature> dead_creatures) 
{     
    double rand = Math.random(); 
    if (rand < 0.25) { 
     setX(getX()+getScale()); 
     setRotateY(90); 
    } else if (rand < 0.5) { 
     setX(getX()-getScale()); 
     setRotateY(270); 
    } else if (rand < 0.75) { 
     setZ(getZ()+getScale()); 
     setRotateY(0); 
    } else if (rand < 1) { 
     setZ(getZ()-getScale()); 
     setRotateY(180); 
    }     

    if (getX() < getScale()) setX(getScale()); 
    if (getX() > 50-getScale()) setX(50 - getScale()); 
    if (getZ() < getScale()) setZ(getScale()); 
    if (getZ() > 50-getScale()) setZ(50 - getScale()); 

    // collision detection 
    if (this instanceof Fox) { 
     for (Creature c : creatures) { 
      if (c.distance(this) < c.getScale()+this.getScale() && c instanceof Tux) { 
       dead_creatures.add(c); 
      } 
     } 
    } 
}   

}

import env3d.Env; 
import java.util.ArrayList; 

/** 
* A predator and prey simulation. Fox is the predator and Tux is the prey. 
*/ 
public class Game 
{ 
private Env env;  
private boolean finished; 

private ArrayList<Creature> creatures; 

/** 
* Constructor for the Game class. It sets up the foxes and tuxes. 
*/ 
public Game() 
{ 
    // we use a separate ArrayList to keep track of each animal. 
    // our room is 50 x 50. 
    creatures = new ArrayList<Creature>(); 
    for (int i = 0; i < 55; i++) { 
     if (i < 5) { 
      creatures.add(new Fox((int)(Math.random()*48)+1, 1, (int)(Math.random()*48)+1));   
     } else { 
      creatures.add(new Tux((int)(Math.random()*48)+1, 1, (int)(Math.random()*48)+1)); 
     } 
    } 
} 

/** 
* Play the game 
*/ 
public void play() 
{ 

    finished = false; 

    // Create the new environment. Must be done in the same 
    // method as the game loop 
    env = new Env(); 

    // Make the room 50 x 50. 
    env.setRoom(new Room()); 

    // Add all the animals into to the environment for display 
    for (Creature c : creatures) { 
     env.addObject(c); 
    } 

    // Sets up the camera 
    env.setCameraXYZ(25, 50, 55); 
    env.setCameraPitch(-63); 

    // Turn off the default controls 
    env.setDefaultControl(false); 

    // A list to keep track of dead tuxes. 
    ArrayList<Creature> dead_creatures = new ArrayList<Creature>(); 

    // The main game loop 
    while (!finished) {    

     if (env.getKey() == 1) { 
      finished = true; 
     } 

     // Move each fox and tux. 
     for (Creature c : creatures) { 
      c.move(creatures, dead_creatures); 
     } 

     // Clean up of the dead tuxes. 
     for (Creature c : dead_creatures) { 
      env.removeObject(c); 
      creatures.remove(c); 
     } 
     // we clear the ArrayList for the next loop. We could create a new one 
     // every loop but that would be very inefficient. 
     dead_creatures.clear(); 

     // Update display 
     env.advanceOneFrame(); 
    } 

    // Just a little clean up 
    env.exit(); 
} 


/** 
* Main method to launch the program. 
*/ 
public static void main(String args[]) { 
    (new Game()).play(); 
} 

}

答えて

0

あなたはあなたのプログラムを十分に示していません。基本的には、アニメーションをスムーズにしたい場合、(JavaFXなどを使用するのではなく)自分でやりたければ、インターフレームをたくさん行う必要があります。したがって、タイマーティック全体を前進させるのではなく、タイマーティックの10分の1を進め、画面上のすべてを少し動かしてから、もう一度進んでください。スムーズなアニメーションのために、10秒ごとにバックグラウンドの再描画を行う必要があります。

+0

私は自分自身をはっきりと説明していないと思う。 現在、move()が呼び出されるたびに、ランダムになると1(尺度[getscale()])が加算されます。動きは本当に不安定で突然です。私が望むのは、それらを基本的に...そこに現れるのではなく目的地まで歩くことです。分かりますか? a = bの代わりにaからaへ歩くのと同じように。 ゲームクラスにはリアルタイムを確立するためのwhileループがあります。基本的にはフレームごとにmove()を呼び出します。 – bobby

+0

実例を投稿する必要があります。ただし、現在のスケールで1を加算すると動きが不安定になる場合は、0.1を追加する必要があります。 – vy32

+0

フレームのステップサイズを小さくし、ペイントルーチンをより頻繁に実行させます。 – vy32

0

前述のように、私たちはあなたのコードをもっと見る必要があります。しかし、タイミングコードが不足しているように見えます。

あなたがしたいことは、ゲームループが繰り返されるたびに時間をチェックしてから、一定の時間、スリープして、望ましいフレームレートを達成することです。それ以外の場合、ゲームループは1秒間に数十万回実行されます。

また、前のフレームから経過した時間に比例した距離だけあなたのクリーチャーを前進させる必要があります。ここで

は(「FPS」は、所望のフレームレートである)非常に単純な規制ループの例です:

private long frameLength = 1000000000/fps; 

public void run() { 
    long ns = System.nanoTime(); 
    while (!finished) { 

     //Do one frame of work 
     step(); 

     //Wait until the time for this frame has elapsed 
     try { 
      ns += frameLength; 
      Thread.sleep(Math.max(0, (ns - System.nanoTime())/10000000)); 
     } catch (InterruptedException e) { 
      break; 
     } 
    } 
} 

あなたのゲームループにこれを改造するのは非常に簡単なはずです。

+0

私はそれが漂うので、このアプローチが嫌いです。また、作業が複雑になると、より多くのドリフト(頻繁に更新されない)されます。より良いアプローチは、毎回指定された量のスリープを行うのではなく、特定のレートでオフになるタイマーを使用することです。 – vy32

+0

私は特に簡単な解決策を出していました。この場合、もっと良いものが必要なのかどうかは疑問です。しかし、あなたが示唆している行に沿った答えを書くことができますか?別のスレッドを使わずに半単純に行うことは可能ですか? – Pryo

関連する問題