Reputation: 27
I am trying to move two spheres simultaneously on screen. However, they are not moving independent of each other. Instead one is dependent on the other's movement. Please help me out. This is the code :-
Draw
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Draw extends JPanel implements ActionListener
{
Timer timer[] = new Timer[2];
int velX = 2, velY = 2;
Sphere sphere[] = new Sphere[2];
public Draw()
{
for(int i=0;i<2;i++)
{
sphere[i] = new Sphere();
timer[i] = new Timer(5,this);
}
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
for(int i=0;i<2;i++)
drawing(g,sphere[i].color,sphere[i].radius);
}
public void drawing(Graphics g,Color color, int radius)
{
for(int i=0;i<2;i++){
g.setColor(color);
g.fillOval(sphere[i].x,sphere[i].y,radius*2,radius*2);
timer[i].start();
}
}
public void actionPerformed(ActionEvent evt)
{
for(int i=0;i<2;i++){
if(sphere[i].x<0 || sphere[i].x>970)
{
velX = -velX;
}
if(sphere[i].y<0 || sphere[i].y>650)
{
velY = -velY;
}
sphere[i].x += velX;
sphere[i].y += velY;
repaint();
}
}
public static void main(String args[])
{
JFrame jf = new JFrame("Renderer");
jf.getContentPane().add(new Draw(),BorderLayout.CENTER);
jf.setBounds(0,0,1024,720);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
}
Sphere
import java.awt.Color;
class Sphere
{
public int x;
public int y;
public int radius;
Color color;
public Sphere()
{
this.x = (int)(Math.random()*800);
this.y = (int)(Math.random()*600);
this.radius = (int)(Math.random()*50);
this.color = new Color((int)(Math.random()*255),
(int)(Math.random()*255),(int)(Math.random()*255));
}
public Sphere(int x,int y,int radius, Color color)
{
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
}
}
Upvotes: 0
Views: 81
Reputation: 347214
Your x/y delta is the same for both objects, you need to contain these values within the Sphere
object, for example
class Sphere {
int velX;
int velY;
public int x;
public int y;
public int radius;
Color color;
public Sphere(int xDelta, int yDelta) {
velX = xDelta;
velY = yDelta;
this.x = (int) (Math.random() * 800);
this.y = (int) (Math.random() * 600);
this.radius = (int) (Math.random() * 50);
this.color = new Color((int) (Math.random() * 255),
(int) (Math.random() * 255), (int) (Math.random() * 255));
}
void move(Dimension size) {
x += velX;
y += velY;
if (x < 0) {
x = 0;
velX *= -1;
} else if (x + (radius * 2) > size.width) {
x = size.width - (radius * 2);
velX *= -1;
}
if (y < 0) {
y = 0;
velY *= -1;
} else if (y + (radius * 2) > size.height) {
y = size.height - (radius * 2);
velY *= -1;
}
}
public Sphere(int x, int y, int radius, Color color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
}
}
Then, in your actionPerformed
method, you simply call update...
@Override
public void actionPerformed(ActionEvent evt) {
for (int i = 0; i < 2; i++) {
sphere[i].move(getSize());
}
repaint();
}
Additionally, you don't need two Timer
s, you only need one, which can be used to update both sphere's each time it's ticked...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
class Draw extends JPanel implements ActionListener {
Timer timer;
Sphere sphere[] = new Sphere[2];
public Draw() {
Random rnd = new Random();
for (int i = 0; i < 2; i++) {
sphere[i] = new Sphere(rnd.nextInt(4) + 1, rnd.nextInt(4) + 1);
}
timer = new Timer(16, this);
timer.start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < 2; i++) {
drawing(g, sphere[i].color, sphere[i].radius);
}
}
public void drawing(Graphics g, Color color, int radius) {
for (int i = 0; i < 2; i++) {
g.setColor(color);
g.fillOval(sphere[i].x, sphere[i].y, radius * 2, radius * 2);
}
}
@Override
public void actionPerformed(ActionEvent evt) {
for (int i = 0; i < 2; i++) {
sphere[i].move(getSize());
}
repaint();
}
public static void main(String args[]) {
JFrame jf = new JFrame("Renderer");
jf.getContentPane().add(new Draw(), BorderLayout.CENTER);
jf.setBounds(0, 0, 1024, 720);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
class Sphere {
int velX;
int velY;
public int x;
public int y;
public int radius;
Color color;
public Sphere(int xDelta, int yDelta) {
velX = xDelta;
velY = yDelta;
this.x = (int) (Math.random() * 800);
this.y = (int) (Math.random() * 600);
this.radius = (int) (Math.random() * 50);
this.color = new Color((int) (Math.random() * 255),
(int) (Math.random() * 255), (int) (Math.random() * 255));
}
void move(Dimension size) {
x += velX;
y += velY;
if (x < 0) {
x = 0;
velX *= -1;
} else if (x + (radius * 2) > size.width) {
x = size.width - (radius * 2);
velX *= -1;
}
if (y < 0) {
y = 0;
velY *= -1;
} else if (y + (radius * 2) > size.height) {
y = size.height - (radius * 2);
velY *= -1;
}
}
public Sphere(int x, int y, int radius, Color color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
}
}
}
Also, you shouldn't be starting the timers in the "paint" pass, they should be started before hand
Upvotes: 3
Reputation: 6721
Move the velX
and velY
into the Sphere
class. So each Sphere
will maintain its own velocity. Then the spheres will move independent of each other.
There is no need of two Timer
s. I've cleaned it up.
I also cleaned up the paintComponent
method. No need of loops in two places.
Here's what I tried and it seems to work for me:
public class Draw extends JPanel implements ActionListener {
Sphere sphere[] = new Sphere[2];
public Draw() {
for (int i = 0; i < 2; i++) {
sphere[i] = new Sphere();
}
Timer timer = new Timer(5, this);
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
drawing(g);
}
public void drawing(Graphics g) {
for (int i = 0; i < 2; i++) {
g.setColor(sphere[i].color);
g.fillOval(sphere[i].x, sphere[i].y, sphere[i].radius * 2, sphere[i].radius * 2);
}
}
public void actionPerformed(ActionEvent evt) {
for (int i = 0; i < 2; i++) {
if (sphere[i].x < 0 || sphere[i].x > 970) {
sphere[i].velX = -sphere[i].velX;
}
if (sphere[i].y < 0 || sphere[i].y > 650) {
sphere[i].velY = -sphere[i].velY;
}
sphere[i].x += sphere[i].velX;
sphere[i].y += sphere[i].velY;
repaint();
}
}
public static void main(String args[]) {
JFrame jf = new JFrame("Renderer");
jf.getContentPane().add(new Draw(), BorderLayout.CENTER);
jf.setBounds(0, 0, 1024, 720);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
}
class Sphere {
public int x;
public int y;
public int radius;
Color color;
int velX;
int velY;
public Sphere() {
this.x = (int) (Math.random() * 800);
this.y = (int) (Math.random() * 600);
this.radius = (int) (Math.random() * 50);
this.color = new Color((int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255));
velX = new Random().nextInt()%5 + 2;
velY = new Random().nextInt()%5 + 2;
}
public Sphere(int x, int y, int radius, Color color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
}
}
Hope this helps!
Upvotes: 2
Reputation: 867
Both Spheres share the same speed, so their movements will be similar.
int velX = 2, velY = 2;
If in the Sphere creation you set a random speed for each of them the movement will be different.
Upvotes: 2