0

i have been working on mouse motion listener in Java couldn't sort it out completely because i want the object to move towards the direction where ever on the screen the mouse is pointed at but unforunately when the mouse is inside the applet window, the object moves only towards a single direction. Here is my code below..

import java.awt.*;
import java.awt.geom.*;
import java.util.*;
import java.applet.*;
import java.awt.event.*;
import javax.swing.*;

public class MouseOver extends Applet implements KeyListener, MouseListener,
      MouseMotionListener {
   private int[] Xpoints = { 0, -5, 5 };
   private int[] Ypoints = { -10, -2, -2 };
   private double xpos, ypos;
   private Polygon poly;
   int polyrot = 0;
   private int width; // !! added
   private int height; // !! added

   public void init() {
      poly = new Polygon(Xpoints, Ypoints, Xpoints.length);
      addKeyListener(this);
      addMouseListener(this);
      addMouseMotionListener(this);
   }

   public void paint(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
      AffineTransform id = new AffineTransform();
      width = getSize().width;
      height = getSize().height;
      g2d.setColor(Color.BLACK);
      g2d.fillRect(0, 0, width, height);
      g2d.setColor(Color.RED);
      g2d.draw(poly);
      g2d.translate(width / 2, height / 2);
      g2d.rotate(Math.toRadians(polyrot));
      g2d.scale(5, 5);
   }

   public void keyReleased(KeyEvent k) {
   }

   public void keyTyped(KeyEvent k) {
   }

   public void keyPressed(KeyEvent k) {
      switch (k.getKeyCode()) {
      case KeyEvent.VK_LEFT:
         if (polyrot < 0) {
            polyrot = 359;
            polyrot++;
         }
         repaint();
         break;
      case KeyEvent.VK_RIGHT:
         if (polyrot > 360) {
            polyrot = 0;
            polyrot--;
         }
         repaint();
         break;
      }
   }

   public void mouseEntered(MouseEvent m) {
   }

   public void mouseExited(MouseEvent m) {
   }

   public void mouseReleased(MouseEvent m) {
   }

   public void mouseClicked(MouseEvent m) {
   }

   public void mousePressed(MouseEvent m) {
      switch (m.getButton()) {
      case MouseEvent.BUTTON1:
         if (polyrot < 0) {
            polyrot = 359;
            polyrot--;
         }
         repaint();
         break;
      case MouseEvent.BUTTON2:
         if (polyrot > 360) {
            polyrot = 0;
            polyrot++;
         }
         repaint();
         break;
      }
   }

   public void mouseMoved(MouseEvent e) {
      xpos = getX();
      if (xpos < 0) {
         polyrot--;
      } else if (xpos > 0) {
         polyrot++;
      }
      repaint();
      // !! break; // Doesn't belong here
   }

   @Override
   public void mouseDragged(MouseEvent e) {
      // You forgot this method
   }
}
Charles
  • 50,943
  • 13
  • 104
  • 142
  • 2
    Your code is without any indentations making it all left justified and almost impossible for us to read, understand and debug. Please re-format your posted code by giving it proper indentations, usually 3 spaces per block, and making sure that all code on the same block is on the same indentation level. Your cooperation in this would be greatly appreciated and will likely improve your chances of getting a decent and prompt answer. – Hovercraft Full Of Eels Nov 21 '13 at 18:39
  • 1
    If this is your idea of humor, it's not well appreciated. – Hovercraft Full Of Eels Nov 21 '13 at 19:08
  • well nope i wasnt joking. well the code can be read properly i dont know why u feel difficult? – nishpystoned Nov 21 '13 at 19:14
  • there it is i hope now its what expected? – nishpystoned Nov 21 '13 at 19:21
  • No, I'm not talking about empty lines, and in fact you shouldonly have one empty line between methods. Again you need to indent blocks of code. If code is in a method block, that block needs to be indented 3 spaces. I'd do it for you, but the code posted has too many careless errors that it won't compile for me and my IDE can't format it. You do understand what the term "indentation" means right? It means that the line of code doesn't start at the left, it's moved over 3 chars if inside of a block. – Hovercraft Full Of Eels Nov 21 '13 at 19:22
  • 1
    I've tried to add fields and variables that you left out so that your code now compiles. I've now indented your code. Again, please remember that we're volunteers, that when asking for advice here, you should make effort for your code to be presentable and readable. – Hovercraft Full Of Eels Nov 21 '13 at 19:26
  • Do you mean you want the object to "point towards" the mouse cursor or actually move towards it...? – MadProgrammer Nov 21 '13 at 19:57

