Euclid's Compass
Euclid's Compass

Reputation: 55

Having trouble displaying balls in the right position using Java and vector objects

I'm having issues with the balls that I display in my JFrame window. Here's the main idea of my application:

Point object (with coordinates x and y) --> Vector object (a class I wrote that has the x and y components of a vector, as well as a few methods... gets its location and head/tail points from the Point object) --> Ball object (the position, velocity, and acceleration vectors are collected in an ArrayList, also has radius and color attributes) --> ContainerBox object (contains the balls, defines the min/max x and y for collision detection purposes).

I'm working toward having one ball centered in the window and the other orbiting the first, but right now I'm just trying to get my objects to play nicely. I'm very new to OOP principles and this is the first time I've written a program using classes in this way.

Everything works perfectly, the JFrame comes up and displays the balls... the problem is that the balls won't show up in the right places. No matter what I put in for the x and y coordinates of the balls (either explicitly or using the objects), they always show up in the upper left-hand corner of the screen. Here's a pic of what I get: Picture Here

I don't know whether it's the vectors or the collision detection or what... any ideas? Thanks a lot for reading and replying!

EDIT: Here's some of the code that I'm using (sorry to put so much, I have no idea where the problem is):

EDIT AGAIN: Added the ball class that I forgot.

package chaneyBouncingBall;
import java.util.*;

public class Point
{
        float x;
    float y;    

    public Point(float x, float y)
    {
        this.x = x;
        this.y = y;
    }

}

package chaneyBouncingBall;
import java.util.ArrayList;

public class Chaney2DVector
{
    float x;
    float y;
    Point fromLocation;

    public Chaney2DVector(float x,
        float y)
    {
        this.x = x;
        this.y = y;

    }

    public Chaney2DVector(Point point1,
        Point point2)
    {
        fromLocation = new Point(point1.x, point1.y);
        this.x = point2.x - point1.x;
        this.y = point2.y - point1.y;

    }
}


package chaneyBouncingBall;
import java.awt.*;
import java.util.*;

public class Ball
{
    float x, y;
    float velX, velY;
    float accelX, accelY;
    float radius;
    private Color color;



    public Ball(float x, float y, float velX, 
        float velY, float accelX,
        float accelY, float radius, 
        Color color)
    {
        Chaney2DVector position = new Chaney2DVector(x, y);
        Chaney2DVector velocity = new Chaney2DVector(velX, velY);
        Chaney2DVector acceleration = new Chaney2DVector(accelX, accelY);

        ArrayList posVelAcc = new ArrayList();
        posVelAcc.add(position);
        posVelAcc.add(velocity);
        posVelAcc.add(acceleration);

        this.radius = radius;
        this.color = color;


    }


    public void draw(Graphics g)
    {
        g.setColor(color);
        g.fillOval((int)(x - radius), (int)(y - radius),
            (int)(2 * radius), (int)(2 * radius));
    }

    public void moveOneStepWithCollisionDetection( ContainerBox box)
    {
        float ballMinX = box.minX + radius;
        float ballMinY = box.minY + radius;
        float ballMaxX = box.maxX - radius;
        float ballMaxY = box.maxY - radius;

        x = x + velX;
        y = y + velY;

        if (x < ballMinX)
        {
            velX = -velX;
            x = ballMinX;
        }
        else if (x > ballMaxX)
        {
            velX = -velX;
            x = ballMaxX;
        }

        if (y < ballMinY)
        {
            velY = -velY;
            y = ballMinY;
        }
        else if (y > ballMaxY)
        {
            velY = -velY;
            y = ballMaxY;
        }
    }
}

package chaneyBouncingBall;
import java.awt.*;
/**
 * A rectangular container box, containing the bouncing ball.  
 */
public class ContainerBox {
   int minX, maxX, minY, maxY;  // Box's bounds (package access)
   private Color colorFilled;   // Box's filled color (background)
   private Color colorBorder;   // Box's border color
   private static final Color DEFAULT_COLOR_FILLED = Color.BLACK;
   private static final Color DEFAULT_COLOR_BORDER = Color.YELLOW;

   /** Constructors */
   public ContainerBox(int x, int y, int width, int height, Color colorFilled, Color colorBorder) {
      minX = x;
      minY = y;
      maxX = x + width - 1;
      maxY = y + height - 1;
      this.colorFilled = colorFilled;
      this.colorBorder = colorBorder;
   }

   /** Constructor with the default color */
   public ContainerBox(int x, int y, int width, int height) {
      this(x, y, width, height, DEFAULT_COLOR_FILLED, DEFAULT_COLOR_BORDER);
   }

   /** Set or reset the boundaries of the box. */
   public void set(int x, int y, int width, int height) {
      minX = x;
      minY = y;
      maxX = x + width - 1;
      maxY = y + height - 1;
   }

   /** Draw itself using the given graphic context. */
   public void draw(Graphics g) {
      g.setColor(colorFilled);
      g.fillRect(minX, minY, maxX - minX - 1, maxY - minY - 1);
      g.setColor(colorBorder);
      g.drawRect(minX, minY, maxX - minX - 1, maxY - minY - 1);
   }
}



