重绘动画中的多个Ball对象(一次一个)

时间:2016-01-25 05:28:45

标签: java animation paintcomponent repaint

我有一个程序,我需要为球对象设置动画。我有一个Ball()类来处理球向下移动时的移动,然后是一个Animation()类,用于绘制球和背景,然后使用计时器重新绘制球。

我需要每个球都有动画,然后球停在屏幕底部,在屏幕顶部开始另一个球。我假设我需要一个Ball对象数组,以便在实例化一个新球时球不会消失。我的问题是我无法弄清楚如何在我的代码中实例化另一个Ball对象。我尝试了多种方法但都失败了。我终于通过一个工作球将我的代码恢复到正常状态并希望得到一些帮助!

最后注意:用户将从另一个菜单类中指定球的数量,然后将整数值传递给Animation()类构造函数。我想用这个整数值创建一个球数组。这是正确的思维方式吗? paintComponent()方法无法在构造函数中看到一个数组,所以我必须创建一个方法将数组传递给paintComponent()?

动画类:

public class Animation extends JPanel implements ActionListener{

// Global Variables
private Timer timer;
Random rand = new Random();
private int delay = 0;
ActionListener updateAnim;
Ball myBall = new Ball();

// Animation Constructor
public Animation()
{
    timer = new Timer(delay,this);
    timer.setInitialDelay(500);
    timer.start();
}

// Ball will roll down/left/right
public void actionPerformed(ActionEvent e)
{       
    int x = rand.nextInt(2);
    myBall.rollDown();

    if (x == 0)
        myBall.rollRight();
    else
        myBall.rollLeft();

    myBall.finalDescent();
    repaint();
}

// Draws Ball object, and Background
public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    myBall.drawBall(g);

    this.setBackground(Color.WHITE); // Background

    int counter = 0; // count what number peg we are painting
    int row = 1;     // calculate what row we are creating
    int rowSpacer = 55;
    boolean evenRow = false;
    int columnSpacer = 60;

    // DRAW PEGS TO SCREEN (4 rows of 8, 4 rows of 7)
    for (int x = 0; x < 60; x++)
    {
        // For odd rows
        if (row % 2 == 1)
        {
            g.setColor(Color.BLACK);
            g.fillOval(rowSpacer - 40, columnSpacer, 10, 10);
            rowSpacer += 40;
            counter++;
        }
        // For Even rows
        else 
        {
            g.setColor(Color.BLACK);
            g.fillOval(rowSpacer - 20, columnSpacer, 10, 10);
            rowSpacer += 40;
            counter++;
        }

        // Check to see if we are finished with odd row
        if (counter % 8 == 0 && evenRow == false)
        {
            row++;
            rowSpacer = 55;
            columnSpacer += 60;
            evenRow = true;
            counter = 0;
        }
        else if(counter % 7 == 0 && evenRow == true) 
        {
            row++;
            rowSpacer = 55;
            columnSpacer += 60;
            evenRow = false;
            counter = 0;
        }
    } // END DRAWING PEGS TO SCREEN

    // DRAW RECTANGULAR WALLS TO SCREEN
    g.setColor(Color.BLACK);    // Wall Color
    g.fillRect(0, 0, 5, 760);   // LEFT Wall
    g.fillRect(315, 0, 5, 760); // RIGHT Wall
    //g.fillRect(0, 0, 315, 5);   // TOP Wall
    g.fillRect(0, 755, 320, 5); // BOTTOM Wall

    // DRAW BOTTOM GATES
    int gateSeperator = 35;
    for (int x = 0; x < 7; x++)
    {
        g.setColor(Color.BLACK);
        g.fillRect(gateSeperator, 500, 10, 255);
        gateSeperator += 40;
    }   

    } // END paintComponent()
} // END Animation Class

球类:

public class Ball{

private int x = 85, y = -30;
private int velx = 0, vely = 0;
private boolean downInMotion = false;
private boolean rightInMotion = false;
private boolean leftInMotion = false;
private boolean ballStopped = false;
private boolean finalDescent = false;
private boolean horizontalLast = true;
private int hCounter = 0, vCounter = 0;
private int traveled = 0;

public void moveBall(int xPos, int yPos)
{
    x = xPos;
    y = yPos;
}

public int getX()
{
    return x;
}

public int getY()
{
    return y;
}

public void rollDown()
{
    if(leftInMotion == false && rightInMotion == false && ballStopped == false
            && finalDescent == false && horizontalLast == true)
    {
        downInMotion = true;
        vely = 1;
        velx = 0;

        if (traveled == ((vCounter + 60) + hCounter))
        {
            vely = 0;
            downInMotion = false;
            horizontalLast = false;
            vCounter += 60;
            System.out.println("Turning Right");
        }
        else
        {
            moveBall(x, y + vely);
            traveled += 1;
            System.out.println("Traveled: " + traveled);
        }
    }
} // END rollDown()

// The Ball will roll to the right
public void rollRight()
{
    if (leftInMotion == false && downInMotion == false && ballStopped == false 
            && finalDescent == false && horizontalLast == false)
    {
        rightInMotion = true;
        vely = 0;
        velx = 1;

        if (traveled == (vCounter + (hCounter + 20)))
        {
            velx = 0;
            rightInMotion = false;
            horizontalLast = true;
            hCounter += 20;
            System.out.println("Going Down");
        }
        else
        {
            moveBall(x + velx, y);
            traveled += 1;
            System.out.println("Traveled: " + traveled);
        }
    }
} // END rollRight()

public void rollLeft()
{
    if (rightInMotion == false && downInMotion == false && ballStopped == false
            && finalDescent == false && horizontalLast == false)
    {
        leftInMotion = true;
        vely = 0;
        velx = -1;

        if (traveled == (vCounter + (hCounter + 20)))
        {
            velx = 0;
            leftInMotion = false;
            horizontalLast = true;
            hCounter += 20;
            System.out.println("Turning Right");
        }
        else
        {
            moveBall(x + velx, y);
            traveled += 1;
            System.out.println("Traveled: " + traveled);
        }
    }
} // END rollLeft()

public void finalDescent()
{
    if (traveled >= 640 && ballStopped == false)
    {           
        finalDescent = true;

        vely = 1;
        velx = 0;

        System.out.println("FINAL DESCENT");

        if (traveled == 915)
        {
            vely = 0;
            System.out.println("Ball Stopped");
            stopBall();
        }
        else
        {
            moveBall(x, y + vely);
            traveled += 1;
            System.out.println("Traveled: " + traveled);
        }
    }
} // END finalDescent()

public void stopBall()
{
    ballStopped = true;
}

public void drawBall(Graphics g)
{
    g.setColor(Color.GREEN);
    g.fillOval(x, y, 30, 30);

}
}

1 个答案:

答案 0 :(得分:0)

你可能忘了在阵列中实例化每个球......

//declare a field
private List<Ball> balls;

Animation(int count) {
  balls = new ArrayList<Ball>();
  for (int i = 0; i < count; ++i) {
    //this is probably what you've missed...
    balls.add(new Ball());
  }
}


...
public void paintComponent(Graphics g)
  ...
  //paint as usual
  for (int i = 0; i < balls.length; ++i) {
    //this is probably what you've missed...
    balls[i].drawBall(g);
  }
}

...
public void someMethod() {
    if (youWantToAddBall) {
        balls.add(new Ball());
    }
    if (youWantToRemoveBall) {
        Ball ballToRemove = ...; //
        balls.remove(ballToRemove);
    }
}

[编辑:] 我已经仔细阅读了你的问题,这里有更多的想法。我认为将当前的移动球与其他移动球分开会更好。所以你可以单独移动它们,但仍然可以完全绘制它们。此外,您还需要向Ball类添加check方法,以确定球是否被丢弃。

List<Ball> movingBalls = new ArrayList<Ball>();
List<Ball> allBalls = new ArrayList<Ball>();

Animation(int count) {
  balls = new ArrayList<Ball>();
  for (int i = 0; i < count; ++i) {
    Ball newBall = new Ball();

    allBalls.add(newBall);
    //all new balls are initially moving
    movingBalls.add(newBall);
  }
}

// Ball will roll down/left/right
public void actionPerformed(ActionEvent e) {       
    // we need to use new list here, because we can't add to movingBalls list, while iterating
    List<Ball> newBalls = new ArrayList<Ball>();

    //using iterators here, so we can remove balls, while iterating
    Iterator it = movingBalls.iterator()
    while (it.hasNext()) {
      Ball ball = it.next();

      int x = rand.nextInt(2);
      ball.rollDown();

      if (x == 0)
          ball.rollRight();
      else
          ball.rollLeft();

      ball.finalDescent();

      //now check if ball is dropped and create new one...
      if (ball.isDropped()) {
        //remove current ball from movingBalls list
        it.remove(); 

        //create new ball
        newBalls.add(new Ball());
      }
    }

    movingBalls.addAll(newBalls);
    allBalls.addAll(newBalls);

    repaint();
}

public void paintComponent(Graphics g)
  ...
  //paint as usual
  for (int i = 0; i < allBalls.length; ++i) {
    //this is probably what you've missed...
    allBalls[i].drawBall(g);
  }
}