4 Answers4

2

Your problem is with this line:

public void mouseMoved(MouseEvent e){
 xpos=getX(); // ******
 if(xpos<0){polyrot--;}
 else if(xpos>0){polyrot++;}
 repaint();
 break;
}

That returns the x position of the applet not the mouse cursor. You need to use your MouseEvent object, e and instead get the mouse's position. Change it to:

xpos = e.getX();

Please don't ignore the comment that I made to your question. Please remember that we're volunteers who help on our free time. Please don't make it any more difficult than it has to be to help you.


I've tried to edit your code so that it compiles, and now is indented. Consider creating a Swing application, not an AWT application, since Swing apps are more flexible, powerful and robust.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • @Hovercraft..thanks for indenting apologies in not getting what u meant earlier, Can u show me how to be done using swing? – nishpystoned Nov 22 '13 at 05:57
1

There are a few things...

In your keyPressed and mousePressed events, are are only ever process the out of bounds conditions, for example...

if (polyrot < 0) {
    polyrot = 359;
    polyrot++;
}
//...
if (polyrot > 360) {
    polyrot = 0;
    polyrot--;
}

But you never process what it should do when it's within the acceptable bounds (0-359)...

Instead, you could simply add or subtract the amount from polyrot and allow the API to deal with it (surprisingly, it's capable for dealing with angles < 0 and > 359), for example...

public void mousePressed(MouseEvent m) {
    switch (m.getButton()) {
        case MouseEvent.BUTTON1:
            polyrot--;
            repaint();
            break;
        case MouseEvent.BUTTON2:
            polyrot++;
            repaint();
            break;
    }
}

Now, I'm not sure what you mean by "object to move towards the direction where ever on the screen the mouse is pointed". Does this mean that the object should actually change it's x/y coordinates or should it just "look" at the mouse cursor...

Based on the fact that you actually have no movement code and you basically have the object painted in a fixed location, I'm assuming "look at"...

Basically, you need to know where the mouse is and where the object is, then determine the angle between them...

public void mouseMoved(MouseEvent e) {
    int x = width / 2;
    int y = height / 2;

    Point mousePoint = e.getPoint();

    int deltaX = mousePoint.x - x;
    int deltaY = mousePoint.y - y;

    polyrot = -Math.atan2(deltaX, deltaY);
    polyrot = Math.toDegrees(polyrot) + 180;

    repaint();
}

You should note that I changed 'polyrot' to 'double'

Your paint method is also wrong. Basically, you are painting your object BEFORE you've transformed it, instead, you should be using something more like...

g2d.translate(width / 2, height / 2);
g2d.rotate(Math.toRadians(polyrot));
g2d.draw(poly);

You should also be calling super.paint(g) before you apply you own custom painting...

As a side note, you should avoid overriding paint of top level containers, like JApplet, but instead, create a custom component, extending from something like JPanel and override it's paintComponent method, performing your custom painting there (don't forget to call super.paintComponent). Take a look at Performing Custom Painting for more details

You should also avoid using KeyListener and instead use the Key Bindings API as it doesn't suffer from the same focus issues that KeyListener does...

Updated with runnable example

So I had a play around with code and produced this simple example...

enter image description here

Basically, I tossed out Polygon in favour of Path2D, basically because it provides much greater functionality and is easy to deal with when scaling ;)

import java.applet.Applet;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;

