views:

134

answers:

2

Hi folks, I'm learning Java, and I know one of the big complaints about newbie programmers is that we make really long and involved methods that should be broken into several. Well here is one I wrote and is a perfect example. :-D.

public void buildBall(){

        /* sets the x and y value for the center of the canvas */
        double i = ((getWidth() / 2));
        double j = ((getHeight() / 2));

        /* randomizes the start speed of the ball */
        vy = 3.0;
        vx = rgen.nextDouble(1.0, 3.0);
        if (rgen.nextBoolean(.05)) vx = -vx;    

        /* creates the ball */
        GOval ball = new GOval(i,j,(2 *BALL_RADIUS),(2 * BALL_RADIUS));     
        ball.setFilled(true);
        ball.setFillColor(Color.RED);
        add(ball);


        /* animates the ball */ 
        while(true){
            i = (i + (vx* 2));
            j = (j + (vy* 2));  
            if (i > APPLICATION_WIDTH-(2 * BALL_RADIUS)){
                vx = -vx;       
            }

            if (j > APPLICATION_HEIGHT-(2 * BALL_RADIUS)){
                vy = -vy;
            }

            if (i < 0){
                vx = -vx;
            }

            if (j < 0){
                vy = -vy;
            }

            ball.move(vx + vx, vy + vy);
            pause(10);

            /* checks the edges of the ball to see if it hits an object */
            colider = getElementAt(i, j);

            if (colider == null){
                colider = getElementAt(i + (2*BALL_RADIUS), j); 
                }
            if (colider == null){
                colider = getElementAt(i + (2*BALL_RADIUS), j + (2*BALL_RADIUS));   
                }
            if (colider == null){
                colider = getElementAt(i, j + (2*BALL_RADIUS)); 
                }

            /* If the ball hits an object it reverses direction */
            if (colider != null){
                vy = -vy;


             /* removes bricks when hit but not the paddle */
                if (j < (getHeight() -(PADDLE_Y_OFFSET + PADDLE_HEIGHT))){
                remove(colider);
                }

            }

        }

You can see from the title of the method that I started with good intentions of "building the ball".

There are a few issues I ran up against:

The problem is that then I needed to move the ball, so I created that while loop. I don't see any other way to do that other than just keep it "true", so that means any other code I create below this loop won't happen. I didn't make the while loop a different function because I was using those variables i and j.

So I don't see how I can refactor beyond this loop.

So my main question is:

How would I pass the values of i and j to a new method: "animateBall" and how would I use ball.move(vx + vx, vy + vy); in that new method if ball has been declared in the buildBall method?

I understand this is probably a simple thing of better understanding variable scope and passing arguments, but I'm not quite there yet...

+1  A: 

This is a bit less redundant

       colider = getElementAt(i, j);

           /* If the ball hits an object it reverses direction */

        if (colider != null && j < (getHeight() -(PADDLE_Y_OFFSET + PADDLE_HEIGHT)))
        {
            vy = -vy;

         /* removes bricks when hit but not the paddle */
            remove(colider);
         }


            else
            {
                colider = getElementAt(i + (2*BALL_RADIUS), j); 
                colider = getElementAt(i + (2*BALL_RADIUS), j + (2*BALL_RADIUS));  
                colider = getElementAt(i, j + (2*BALL_RADIUS));      
            }
Zaki
nice, thank you!
Joel
+3  A: 

This can be refactored into three methods a> build ball : create the ball object and set initial location: buildBall() b> animate the entire while loop except the collider part animate(Ball ball, vx, vy) c> get the collider getCollider()

Since ball is an object and you are already setting i,j as its fields they will be passed. Java passes all parameters by value. Objects live on the heap; object references are passed by value as method parameters.

Edit, added pseudo code

    class Animator{
    void animateBall(){
    Ball ball = buildBall(); //Ball will have i,j,radius etc set by this method
    int vx = randomNumber();
    int vy = randomNumber();
    moveIt(vx,vy, ball);
    }
    void moveIt(int vx, int vy, Ball ball){
        while(true){
             //move the ball, change i,j fields of ball
             //check for collission etc
             Collider collider = getCollider(ball);
             //change direction based on collider etc.
        }
    }
    Collider getCollider(Ball ball){
    //collision code here
    }
}
saugata
Right-I get the idea. My problem is 1) how do I pass the argument from build ball to animate ball, and 2) how does it reach the collider if the previous function is a while loop that never goes false?
Joel
@Joel, added some pseudo code, hope this helps
saugata
This helps a lot. Thanks for taking the time!
Joel
"Objects are passed by reference, not by value." - this is incorrect. Everything in Java is passed by value. In the case of objects, it's a reference that's passed by value. The object itself lives out on the heap and is not copied when passed to a method.
duffymo
@duffymo incorrect choice of words on my part :(, but I think/hope it gets the idea across.
saugata
I'd edit that response for posterity if you agree that it's incorrect.
duffymo