making an image move along a line in java - java

Im trying to make a simple program where I click and an image appears and moves along the line from the starting point to the point where I clicked. I cant seem to get the image to travel along the line because I am getting problems with the slope. Also, I cannot seem to get the picture to move along and direction in an animated fashion. Any advice?
(i excluded mousemotionlistener code i had)
public class Screen extends JPanel implements Runnable {
public Thread thread = new Thread(this); //this is needed for a game loop (i think)
public static JLabel statusbar; //displays a status bar showing what mouse movements are taking place
private Image cat; //image of the cat
public int xCoord; //get the coordinates of the mouse pressed
public int yCoord;
public double xCoord2; //get the coordinates as the mouse is released
public double yCoord2;
public int yCoordMove;
public int xCoordMove;
public double slope;
public Screen(Frame frame) {
thread.start();
loadPic(); //calls the loadPic method above
Handlerclass handler = new Handlerclass(); //creates a new class to use the mouse motion listener
System.out.println("this mouse thing works!");
addMouseListener(handler);
addMouseMotionListener(handler);
statusbar = new JLabel("default");
add(statusbar);
}
public void run(){ //this is the game run loop
System.out.println("this is running");
try{
Thread.sleep(5); //sleeps the run loop after 5000 game seconds
} catch(Exception e) {}
}
public void loadPic(){ //loads the picture
cat = new ImageIcon("C:\\Users\\Camtronius\\Documents\\NetBeansProjects\\Moving Block Proj\\src\\MovingBlock\\catIcon1.png").getImage(); //gets the image
System.out.println("Image Loaded!");
}
#Override public void paintComponent(Graphics g){
super.paintComponent(g); //paints the component, the picture, on top
g.drawImage(cat, xCoord, yCoord, this); //draws the image and at a specific location
g.drawString("sup tho!", 250, 250); //draws the text to the screen
g.setColor(Color.black); //sets color to red
g.drawLine(xCoord, yCoord, xCoordMove, yCoordMove); //draws the clicked line
}
public void picMove(){
double numerator = yCoord2 - yCoord;
double denominator = xCoord2 - xCoord;
if(denominator == 0) {
denominator =.0001;
}
slope = (numerator/denominator);
System.out.printf("the slope is: %.2f \n\n ",slope);
}

double a=Math.atan2(numerator, denominator);
double rate=100; //rate at which block will move
xCoord=(int) (xCoord + rate* Math.cos(a));
yCoord=(int) (yCoord + rate* Math.sin(a));
Result:

Related

JFrame Background is moving despite having fixed coordinates

