2

私の計画は、Java でプールの簡単なゲームを設計することです。

OOP は、ボールに対してここで最も理にかなっています。すべてのボールは同じ機能を持っているため、ボールの相対的な位置や、ボールが穴に入ったときにそれ自体を削除してスコアをインクリメントするなどの他の変数を処理する Ball クラスを作成することをお勧めします。 . したがって、穴に当たったとき Ball.dispose (); うまくフィットします。

私の問題は、ボールを操作して処分する方法がわからないことです。また、それを移動するために、java.swing.timer の代わりに Thread.sleep に依存しています。これは、利用できる Action Performed メソッドがないためです。

ボールをより簡単に動かし、必要なときに取り除くにはどうすればよいですか?

ここに画像の説明を入力

ボールを覆っている緑色のものは、ボールの上に緑色の楕円を描くことで、ボールの最後の位置を消去する方法です。

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;


public class Main extends JFrame{

     Ball redball = new Ball (285, 600, 20, 20, Color.RED); 

    //variables to control redball
    private int rX = redball.getX();
    private int rY = redball.getY();
    private final int rWidth = redball.getWidth();
    private final int rHeight = redball.getHeight();

    int Force = 30; 
    int Bearing = 20; // True Bearing

 public Main (){

         setSize(600, 800);
         setVisible(true); 
         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         setTitle("Pool");

    }
     public void paint(Graphics g){
         super.paint(g);

         // draw the table
         g.setColor (Color.GREEN);
         g.fillRect(100, 100, 400, 600);
         g.setColor (Color.BLACK);
         g.drawRect(99, 99, 401, 601);


             //draw start ball
         g.setColor(redball.getColor());
         g.fillOval(rX, rY, rWidth, rHeight);



         if (Force == 30){
         for (int i = Force; i > 0;i--){
             try {
                    Thread.sleep(100);
                } catch(InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }
             Force--;
             if (rY > 98 + rWidth) {
                 rY = rY - i;
                 rX = rX + (Bearing/5);
             }

             g.fillOval(rX, rY, rWidth, rHeight);
             g.setColor(Color.GREEN);
             repaint ();
             g.fillOval(rX - (Bearing/5), rY + i, rWidth, rHeight); // repaint last ball
             g.setColor(Color.RED);
             repaint ();
          }
         }



         // Ball.dispose (redball);

     }

    public static void main(String[] args) {

        new Main();
    }

ボールのクラスはこちら

public class Ball {

    private int x;
    private int y;
    private int width;
    private int height;
    private Color color;

    public Ball (int x, int y, int width, int height, Color color)
    {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.color = color;
    }

    public void setX (int x){
        this.x = x;
    }

    public int getX (){
        return this.x;
    }

    public void setY (int x){
        this.y = y;
    }

    public int getY (){
        return this.y;
    }

    public void setWidth (int width){
        this.width = width;
    }

    public int getWidth (){
        return this.width;
    }

    public void setHeight (int height){
        this.height = height;
    }

    public int getHeight (){
        return this.height;
    }

    public void setColor (Color color){
        this.color = color;
    }

    public Color getColor (){
        return this.color;
    }

    public static void dispose(Ball ball) {

    ball = null; // if I call this method nothing happens

    }


}
4

2 に答える 2

2

ここにいくつかの提案があります。

  • ゲームのすべてのボールを含む Rack クラスを作成します。

  • ボールの描画コードを Ball クラスに移動します。この提案は純粋な MVC ではないことを認識していますが、オブジェクトが自分自身を描画すると、ゲームのコーディングがはるかに簡単になります。

  • 画面の一部を再描画しようとしないでください。画面全体を再描画するだけの方がはるかに簡単で、かなり高速です。

