I have a problem.
I am a beginner with java, and succeeded up to this point. Add bubbles with random sizes.
Now I need to make the bubbles escaping mouse when he gets near them.
Can anyone give me a hint how?
Thank you.
public class BounceBall extends JFrame {
private ShapePanel drawPanel;
private Vector<NewBall> Balls;
private JTextField message;
// set up interface
public BounceBall() {
super("MultiThreading");
drawPanel = new ShapePanel(400, 345);
message = new JTextField();
message.setEditable(false);
Balls = new Vector<NewBall>();
add(drawPanel, BorderLayout.NORTH);
add(message, BorderLayout.SOUTH);
setSize(400, 400);
setVisible(true);
}
public static void main(String args[]) {
BounceBall application = new BounceBall();
application.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
private class NewBall extends Thread {
private Ellipse2D.Double thisBall;
private boolean ballStarted;
private int size, speed; // characteristics
private int deltax, deltay; // of the ball
public NewBall() {
ballStarted = true;
size = 10 + (int) (Math.random() * 60);
speed = 10 + (int) (Math.random() * 100);
int startx = (int) (Math.random() * 300);
int starty = (int) (Math.random() * 300);
deltax = -10 + (int) (Math.random() * 21);
deltay = -10 + (int) (Math.random() * 21);
if ((deltax == 0) && (deltay == 0)) {
deltax = 1;
}
thisBall = new Ellipse2D.Double(startx, starty, size, size);
}
public void draw(Graphics2D g2d) {
if (thisBall != null) {
g2d.setColor(Color.BLUE);
g2d.fill(thisBall);
}
}
public void run() {
while (ballStarted) // Keeps ball moving
{
try {
Thread.sleep(speed);
} catch (InterruptedException e) {
System.out.println("Woke up prematurely");
}
// calculate new position and move ball
int oldx = (int) thisBall.getX();
int oldy = (int) thisBall.getY();
int newx = oldx + deltax;
if (newx + size > drawPanel.getWidth() || newx < 0) {
deltax = -deltax;
}
int newy = oldy + deltay;
if (newy + size > drawPanel.getHeight() || newy < 0) {
deltay = -deltay;
}
thisBall.setFrame(newx, newy, size, size);
drawPanel.repaint();
}
}
}
private class ShapePanel extends JPanel {
private int prefwid, prefht;
public ShapePanel(int pwid, int pht) {
prefwid = pwid;
prefht = pht;
// add ball when mouse is clicked
addMouseListener(
new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
NewBall nextBall = new NewBall();
Balls.addElement(nextBall);
nextBall.start();
message.setText("Number of Balls: " + Balls.size());
}
});
}
public Dimension getPreferredSize() {
return new Dimension(prefwid, prefht);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (int i = 0; i < Balls.size(); i++) {
(Balls.elementAt(i)).draw(g2d);
}
}
}
}
You should not have a Thread for each individual ball, this will not scale well, the more balls you add, the more threads you add. At some point, the amount of work it takes to manage the threads will exceed the benefit for using multiple threads...
Also, I doubt if your need 1000fps...something like 25fps should be more than sufficient for your simple purposes. This will give the system some breathing room and allow other threads within the system time to execute.
Lets start with a simple concept of a Ball. The Ball knows where it is and which direction it is moving it, it also knows how to paint itself, for example...
public class Ball {
private int x;
private int y;
private int deltaX;
private int deltaY;
private int dimeter;
private Ellipse2D ball;
private Color color;
public Ball(Color color, Dimension bounds) {
this.color = color;
Random rnd = new Random();
dimeter = 5 + rnd.nextInt(15);
x = rnd.nextInt(bounds.width - dimeter);
y = rnd.nextInt(bounds.height - dimeter);
if (x < 0) {
x = 0;
}
if (y < 0) {
y = 0;
}
int maxSpeed = 10;
do {
deltaX = rnd.nextInt(maxSpeed) - (maxSpeed / 2);
} while (deltaX == 0);
do {
deltaY = rnd.nextInt(maxSpeed) - (maxSpeed / 2);
} while (deltaY == 0);
ball = new Ellipse2D.Float(0, 0, dimeter, dimeter);
}
public void update(Dimension bounds) {
x += deltaX;
y += deltaY;
if (x < 0) {
x = 0;
deltaX *= -1;
} else if (x + dimeter > bounds.width) {
x = bounds.width - dimeter;
deltaX *= -1;
}
if (y < 0) {
y = 0;
deltaY *= -1;
} else if (y + dimeter > bounds.height) {
y = bounds.height - dimeter;
deltaY *= -1;
}
}
public void paint(Graphics2D g2d) {
g2d.translate(x, y);
g2d.setColor(color);
g2d.fill(ball);
g2d.translate(-x, -y);
}
}
Next, we need somewhere for the balls to move within, some kind of BallPit for example...
public class BallPit extends JPanel {
private List<Ball> balls;
public BallPit() {
balls = new ArrayList<>(25);
balls.add(new Ball(Color.RED, getPreferredSize()));
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Ball ball : balls) {
ball.update(getSize());
}
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
for (Ball ball : balls) {
ball.paint(g2d);
}
g2d.dispose();
}
}
This maintains a list of balls, tells them when the need to update and when the need to paint. This example uses a simple javax.swing.Timer, which acts as the central timer which updates the balls and schedules the repaints.
The reason for this is takes care of synchronisation between the updates and the paints, meaning that the balls won't be updating while they are been painted. This is achieved because javax.swing.Timer triggers it's callbacks within the context of the EDT.
See Concurrency in Swing and How to use Swing Timers for more details.
Okay, so that fixes the threading issues, but what about the mouse avoidance...
That's a little more complicated...
What we need to is add a MouseMoitionListener to the BillPit and record the last position of the mouse.
public class BallPit extends JPanel {
//...
private Point mousePoint;
//...
public BallPit() {
//...
MouseAdapter handler = new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
mousePoint = e.getPoint();
}
#Override
public void mouseExited(MouseEvent e) {
mousePoint = null;
}
};
addMouseListener(handler);
addMouseMotionListener(handler);
//...
The reason for including mouseExit is to ensure that balls don't try and move away from a phantom mouse cursor...
Next, we need to update Ball to have an "area of effect", this is the area around the ball that will trigger a change in movement if the mouse cursor moves within it's range...
public class Ball {
//...
private final Ellipse2D.Float areaOfEffect;
public Ball(Color color, Dimension bounds) {
//...
areaOfEffect = new Ellipse2D.Float(-10, -10, dimeter + 20, dimeter + 20);
}
Now, I also add some additional painting for debug reasons...
public void paint(Graphics2D g2d) {
g2d.translate(x, y);
g2d.setColor(new Color(0, 0, 192, 32));
g2d.fill(areaOfEffect);
g2d.setColor(color);
g2d.fill(ball);
g2d.translate(-x, -y);
}
Next, we need to modify the Ball's update method to accept the mousePoint value...
public void update(Dimension bounds, Point mousePoint) {
PathIterator pathIterator = areaOfEffect.getPathIterator(AffineTransform.getTranslateInstance(x, y));
GeneralPath path = new GeneralPath();
path.append(pathIterator, true);
if (mousePoint != null && path.contains(mousePoint)) {
// Determine which axis is closes to the cursor...
int xDistance = Math.abs(x + (dimeter / 2) - mousePoint.x);
int yDistance = Math.abs(y + (dimeter / 2) - mousePoint.y);
if (xDistance < yDistance) {
// If x is closer, the change the delatX
if (x + (dimeter / 2) < mousePoint.x) {
if (deltaX > 0) {
deltaX *= -1;
}
} else {
if (deltaX > 0) {
deltaX *= -1;
}
}
} else {
// If y is closer, the change the deltaY
if (y + (dimeter / 2) < mousePoint.y) {
if (deltaY > 0) {
deltaY *= -1;
}
} else {
if (deltaY > 0) {
deltaY *= -1;
}
}
}
}
//...Rest of previous method code...
}
Basically, what this is trying to do is determine which axis is closer to the mouse point and in which direction the ball should try and move...it's a little "basic", but gives the basic premise...
Lastly, we need to update the "update" loop in the javax.swing.Timer to supply the additional parameter
for (Ball ball : balls) {
ball.update(getSize(), mousePoint);
}
I'm going to answer this, but I'm very close to issuing a close vote because it doesn't show what you've done so far to attempt this. I would not be surprised if others are closer to the edge than I am on this. At the same time, you've clearly shown your progress before you reached this point, so I'll give you the benefit of the doubt. In the future, I would strongly advise making an attempt and then posting a question that pertains to the specific problem you're having while making that attempt.
You need two things:
The current location of the mouse
A range check and reversal of direction if too close.
The location of the mouse can be achieved by adding two variables (x and y) and, every time the mouse is moved (so add a mouse event listener to your JPanel or something) update those variables with the new location.
Then, you can do a range check (think Pythagorean theorem) on each bubble to make sure they're far enough away. If the bubble is too close, you'll want to check where that bubble would end up if it carried on its current course, as well as where it would end up if it changed X direction, Y direction, or both. Pick the one that ends up being furthest away and set the deltax and deltay to those, and let the calculation carry on as normal.
It sounds like a lot, but those are the two basic components you need to achieve this.
Related
I trying to animate 50 bouncing dots with different colours. I am able to make the dots move but the dots drag on like it is being painted. I do not know why it turned to be like this
This is my codes for DotsPanel:
public DotsPanel(){
frameSize = 300;
setBounds (100, 100,frameSize,frameSize );
setPreferredSize (new Dimension(frameSize, frameSize));
setVisible(true);
x = 0;
y = 40;
moveX = moveY = 3;
for (int i = 0; i < dot.length; i++)
{
dot[i] = new Dot (frameSize, frameSize);
}
timer = new Timer(DELAY, new TimerListener());
timer.start();
}
private class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
for (int i = 0; i < dot.length; i++)
{
dot[i].animate();
}
repaint();
}
}
public void paintComponent(Graphics g){
for (int i = 0; i < dot.length; i++)
{
dot[i].draw(g);
}
}
public void run ()
{
while(true)
{
for (int i = 0; i < dot.length; i++)
{
dot[i].animate();
}
repaint();
}
}
This is the Dot class:
public Dot(int width, int height) {
this.width = width;
this.height = height;
x = r.nextInt(width - d);
y = r.nextInt(height - d);
speed = r.nextInt(10);
red = r.nextInt(256);
green = r.nextInt(256);
blue = r.nextInt(256);
moveX = moveY = 3;
}
public void animate ()
{
x += moveX;
y += moveY;
if (x <= 0 || x >= 300)
moveX = moveX * -1;
if (y <= 0 || y >= 300)
moveY = moveY * -1;
}
public void draw(Graphics g) {
g.setColor(new Color(red, green, blue));
//g.setColor(Color.BLUE);
g.fillOval(x, y, d, d);
}
I do not know which part went wrong. I am guessing is the draw method. I tried using paint instead of paintComponent but still the same result. And if i remove the while loop, the dots do not animate, I did this according to a tutorial i seen in youtube, the tutorial works well though.
Well, I guess it's simply because you don't "clear" the previous drawing each time a new one is drawn. As a result, you see all your previous graphics being continuously stacked !
EDIT (correct solution by camickr in comments below) :
The solution is to invoke super.paintComponent(g) at the top of the method to invoke the default painting functionality, which for a JPanel, will paint the background for you.
I'm trying to learn how to make a 2D Game without Game Engines, anyways I already created a background scrolling right now my goal is to make my character jump. But the thing is whenever I start my app the character is spinning up and down and it will just go away to the background.
Here's my character code
public class Deer extends GameCharacter {
private Bitmap spritesheet;
private double dya;
private boolean playing;
private long startTime;
private boolean Jump;
private Animate Animation = new Animate();
public Deer(Bitmap res, int w, int h, int numFrames) {
x = 20;
y = 400;
dy = 0;
height = h;
width = w;
Bitmap[] image = new Bitmap[numFrames];
spritesheet = res;
for (int i = 0; i < image.length; i++)
{
image[i] = Bitmap.createBitmap(spritesheet, i*width, 0, width, height);
}
Animation.setFrames(image);
Animation.setDelay(10);
startTime = System.nanoTime();
}
public void setJump(boolean b){
Jump = b;
}
public void update()
{
long elapsed = (System.nanoTime()-startTime)/1000000;
if(elapsed>100)
{
}
Animation.update();
if(Jump){
dy = (int)(dya+=5.5);
}
else{
dy = (int)(dya+=5.5);
}
if(dy>14)dy = 14;
if(dy>14)dy = -14;
y += dy*2;
dy = 0;
}
public void draw(Canvas canvas)
{
canvas.drawBitmap(Animation.getImage(),x,y,null);
}
public boolean getPlaying(){return playing;}
public void setPlaying(boolean b){playing = b;}
public void resetDYA(){dya = 0;}
}
x - character's horizontal position
y - character's vertical position
dx - character's horizontal acceleration
dy - character's vertical acceleration
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN) {
if(!deer.getPlaying()) {
deer.setPlaying(true);
}
deer.setJump(true);
return true;
}
return super.onTouchEvent(event);
}
I can't say for sure if this is the only problem because you have other suspicious code but it looks like you jump no matter what.
if(Jump){
dy = (int)(dya+=5.5);
} else {
dy = (int)(dya+=5.5);
}
If Jump is true you set the vertical acceleration. But you also set the vertical acceleration to the same value if Jump is false. You also don't show in your code where Jump is ever set to false.
Another odd bit of code is:
if(dy>14)dy = 14;
if(dy>14)dy = -14;
Here, if dy>14 you set it to 14. Then you check dy>14 immediately after. Of course, this time it's false. But because those two conditions are the same the second one will never pass since the one before it ensures it won't. The only other option is they both fail. IOW, you'll never be able to enter the second if.
All that aside, I'm not sure why you're taking this approach. You can simply rely on physics equations with constant acceleration, give an initial velocity, check for a collision with the ground (or at least the original height), and just let it run. For example:
// These are the variables you need.
int x = 200, y0 = 0, y = 0, velocity = 15;
double t = 0.0, gravity = -9.8;
// This is the statement that should run when you update the GUI.
// It is the fundamental equation for motion with constant acceleration.
// The acceleration is the gravitational constant.
y = (int) (y0 + velocity * t + .5 * gravity * t * t);
if (y < 0) {
y = y0 = 0;
//Stop jumping!
Jump = false;
} else {
// Swap the y values.
y0 = y;
// Increase the time with the frame rate.
t += frameRate;
}
// Draw the character using the y value
The best part about this is you don't need to worry about when you get to the maximum height because the equation will automatically bring you down. It also looks more natural as if the mechanics are real. Try it out.
A simple Swing example that you can play around with. Note that the values are different to deal with the way the components are drawn to the screen. Normally, you would deal with that with transformations but this will do for the task.
public class Main {
static Timer timer;
Main() {
JFrame frame = new JFrame("Hello sample");
frame.setSize(new Dimension(550, 550));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel panel = new MyPanel();
frame.add(panel);
frame.setVisible(true);
timer = new Timer(5, (e) -> panel.repaint());
timer.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(Main::new);
}
class MyPanel extends JPanel {
int x = 200, y0 = 300, y = 0, w = 200, h = 200, v = -8;
double t = 0.0, gravity = 9.8;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
y = (int) (y0 + v * t + .5 * gravity * t * t);
if (y > 300) {
y = y0 = 300;
// To prevent it from stopping comment the timer.stop() and
// uncomment the t = 0.0 statements.
//t = 0.0;
timer.stop();
} else {
y0 = y;
t += .025;
}
g.drawOval(x, y, w, h);
}
}
}
I have been working on this java application.
So far it has no meaning, just a randomly colored ball bouncing around.
But now, when i wanted to add another ball to the bouncing app, the balls followed each other.
This is my code so far.
import java.awt.*;
import javax.swing.*;
public class MainFrame extends JPanel implements Runnable {
Color color = Color.red;
int dia = 60;
Diameter of the objects.
long delay = 20;
Delay time.
private int x = (int)Math.floor(Math.random() * 580);
private int y = (int)Math.floor(Math.random() * 900);
private int xx = (int)Math.floor(Math.random() * 580);
private int yy = (int)Math.floor(Math.random() * 900);
Above is the objects position.
private int dx = (int)Math.floor(Math.random() * 7);
private int dy = (int)Math.floor(Math.random() * 7);
private int dxx = (int)Math.floor(Math.random() * 7);
private int dyy = (int)Math.floor(Math.random() * 7);
Above is object speed.
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
g.fillOval(x,y,60,60);
g.setColor(color);
g.fillOval(xx,yy,60,60);
}
The graphics.
And below is just calculations, thread.sleep and the JFrame.
public void run() {
while(isVisible()) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move();
repaint();
}
}
public void move() {
if(x + dx < 0 || x + dia + dx > getWidth()) {
dx *= -1;
color = getColor();
}
if(y + dy < 0 || y + dia + dy > getHeight()) {
dy *= -1;
color = getColor();
}
if(xx + dxx < 0 || xx + dia + dxx > getWidth()) {
dxx *= -1;
color = getColor();
}
if(yy + dyy < 0 || yy + dia + dyy > getHeight()) {
dyy *= -1;
color = getColor();
}
x += dx;
y += dy;
xx += dx;
yy += dy;
}
private Color getColor() {
int rval = (int)Math.floor(Math.random() * 256);
int gval = (int)Math.floor(Math.random() * 256);
int bval = (int)Math.floor(Math.random() * 256);
return new Color(rval, gval, bval);
}
private void start() {
while(!isVisible()) {
try {
Thread.sleep(25);
} catch(InterruptedException e) {
System.exit(1);
}
}
Thread thread = new Thread(this);
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
public static void main(String[] args) {
MainFrame test = new MainFrame();
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(test);
f.setSize(640, 960);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
f.setLocation(dim.width/2-f.getSize().width/2, dim.height/2-f.getSize().height/2);
f.setVisible(true);
test.start();
}
}
I just can not figure it out.
I know the answer is going to be simple.
You should define a single class Ball and create two instances of it rather than repeating the variables and have an x,y co-ordinate and velocity dx and dy inside that class.
The two follow each other ebcause you add the same velocity to both balls all the time:
x += dx;
y += dy;
xx += dx;
yy += dy;
I am trying to make a stoplight that performs certain tasks after a button is clicked. What this stoplight is supposed to do is change from green to yellow after 50 secs, from yellow to red after 10 secs, and from red to green after 60 secs (this part I have working fine), and if the button is pressed when it is green it should change to yellow, this should only work after 10 secs have at least passed while green. What I have a problem is how do I check if 10 secs have passed or not?
public class Stoplight extends Applet
{
Button cross;
public void init(){
cross = new Button("Cross");
add(cross);
StoplightCanvas stoplightCanvas = new StoplightCanvas(cross);
add(stoplightCanvas);
new StoplightThread(stoplightCanvas).start();
}
}
class StoplightCanvas extends Canvas implements ActionListener
{
int Xpos;
int Ypos;
int diameter;
Button cross;
int x = 1;
StoplightCanvas(Button cross)
{
this.cross = cross;
cross.addActionListener(this);
setSize(300, 600);
}
public void paint(Graphics g)
{
diameter = 70;
Xpos = 70;
Ypos = 50;
g.setColor(Color.BLUE);
g.fillRect(70, 50, 74, 220);
g.setColor(Color.WHITE);
if (x == 1)
g.setColor(Color.RED);
drawCircles(g, Xpos, Ypos);
g.setColor(Color.WHITE);
if (x == 2)
g.setColor(Color.YELLOW);
drawCircles(g, Xpos, Ypos + diameter);
g.setColor(Color.WHITE);
if (x == 3)
g.setColor(Color.GREEN);
drawCircles(g, Xpos, Ypos + diameter * 2);
}
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == cross) {
}
repaint();
}
void drawCircles(Graphics g, int x, int y)
{
g.fillOval(x, y, diameter, diameter);
}
public void toggleColor() {
if (x == 1)
x = 3;
else if (x == 2)
x = 1;
else if (x == 3)
x = 2;
}
}
class StoplightThread extends Thread
{
StoplightCanvas stoplightCanvas;
StoplightThread(StoplightCanvas stoplightCanvas) {
this.stoplightCanvas = stoplightCanvas;
}
public void run()
{
while (true) {
try {
if (stoplightCanvas.x == 3){
Thread.sleep(50000);
} else if (stoplightCanvas.x == 2) {
Thread.sleep(10000);
} else if (stoplightCanvas.x == 1) {
Thread.sleep(60000);
}
} catch (InterruptedException e){}
stoplightCanvas.toggleColor();
stoplightCanvas.repaint();
}
}
}
You can set a timer when they press the button for 10 seconds. When that time expires, then change the color to yellow via the callback. It is much better than dealing with exceptions, because they should be for exceptional circumstances.
See this thread on how to set a timer for later.
Edit
The poster wishes to not use timers. One way would be to store the time when the button is pressed in a variable, then access that variable and compare against the current time within the while loop of the run method.
sorry to keep asking questions about my program but i think i'm nearly there and i'm teaching myself java so please bear with me. I'm creating an applet that moves sheep object across the screen in a random direction when a dog object moves close to the sheep. Getting the sheep to move in a random direction took some work and with the help of you guys on here it now works (sort of) but what I'm trying to do now is stop it from flickering when i drag objects across the screen. I've read about double buffering, I can get it to work for items drawn in the paint method of a main class but cant get it to work for my sheep and dog objects which are defined as separate objects in separate classes. Any help will be much appreciated. Here is my code:
package mandAndDog;
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class SheepDog extends Applet implements ActionListener, MouseListener, MouseMotionListener
{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
*
*/
Dog dog;
Sheep sheep;
int[] directionNumbersLeft = {0, 1, 3};
int[] directionNumbersUp = {0, 1, 2};
int x;
int selection;
int xposR;
int yposR;
int sheepx;
int sheepy;
int sheepBoundsx;
int sheepBoundsy;
int MAX_DISTANCE = 50;
int direction;
int distance;
Boolean sheepisclosetodog;
public void init()
{
addMouseListener(this);
addMouseMotionListener(this);
dog = new Dog(10, 10);
sheepx = 175;
sheepy = 75;
sheep = new Sheep(sheepx, sheepy);
sheepBoundsx = 30;
sheepBoundsy = 30;
direction = (int)(Math.random()*4);
distance = (int) (Math.random() * MAX_DISTANCE) % MAX_DISTANCE;
sheepisclosetodog = false;
Random rand = new Random();
x = rand.nextInt(3);
selection = directionNumbersLeft[x];
}
public void paint(Graphics g)
{
dog.display(g);
sheep.display(g);
g.drawString(Integer.toString(distance), 85, 100);
g.drawString(Integer.toString(direction), 85, 125);
g.drawString(Integer.toString(selection), 85, 140);
}
public void actionPerformed(ActionEvent ev)
{}
public void mousePressed(MouseEvent e)
{}
public void mouseReleased(MouseEvent e)
{}
public void mouseEntered(MouseEvent e)
{}
public void mouseExited(MouseEvent e)
{}
public void mouseMoved(MouseEvent e)
{
}
public void mouseClicked(MouseEvent e)
{}
public void mouseDragged(MouseEvent e)
{
dog.setLocation(xposR, yposR);
sheep.setLocation(sheepx, sheepy);
if (xposR > (sheepx - 20)&& xposR < (sheepx - 20)+(sheepBoundsx - 20) && yposR > (sheepy - 20)
&& yposR < (sheepy - 20)+(sheepBoundsy - 20) && direction == 0){
sheepx = sheepx + 50;
direction = (int)(Math.random()*4);
}
if (xposR > (sheepx - 20)&& xposR < (sheepx - 20)+(sheepBoundsx - 20) && yposR > (sheepy - 20)
&& yposR < (sheepy - 20)+(sheepBoundsy - 20) && direction == 1){
sheepy = sheepy + 50;
direction = (int)(Math.random()*4);
}
if (xposR > (sheepx - 20)&& xposR < (sheepx - 20)+(sheepBoundsx - 20) && yposR > (sheepy - 20)
&& yposR < (sheepy - 20)+(sheepBoundsy - 20) && direction == 2){
sheepx = sheepx - 50;
direction = (int)(Math.random()*4);
}
if (sheepx <= 5){
direction = directionNumbersLeft[x];
}
if (xposR > (sheepx - 20)&& xposR < (sheepx - 20)+(sheepBoundsx - 20) && yposR > (sheepy - 20)
&& yposR < (sheepy - 20)+(sheepBoundsy - 20) && direction == 3){
sheepy = sheepy - 50;
direction = (int)(Math.random()*4);
}
if (sheepy <=5){
direction = directionNumbersUp[x];
}
xposR = e.getX();
yposR = e.getY();
repaint();
}
}
class Dog
{
int xpos;
int ypos;
int circleWidth = 30;
int circleHeight = 30;
public Dog(int x, int y)
{
xpos = x;
ypos = y;
}
public void setLocation(int lx, int ly)
{
xpos = lx;
ypos = ly;
}
public void display(Graphics g)
{
g.setColor(Color.blue);
g.fillOval(xpos, ypos, circleWidth, circleHeight);
}
}
class Sheep
{
int xpos;
int ypos;
int circleWidth = 10;
int circleHeight = 10;
public Sheep(int x, int y)
{
xpos = x;
ypos = y;
}
public void setLocation(int lx, int ly)
{
xpos = lx;
ypos = ly;
}
public void display(Graphics g)
{
g.setColor(Color.green);
g.fillOval(xpos , ypos, circleWidth, circleHeight);
g.drawOval(xpos - 20, ypos - 20, 50, 50);
}
}
First of all, I dont exactly understand why you have a display method inside your Sheep and Dog class. Instead of doing that, I suggest you display the sheep and dog inside your SheepDog class.
Also instead of using Graphics, you should use Graphics2D. In order to use this simply do
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
}
This is possible because Graphics2D is a subclass of Graphics. Once you do that, what I would do is override the update() method and do this
public void update(Graphics g) {
if (image == null) {
image = createImage(this.getWidth(), this.getHeight());
graphics = image.getGraphics();
}
graphics.setColor(getBackground());
graphics.fillRect(0, 0, this.getWidth(), this.getHeight());
graphics.setColor(getForeground());
paint(graphics);
g.drawImage(image, 0, 0, this);
}
When you call repaint(), it actually first calls the update() method, which in turn calls the paint() method. Towards the top of the class, you should declare
Image image;
Graphics graphics;