I'm using JFrame to display some images. I've just started, and at this point I want to have a character move on screen. I have 2 files, one that extends JFrame (displays the images) and a runner file. One images is a stationary background while the other is the movable character, however, it seems that both images seem to move and the background position being stationary.
I just started using JFrame and have no idea whats going on.
This is the file that extends JPanel:
public class testScene extends JPanel{
private int x = 60;
private int y = 60;
private boolean end = false;
public void paintComponent(Graphics g){
super.paintComponent(g);
ImageIcon background = new ImageIcon("images\\map\\TestMap1.png");
background.paintIcon(this, g, 0, 0);
ImageIcon protag = new ImageIcon("images\\protag\\protag_f.png");
protag.paintIcon(this, g, x, y);
}
public int getX(){return x;}
public int getY(){return y;}
public boolean getEnd(){return end;}
public void setX(int i){x=i;}
public void setY(int i){y=i;}
public void setEnd(boolean b){end = b;}
}
This is the intended Runner:
public class testSceneRunner{
public static void main(String[] args){
testScene scene = new testScene();
scene.setBackground(Color.black);
JFrame jf = new JFrame();
InListner keyIn = new InListner(); //this is a keyboard listner
jf.addKeyListener(keyIn);
jf.setTitle("Test Scene");
jf.setSize(1020,600);
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.add(scene);
while(!scene.getEnd()){
//just changes x or y based on keyboard input
try {
Thread.sleep(25);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(keyIn.getPressed() == 87){
scene.setY(scene.getY()-1);
}
if(keyIn.getPressed() == 65){
scene.setX(scene.getX()-1);
}
if(keyIn.getPressed() == 83){
scene.setY(scene.getY()+1);
}
if(keyIn.getPressed() == 68){
scene.setX(scene.getX()+1);
}
if(keyIn.getPressed() == 69){
scene.setEnd(true);
}
jf.repaint();
}
jf.dispatchEvent(new WindowEvent(jf, WindowEvent.WINDOW_CLOSING));
}
}
I want the background to remain stationary and the character to move when one of the WASD keys is pressed. However, the background moves as well.

Java 2D game: repaint

I am creating a very simple game for my homework and right now I am solving the following problem:
in this game when you click on the shape (for now it is just a circle) it should dissapear and render a new one somewhere else (you are collecting points when you hit that shapes, that´s the point) and my problem is in the mouseClicked method, i think. I put some control System.out.println() there and everytime when the program reach this method it displays as many prints as there was circles. I mean, if you click on the first circle it displays one print, if you click on the second circle it diplays two prints and so on. Can you help me pls? I just started with the swing and awt and I don´t have much time for thorough study. Thank you so much.
public class Shape extends JPanel implements ActionListener{
Graphics2D g2;
Ellipse2D circle;
Timer t = new Timer(2000, this);
int x, y, count;
JLabel counting;
public Shape(JLabel counting){
this.counting = counting;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g2 = (Graphics2D)g;
ListenForMouse lForMouse = new ListenForMouse();
addMouseListener(lForMouse);
Random ran = new Random();
int green = ran.nextInt(256);
int red = ran.nextInt(256);
int blue = ran.nextInt(256);
Color randomColor = new Color(green, red, blue);
int wid = ran.nextInt(101) + 50;
x = ran.nextInt(650);
if(x > wid)
x = x - wid;
y = ran.nextInt(600);
if(y > wid)
y = y - wid;
circle = new Ellipse2D.Double(x,y,wid,wid);
t.start();
g2.setColor(randomColor);
g2.fill(circle);
}
#Override
public void actionPerformed(ActionEvent arg0) {
repaint();
}
private class ListenForMouse implements MouseListener{
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Control before");
if(circle.contains(e.getPoint())){
count++;
counting.setText(Integer.toString(count));
t.stop();
repaint();
System.out.println("Control in");
}
System.out.println("Control out");
}
}
}
This happens, because you add a new mouse listener every time paintComponent is called. You should do this once, inside the constructor.

Panel not correctly repainting image in Java?

Right now I am trying to get it so whenever I click inside of the oval that I have painted, and drag the mouse it will move positions by repainting. However, even though the MouseEvents are being detected correctly, the oval image is not updating. I am confused to why that is. Here is the code that deals with the oval, MouseEvents, and updating:
public class DrawOval extends JPanel {
private int size = 50;
private int locX = 0; //vector points
private int locY = 0;
private boolean isPressed = false;
private Shape oval = new Ellipse2D.Double(locX, locY, size, size * 2);
public DrawOval(int size){
this.size = size;
Dimension dims = new Dimension(size, size);
setPreferredSize(dims);
setMaximumSize(dims);
setMinimumSize(dims);
MouseAdapter m = new MouseAdapter(){
public void mouseReleased(MouseEvent e){
isPressed = false;
update(e);
System.out.println("Mouse is released!");
}
public void mousePressed(MouseEvent e){
isPressed = true;
update(e);
System.out.println("Mouse is pressed!");
}
public void mouseDragged(MouseEvent e){
if(isPressed){
update(e);
System.out.println("Mouse is dragged!");
}
}
public void update(MouseEvent e){
System.out.println("X: " + e.getX() + ", Y: " + e.getY());
if(oval.contains(e.getX(), e.getY())){
setX(e.getX()); setY(e.getY());
repaint();
}
//does not update if the mouses click coordinates are outside of the oval
}
};
addMouseListener(m); //for pressing and releasing
addMouseMotionListener(m); //for dragging
}
public void setX(int _x){
this.locX = _x;
}
public void setY(int _y){
this.locY = _y;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK);
g2.fill(oval);
}
}
I cannot figure out why it is not updating correctly. I had it partially working before, but it would update all the time, even if where the user clicked was not within the oval.
I think doing setX and setY you forget to update x and y in your oval. You have at least three options:
1) recreate Ellipse2D.Double every time you change this.locX and this.locY.
2) expect that your oval is created with x=0, y=0 once and for all, check mouse event switching to relative coordinates (if(oval.contains(e.getX() - locX, e.getY() - locY)){...}) and draw your oval using AffineTransform by g2.transform(...).
3) Declare oval as Ellipse2D.Double oval = new Ellipse2D.Double(...); and then you can change its x and y directly cause they're public:
oval.x = this.locX;
oval.y = this.locY;