  • Ball インスタンスを破棄しないでください。描画コードが認識して描画しない負の位置に移動します。

アクション ゲームをコーディングする場合、メイン ループは次のようになります (疑似コード)。

while (running) {
    calculateRackPosition();
    drawRack();
    Thread.sleep(100L);
}

ボールを少しずつ動かしてから、画面を再描画します。これは、アニメーションをコーディングする方法です。このコードは、ボールが動いている間に実行されます。

人がショットを狙っているときは、別のコードを記述します。

于 2013-08-08T15:58:50.090 に答える
2

私がすることはList<Ball>、すべてのアクティブなボールのフィールドを維持することです. 次に、反復ごとに、そのリストを反復し、ボールを更新してペイントします。ボールがなくなったら、リストから削除するだけです。

考慮事項は次のとおりです。ボールを処分する時期を誰が決定しますか? ボールの外に何かがある場合は、いくつかのオプションがあります。

  1. 上で述べたように、ボールをリストから削除するだけです。
  2. 他の場所でボールに「デッド」フラグを設定し、各反復で「デッド」フラグが設定されているすべてのボールをリストから削除できます。

ボール自体がいつ立ち去るかを決定する場合、いくつかのオプションがあります。

  1. おそらく、boolean Ball.think()ボールの状態を更新し、ボールがまだ有効な場合は true を返し、無効な場合は false を返すメソッドです。次に、ボールのリストを反復処理するときに、think()すべてのボールを呼び出して更新し、false を返したボールをリストから削除します。
  2. 上記のオプション 2 に関連して、Ball にthinkメソッドまたは類似のものがある場合、Ball は独自の「デッド」フラグを設定できます (または、Ball の外部の何かがそれを設定できます)。その後、メイン ループはデッド ボールをリストから削除できます。

Ball インスタンスを保持し、描画しないようにする場合は、いくつかのオプションもあります。

  1. ボールを削除する代わりに、「デッド」とマークされたボールの処理をスキップするだけです。
  2. 「デッド」ボールを別のデッド ボール リストに移動します。

個人的にboolean think()は、シーン内のオブジェクトの基本インターフェイスを簡単に指定できるため、この方法が気に入っています。その場合、オブジェクト自体をペイントすることもできます。例えば:

interface Entity {
    public boolean think ();
    public void paint (Graphics g);
}

class Ball implements Entity {
    @Override public boolean think () {
        // return true if alive, false if dead
    }
    @Override public void paint (Graphics g) {
        // draw this ball
    }
}

// then in your main update loop:
List<Entity> entities = ...;
Iterator<Entity> eit = entities.iterator();
while (eit.hasNext())
    if (!eit.next().think()) 
        eit.remove();

// and in paint:
for (Entity e:entities)
    e.paint(graphics);

上記の「死んだ」ボールを削除するのではなくスキップするというオプションを使用したい場合は、このようなものがより適切です (簡潔にするために Ball を省略します)。isActive() は、ボールがアクティブまたは false の場合に true を返します。一時的に「死んでいる」場合:

interface Entity {
    public boolean isActive ();
    public void think (); // think returns nothing
    public void paint (Graphics g);
}

// then in your main update loop:
List<Entity> entities = ...;
for (Entity e:entities)
    if (e.isActive())
        e.think();
// it is the responsibility of something outside the ball to restore it to an
// active state, since think() isn't called if !isActive(). alternatively, you 
// could always call think(), and just don't paint inactive balls.

// and in paint:
for (Entity e:entities)
    if (e.isActive())
        e.paint(graphics);

それでも、そのようにする必要はありません上記のすべてのオプションなどには、たくさんの引数があります。たとえば、あなたのアプリケーションでは、Entityボールだけを扱っていることがわかっている場合、インターフェースはあまり必要ありません。すべての物理ロジックが別の場所で発生している場合、これは最も便利な方法ではない可能性がありthink()ます (もちろん、ロジックを Ball に配置するようにコードを作成することもできます)。

ご覧のとおり、猫の皮を剥ぐ方法はたくさんありますが、ここで何かが役立つことを願っています.

于 2013-08-08T15:55:02.170 に答える