package chaneyBouncingBall;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
/**
 * The control logic and main display panel for game.
 */
public class BallWorld extends JPanel {
   private static final int UPDATE_RATE = 50;  // Frames per second (fps)

   private Ball ball; // A single bouncing Ball's instance
   private Ball ball2;
   private ContainerBox box;  // The container rectangular box

   private DrawCanvas canvas; // Custom canvas for drawing the box/ball
   private int canvasWidth;
   private int canvasHeight;

   /**
    * Constructor to create the UI components and init the game objects.
    * Set the drawing canvas to fill the screen (given its width and height).
    * 
    * @param width : screen width
    * @param height : screen height
    */
   public BallWorld(int width, int height) {

      canvasWidth = width;
      canvasHeight = height;

boolean stationary = true;
      Random rand = new Random();
      int angleInDegree = rand.nextInt(360);
      int radius = 50;
      int radius2 = 25;
//      double accelAngle;
      float x1 = rand.nextInt(canvasWidth - radius * 2 - 20) + radius + 10;
      float y1 = rand.nextInt(canvasHeight - radius * 2 - 20) + radius + 10;
      float x2 = rand.nextInt(canvasWidth - radius * 2 - 20) + radius + 10;
      float y2 = rand.nextInt(canvasHeight - radius * 2 - 20) + radius + 10;
//      float x = 100;
//      float y = 100;
      float velX1 = 0;
      float velY1 = 0;
      float accelX1 = 0;
      float accelY1 = 0;
      float velX2 = 0;
      float velY2 = 0;
      float accelX2 = 0;
      float accelY2 = 0;

ball = new Ball(canvasWidth / 2, canvasHeight / 2, velX1, velY1, accelX1, accelY1, 
              radius, Color.BLUE);
      ball2 = new Ball(x2, y2, velX2, velY2, accelX2, accelY2, radius / 5,         Color.YELLOW);
      // Init the Container Box to fill the screen
      box = new ContainerBox(0, 0, canvasWidth, canvasHeight, Color.BLACK,         Color.WHITE);

      // Init the custom drawing panel for drawing the game
      canvas = new DrawCanvas();
      this.setLayout(new BorderLayout());
      this.add(canvas, BorderLayout.CENTER);

      // Handling window resize.
      this.addComponentListener(new ComponentAdapter() {
         @Override
         public void componentResized(ComponentEvent e) {
            Component c = (Component)e.getSource();
            Dimension dim = c.getSize();
            canvasWidth = dim.width;
            canvasHeight = dim.height;
            // Adjust the bounds of the container to fill the window
            box.set(0, 0, canvasWidth, canvasHeight);
         }
      });

      // Start the ball bouncing
      gameStart();
   }

   /** Start the ball bouncing. */
   public void gameStart() {
      // Run the game logic in its own thread.
      Thread gameThread = new Thread() {
         public void run() {
            while (true) {
               // Execute one time-step for the game 
           gameUpdate();
               // Refresh the display
               repaint();
               // Delay and give other thread a chance
               try {
                  Thread.sleep(1000 / UPDATE_RATE);
               } catch (InterruptedException ex) {}
            }
         }
      };
      gameThread.start();  // Invoke GaemThread.run()
   }

   /** 
    * One game time-step. 
    * Update the game objects, with proper collision detection and response.
    */
   public void gameUpdate() {
      ball.moveOneStepWithCollisionDetection(box);
      ball2.moveOneStepWithCollisionDetection(box);
   }

   /** The custom drawing panel for the bouncing ball (inner class). */
   class DrawCanvas extends JPanel {
      /** Custom drawing codes */
      @Override
      public void paintComponent(Graphics g) {
         super.paintComponent(g);    // Paint background
         // Draw the box and the ball
         box.draw(g);
         ball.draw(g);
         ball2.draw(g);
         // Display ball's information
         g.setColor(Color.WHITE);
         g.setFont(new Font("Courier New", Font.PLAIN, 12));
    //         g.drawString("Ball " + ball.toString(), 20, 30);
      }

      /** Called back to get the preferred size of the component. */
      @Override
      public Dimension getPreferredSize() {
         return (new Dimension(canvasWidth, canvasHeight));
      }
   }
}

package chaneyBouncingBall;
import javax.swing.JFrame;

public class Main
{
        public static void main(String[] args)
        {
            javax.swing.SwingUtilities.invokeLater(new Runnable()
            {
            public void run()
            {
            JFrame frame = new JFrame("Matt Chaney's Gravity App");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setContentPane(new BallWorld(550, 450));
            frame.pack();
            frame.setVisible(true);
            }
            });
        }
}

Upvotes: 2

Views: 494

Answers (1)

jpdymond
jpdymond

Reputation: 1612

In the constructor of your Ball class, you don't assign all the instance variables to their parameters, these need to be added.

public Ball(float x, float y, float velX, float velY, float accelX, float accelY, float radius, Color color) {

...

this.x = x;
this.y = y;

this.velX = velX;
this.velY = velY;

this.accelX = accelX;
this.accelY = accelY;

}

Upvotes: 1

Related Questions