Java window lagging on Ubuntu but not windows when code isn't lagging

EDIT: this bug only happens when I run my game on my Ubuntu 14.04 laptop. When I run it on the Windows school computers it works fine.
the window lags when running normally, but stops lagging while I resize the window with my mouse
I'm trying to make a simple game in java, however when ever I run it, it lags like crazy, I've looked over the code, and done some checks with System.out.println and System.currentTimeMillis and the code runs in much less than a millisecond, so that's not the problem.
The program stops when I drag to resize the window and constantly change the size of the window (presumably forcing a screen redraw), it has nice smooth animation when I do this.
When my program is running, it starts of with smooth animation, then about 1 second later it goes to about 2 FPS, then another second later to goes to 1 FPS, then about 0.5FPS and stays there until I force a repaint by resizing the window
my code is:
public class WindowSetup extends JPanel{
private static final long serialVersionUID = 6486212988269469205L;
static JFrame frame;
static JPanel panel;
protected void paintComponent(Graphics g){
super.paintComponent(g);
GameClass.draw(g);
}
public static void main(String[] args) {
frame = new JFrame("Evolver");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
panel = new WindowSetup();
frame.add(panel);
panel.setVisible(true);
frame.setVisible(true);
GameClass.init();
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
GameClass.tick();
panel.repaint();
}
};
Timer timer = new Timer(50,al); // lower numbers here make it run faster, but it still ends up slowing down to 1FPS
timer.start();
}
}
My GameClass:
public class GameClass {
static Random random;
static ArrayList<Enemy> enemies = new ArrayList<Enemy>();
static Wall wall;
static void init(){
random = new Random();
wall=new Wall();
for(int i=0;i<5;i++){
enemies.add(new Enemy(random.nextInt(200)+100,random.nextInt(200)+100,10,10,(float) (random.nextFloat()*(Math.PI*2)),1));
}
}
static void tick(){
for(Enemy d:enemies){
d.tick();
}
}
static void draw(Graphics g){
for(Enemy d:enemies){
d.draw(g);
}
wall.draw(g);
}
}
Enemy Class:
public class Enemy {
float x;
float y;
float width;
float height;
float direction;
float speed;
public Enemy(float x, float y, float width, float height, float direction, float speed) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.direction = direction;
this.speed = speed;
}
public void tick() {
direction += 0.01;
if (!(GameClass.wall.collides((int) (x + (Math.cos(direction) * speed)), (int) (y + (Math.sin(direction) * speed)),(int)width,(int)height))) {
x += Math.cos(direction) * speed;
y += Math.sin(direction) * speed;
}
}
public void draw(Graphics g) {
g.drawRect((int) x, (int) y, (int) width, (int) height);
}
}
Wall code:
public class Wall {
ArrayList<Rectangle> rectlist = new ArrayList<Rectangle>();
public Wall() {
// create list of walls here
rectlist.add(new Rectangle(10, 10, 50, 400));
rectlist.add(new Rectangle(410,10,50,400));
rectlist.add(new Rectangle(60,10,350,50));
rectlist.add(new Rectangle(60,360,350,50));
}
public void draw(Graphics g) {
for (Rectangle d : rectlist) {
g.drawRect(d.x, d.y, d.width, d.height);
}
}
public boolean collides(int x,int y,int width,int height){
for(Rectangle d:rectlist){
if(d.intersects(x, y, width, height)){
return true;
}
}
return false;
}
}
There's a problem with linux's graphics scheduling meaning it gets slower and slower for some reason. The solution to this is using Toolkit.getDefaultToolkit().sync() after you do panel.repaint(), this stops the slowdown.
This function doesn't seem to help anything on other OSes, but it does take up precious CPU cycles (quite a lot of them, actually), so use System.getProperty("os.name") to determine if you need to use it.
As a workaround, I guess you can 'simulate' the resize behavior by adding setVisible(false) and setVisible(true) around your action listener:
public void actionPerformed(ActionEvent e) {
panel.setVisible(false);
GameClass.tick();
panel.repaint();
panel.setVisible(true);
}