public class MouseOver extends Applet implements KeyListener, MouseListener,
                MouseMotionListener {

    private double xpos, ypos;
    private Path2D poly;
    private double polyrot = 0;
    private int width; // !! added
    private int height; // !! added

    public void init() {
        poly = new Path2D.Double();
        poly.moveTo(0, 10);
        poly.lineTo(5, 0);
        poly.lineTo(10, 10);
        poly.lineTo(0, 10);
        poly.closePath();
        addKeyListener(this);
        addMouseListener(this);
        addMouseMotionListener(this);
    }

    public void paint(Graphics g) {
        super.paint(g);;

        Graphics2D g2d = (Graphics2D) g;
        AffineTransform id = new AffineTransform();
        width = getSize().width;
        height = getSize().height;
        g2d.setColor(Color.BLACK);
        g2d.fillRect(0, 0, width, height);
        g2d.setColor(Color.RED);

        id.scale(5, 5);
        Shape scaled = poly.createTransformedShape(id);

        Rectangle bounds = scaled.getBounds();        
        g2d.translate((width - bounds.width) / 2, (height - bounds.height) / 2);
        g2d.rotate(Math.toRadians(polyrot), bounds.width / 2, bounds.height / 2);

        g2d.setStroke(new BasicStroke(5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

        g2d.draw(scaled);
    }

    public void keyReleased(KeyEvent k) {
    }

    public void keyTyped(KeyEvent k) {
    }

    public void keyPressed(KeyEvent k) {
        switch (k.getKeyCode()) {
            case KeyEvent.VK_LEFT:
                polyrot++;
                repaint();
                break;
            case KeyEvent.VK_RIGHT:
                polyrot--;
                repaint();
                break;
        }
    }

    public void mouseEntered(MouseEvent m) {
    }

    public void mouseExited(MouseEvent m) {
    }

    public void mouseReleased(MouseEvent m) {
    }

    public void mouseClicked(MouseEvent m) {
    }

    public void mousePressed(MouseEvent m) {
        switch (m.getButton()) {
            case MouseEvent.BUTTON1:
                polyrot--;
                repaint();
                break;
            case MouseEvent.BUTTON2:
                polyrot++;
                repaint();
                break;
        }
    }

    public void mouseMoved(MouseEvent e) {
        int x = width / 2;
        int y = height / 2;

        Point mousePoint = e.getPoint();

        int deltaX = mousePoint.x - x;
        int deltaY = mousePoint.y - y;

        polyrot = -Math.atan2(deltaX, deltaY);
        polyrot = Math.toDegrees(polyrot) + 180;

        repaint();
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        // You forgot this method
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thanks got it done infact i am using the keypad of my lap so was a silly mistake i just had to change the case MouseEvent.BUTTON2 To case MouseEvent.BUTTON3 – nishpystoned Nov 22 '13 at 06:22
  • At least you're making progress! – MadProgrammer Nov 22 '13 at 06:26
  • Just a correction to be made i have already used the paint method after transformation. By "object to move towards the direction where ever on the screen the mouse is pointed" means the object should face the mouse pointer, which inturn means its x and y cordinates will change as well.. – nishpystoned Nov 22 '13 at 06:32
  • i am working on development of a game, its a plane game with a character seated in it. So i would appreciate if you could help if i needed any..Anyways thanks a lot for now! – nishpystoned Nov 22 '13 at 06:35
  • The mouse moved code present should do that, but it will also keep the object within the center of the screen... – MadProgrammer Nov 22 '13 at 06:35
  • Yes i need at the center but the movement is not perfect as i need the triangle to face the cursor where ever it is placed with in the bounds and turn instantly towards the cursor it doesnt do that.. – nishpystoned Nov 22 '13 at 08:07
  • I'm not sure what you mean. The mouse move code I suggested does just that. As the mouse moves, it calculates the angle that be required to make the shape point at it, see update... – MadProgrammer Nov 22 '13 at 09:48
  • Hope it gets you little loser to your solution ;) – MadProgrammer Nov 25 '13 at 06:24
  • poly.moveTo(0, 10); poly.lineTo(5, 0); poly.lineTo(10, 10); poly.lineTo(0, 10); poly.closePath(); – nishpystoned Nov 25 '13 at 09:24
  • Basically, it creates a "Shape" object that represents the triangle. Think of it like a virtual pen, it says to move to x/y 0/10, draw a line to 5/0, 10/10 and back to 0/10 and ensures that the first and last points are joined. Think of like Ploygon on steroids... – MadProgrammer Nov 25 '13 at 09:43
  • in some games the airplane moves side ways like a wave..How can it be done when using raster graphics? – nishpystoned Nov 25 '13 at 19:38
  • Basically, yes. You either translate the `Graphics` context (`Graphics#translate`) or simply draw the image at the specific location (`Graphics#drawImage(Image, int, int, ImageObserver`) – MadProgrammer Nov 25 '13 at 21:23
1

This:

  if (xpos < 0) {

means "if the cursor is outside of the panel".

This:

  xpos = getX();

does not get a mouse coordinate.

Change your event to something like this:

public void mouseMoved(MouseEvent e) {
    xpos = e.getX();
    if (xpos < getWidth() / 2) {
        polyrot--;
    } else {
        polyrot++;
    }
    repaint();
}

Now it rotates counter-clockwise if the cursor is on the left side of the panel and clockwise if the cursor is on the right side.

This:

  g2d.draw(poly);
  g2d.translate(width / 2, height / 2);
  g2d.rotate(Math.toRadians(polyrot));
  g2d.scale(5, 5);

will not do anything to change the image because you are doing your transforming after drawing it.

This:

  Graphics2D g2d = (Graphics2D) g;

is a bad idea because you are applying transforms to the global graphics context which would carry on to subsequent repaints of other components.

Change your paint to something like this:

public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D) g.create();
    width = getSize().width;
    height = getSize().height;
    g2d.setColor(Color.BLACK);
    g2d.fillRect(0, 0, width, height);
    g2d.translate(width / 2, height / 2);
    g2d.rotate(Math.toRadians(polyrot));
    g2d.scale(5, 5);
    g2d.setColor(Color.RED);
    g2d.draw(poly);
    g2d.dispose();
}

Further reading:

Radiodef
  • 37,180
  • 14
  • 90
  • 125
  • You've broken the paint chain - but I won't blame you as the OP did it as well ;) – MadProgrammer Nov 22 '13 at 06:27
  • @MadProgrammer What do you mean specifically? I know I didn't call super.paint but I figured it didn't really matter in this specific case since the only thing to paint is the shape. Not great form but it's not going to blow up and there are greater issues IE as you pointed out a better plan is to not use Applet. – Radiodef Nov 22 '13 at 07:09
  • @Radiodef Paint is a complex chain of methods, each building ontop of each to produce a final effect. Apart from the fact the `JApplet` is not double buffered, `paint` is doing a lot of important work that you've just decided to throw away. You should, where possible, always try to call `super.paint`, even if there are no components, as `paint` is doining other things other then painting the components ;) – MadProgrammer Nov 22 '13 at 07:19
  • @MadProgrammer Gotcha. I always figured that happened outside the components. I should keep learning too. : / Thanks. – Radiodef Nov 22 '13 at 07:37
  • @MadProgrammer, well its getting interesting now..what kinda other things would paint component do?? – nishpystoned Nov 22 '13 at 17:51
  • @nishpystoned Take a look at [Painting in AWT and Swing](http://www.oracle.com/technetwork/java/painting-140037.html) – MadProgrammer Nov 22 '13 at 19:23
-1

From here:

public void mouseMoved(MouseEvent e){
 xpos=getX();
 if(xpos<0){polyrot--;}
 else if(xpos>0){polyrot++;}
 repaint();
 break;
}

It seems you update only the xpos. You should update also the variable ypos. You might want to do it with something like this:

ypos=e.getY();
if (this.ypos<0){
 this.polyrot--;
}else if (this.ypos>0) {
 this.polyrot++;
}
this.repaint();
Koldar
  • 1,317
  • 15
  • 35