how to draw rectangle on java applet using mouse drag event

i am using java.
i want to draw rectangle based on mousedrag event. if user dragging the mouse, then the rectangle on the applet should increase or decrease basing on current mouse coordinates.
i have the following code.
in the following code i am using [b]SelectionArea[/b] class which extends a canvas on which i am performing drawing operation. i am using [b]image[/b] variable in this class for double buffering to reduce flickering and to save the applet's previous state(i.e drawing content of applet)
but the code is working fine if i draw first rectangle. if i start to draw second rectangle the previously drawn rectangle is disappearing. i want the previously drawn rectangle to be on the screen
can any one tell me how to solve this.
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
/*
* This displays a framed area. When the user drags within
* the area, this program displays a rectangle extending from
* where the user first pressed the mouse button to the current
* cursor location.
*/
public class RectangleDemo extends Applet {
SelectionArea drawingPanel;
Label label;
public void init() {
GridBagLayout gridBag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setLayout(gridBag);
drawingPanel = new SelectionArea(this);
c.fill = GridBagConstraints.BOTH;
c.weighty = 1.0;
c.gridwidth = GridBagConstraints.REMAINDER; //end row
gridBag.setConstraints(drawingPanel, c);
add(drawingPanel);
label = new Label("Drag within the framed area.");
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
c.weighty = 0.0;
gridBag.setConstraints(label, c);
add(label);
drawingPanel.setVisible(true);
validate();
}
public void paint(Graphics g){
drawingPanel.repaint();
}
public void update(Graphics g){
paint(g);
}
}
class SelectionArea extends Canvas implements ActionListener, MouseListener, MouseMotionListener{
Rectangle currentRect;
RectangleDemo controller;
//for double buffering
Image image;
Graphics offscreen;
public SelectionArea(RectangleDemo controller) {
super();
this.controller = controller;
addMouseListener(this);
addMouseMotionListener(this);
}
public void actionPerformed(ActionEvent ae){
repaintoffscreen();
}
public void repaintoffscreen(){
image = createImage(this.getWidth(), this.getHeight());
offscreen = image.getGraphics();
Dimension d = getSize();
if(currentRect != null){
Rectangle box = getDrawableRect(currentRect, d);
//Draw the box outline.
offscreen.drawRect(box.x, box.y, box.width - 1, box.height - 1);
//repaint();
}
}
public void mouseEntered(MouseEvent me) {}
public void mouseExited(MouseEvent me){ }
public void mouseClicked(MouseEvent me){}
public void mouseMoved(MouseEvent me){}
public void mousePressed(MouseEvent me) {
currentRect = new Rectangle(me.getX(), me.getY(), 0, 0);
repaintoffscreen();
}
public void mouseDragged(MouseEvent me) {
System.out.println("here in dragged()");
currentRect.setSize(me.getX() - currentRect.x, me.getY() - currentRect.y);
repaintoffscreen();
repaint();
}
public void mouseReleased(MouseEvent me) {
currentRect.setSize(me.getX() - currentRect.x, me.getY() - currentRect.y);
repaintoffscreen();
repaint();
}
public void update(Graphics g){
paint(g);
}
public void paint(Graphics g) {
g.drawImage(image, 0, 0, this);
}
Rectangle getDrawableRect(Rectangle originalRect, Dimension drawingArea) {
int x = originalRect.x;
int y = originalRect.y;
int width = originalRect.width;
int height = originalRect.height;
//Make sure rectangle width and height are positive.
if (width < 0) {
width = 0 - width;
x = x - width + 1;
if (x < 0) {
width += x;
x = 0;
}
}
if (height < 0) {
height = 0 - height;
y = y - height + 1;
if (y < 0) {
height += y;
y = 0;
}
}
//The rectangle shouldn't extend past the drawing area.
if ((x + width) > drawingArea.width) {
width = drawingArea.width - x;
}
if ((y + height) > drawingArea.height) {
height = drawingArea.height - y;
}
return new Rectangle(x, y, width, height);
}
}
also if i run this code on full screen mode then i am seeing that the rectangle is appering on screen only after i released the mouse. but i want the rectangle to be on the screen while dragging the mouse and it should change it's dimension according to the current mouse coordinates.
can any one help me pls.
homework?
basically what you need to do is:
on mouse down keep the mouse-down coordinates and repaint
on mouse move keep current mouse coordinates and repaint
on mouse up, nullify the mouse-down coordinates to indicate there is no rect, and repaint.
on paint, draw background and then rect between mousedown and cur-mouse coordinates.
if you don't want to keep a background image, you can do a trick with the Graphics xor function, drawing the same rect twice will erase the old rect, so you can use it to restore the old image straight on the graphics object.
Edit: code xor usage sample:
public void paint(Graphics g)
{
g.setXORMode(Color.black);
// draw old rect if there is one. this will erase it
// draw new rect, this will draw xored
g.setDrawMode(); // restore normal draw mode
}
Xor has the an interesting property:
xor(xor(x)) = x
so xoring the same pixel twice restores it's original color.
There are a couple issues that need to be addressed.
First, regarding only one rectangle can be drawn, this is due to the design of your program. In your code, whenever the repaintoffscreen method is called, the currectRect field is used to draw a rectangle. However, there is no provision to keep holding onto rectangles which were made in the past.
One way to keep a hold of past rectangles would be perhaps to make another field which is, for example, a List<Rectangle> which is used to store past rectangles. Then, when the mouse is released, add the current rectangle to that list.
Then, in order for all rectangles, currentRect and past rectangles to appear, repaintoffscreen will need to not only perform getDrawableRect and offscreen.drawRect using the currentRect but also with the past rectangles which are stored in the List<Rectangle>. (Hint, use a for loop to iterate through the list.)
Second, regarding the rectangle not appearing until after releasing the mouse button, rather than using the mouseDragged method, maybe using the mouseMoved method along with a check to see that the mouse button is depressed may be a workaround. (I think I've also had trouble dealing with the mouseDragged method in the past.)
The MouseEvent passed into the mouseMoved method can be used to check if a button is depressed by the getButton method:
public void mouseMoved(MouseEvent e)
{
// Check if button1 is pressed.
if (e.getButton() == MouseEvent.BUTTON1)
{
// Perform sizing of rectangle and off-screen drawing, and repaint.
}
}
My question was about create a select rectangle invert mouse click position, but, in the end I got make this with this method:
... //to set the selection area
private int iniSelX;
private int iniSelY;
private int endSelX;
private int endSelY;
private JPanel myJPanel = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(Color.red);
g.drawLine(260, 5, 260, 260);
g.setColor(Color.BLUE);
//verify if go draw the rectangle
if (iniSelX != 0 || endSelX != 0) {
boolean revertX = iniSelX < endSelX;
boolean revertY = iniSelY < endSelY;
//Simple way
//g.drawRect(iniSelX, iniSelY, endSelX - iniSelX, endSelY - iniSelY);
//reverse way
g.drawRect(revertX ? iniSelX : endSelX, revertY ? iniSelY : endSelY,
revertX ? endSelX - iniSelX : iniSelX - endSelX, revertY ? endSelY - iniSelY : iniSelY - endSelY);
}
}
}; ...
addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent m) {
//update selection area
endSelX = m.getX();
endSelY = m.getY();
repaint();
}
#Override
public void mouseMoved(MouseEvent m) {
repaint();
}
});
addMouseListener(new MouseListener() {
...
#Override
public void mousePressed(MouseEvent e) {
//start drawing the selection
iniSelX = e.getX() - 15;
iniSelY = e.getY() - 20;
}
#Override
public void mouseReleased(MouseEvent e) {
//start drawing the selection
iniSelX = 0;
iniSelY = 0;
endSelX = 0;
endSelY = 0;
}
...
});
}
public void log() {
System.out.println("iniSelX" + iniSelX);
System.out.println("iniSelY" + iniSelY);
System.out.println("endSelX" + endSelX);
System.out.println("endSelY" + endSelY);
} ...
I hope this is useful.

Categories

Resources