Então, estou desenvolvendo um joguinho e eu gostaria de saber o seguinte:
Tenho uma JLabel (por exemplo) que seria a imagem do meu personagem, e então o usuário clica em algum ponto na tela e a JLabel vai se movimentando em linha reta (ou diagonal) até o ponto onde cliquei.
Estou usando obviamente Java Desktop, JFrame.
Hummm…
Eu entendi o que você fez, porém não sei se apliquei da forma certa.
Dê uma olhada como eu fiz:
packagetelas;importjava.awt.EventQueue;importjava.awt.geom.Point2D;importjavax.swing.JFrame;importjavax.swing.JPanel;importjavax.swing.border.EmptyBorder;importjava.awt.event.MouseAdapter;importjava.awt.event.MouseEvent;importjavax.swing.JLabel;importjava.awt.Color;publicclassTelaTesteextendsJFrame{privateJPanelcontentPane;privateJLabellabel;publicstaticvoidmain(String[]args){EventQueue.invokeLater(newRunnable(){publicvoidrun(){try{TelaTesteframe=newTelaTeste();frame.setVisible(true);}catch(Exceptione){e.printStackTrace();}}});}publicdoubleangle(Point2Da,Point2Db){doubledeltaX=b.getX()-a.getX();doubledeltaY=b.getY()-a.getY();returnMath.atan2(deltaY,deltaX)*180/Math.PI;}publicPoint2Dmove(Point2Dp,doubledistance,doubleangle){// coordenadas da origemdoublex0=p.getX();doubley0=p.getY();intanguloArredondado=(int)(angle+0.5);switch(anguloArredondado){case0:// ângulo reto para direita, fácilreturnnewPoint2D.Double(x0+distance,y0);case180:// ângulo reto para esquerda, fácilreturnnewPoint2D.Double(x0-distance,y0);case90:// ângulo reto para cima, fácilreturnnewPoint2D.Double(x0,y0+distance);case270:// ângulo reto para baixo, fácilreturnnewPoint2D.Double(x0,y0-distance);default:// não é um ângulo reto, então tem que usar trigonometria// coordenadas da origem com translação no eixo xdoublex1=x0+distance;doubley1=y0;// coordenadas após a rotaçãodoubleradians=Math.toRadians(angle);doublecosA=Math.cos(radians);doublesinA=Math.sin(radians);doublex2=x0+((x1-x0)*cosA-(y1-y0)*sinA);doubley2=y0+((x1-x0)*sinA+(y1-y0)*cosA);// devolver coordenadas rotacionadasreturnnewPoint2D.Double(x2,y2);}}publicTelaTeste(){setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setBounds(100,100,450,300);contentPane=newJPanel();contentPane.addMouseListener(newMouseAdapter(){@OverridepublicvoidmouseClicked(MouseEvente){Point2DpontoOrigem=label.getBounds().getLocation();Point2Da=move(pontoOrigem,e.getX(),angle(pontoOrigem,e.getPoint()));label.setBounds((int)a.getX(),(int)a.getY(),label.getWidth(),label.getHeight());}});contentPane.setBorder(newEmptyBorder(5,5,5,5));setContentPane(contentPane);contentPane.setLayout(null);label=newJLabel("");label.setBackground(Color.RED);label.setOpaque(true);label.setBounds(0,0,20,20);contentPane.add(label);}}
O segundo parâmetro do move é a distância que deseja mover, por exemplo 5 pixels, mas você está informando o valor de x.
V
ViniLandi
Porém eu preciso que a minha JLabel vá se movendo lentamente até o ponto, como se fosse um personagem andando, para isso eu iria utilizar Threads, tens alguma idéia de como eu posso fazer isso usando a maneira como você me explicou?
Valeu!
staroski1 like
Sim, dispara uma thread que vai deslocando o label 1 ou 2 pixel até chegar na coordenada de destino.
O Point2D utiliza coordenadas do tipo double, então quando você compara pontoLabel.equals(pontoDestino) pode haver diferença devido à precisão dos valores, a solução para isso é comparar as coordenadas utilizando valores arredondados para x e y ou usar Point ao invés de Point2D;
Você sempre estava movendo seu ponto em 2 pixels então pode acontecer uma situação onde a distância entre o ponto de origem e o ponto de destino seja de somente 1 píxel, então se você mover 2 pixels, ele vai se afastar novamente um pixel do destino e na próxima iteração vai mover de volta 2 pixels ficando eternamente afastado 1 pixel de distância, causando uma “tremedeira” pois ele será movido de um lado pro outro sem nunca chegar no destino desejado. Neste caso tem que verificar se a distância que deseja deslocar a origem não é maior do que a distância restante para chegar ao destino.
Dei uma refatorada no seu código, veja:
importjava.awt.Color;importjava.awt.EventQueue;importjava.awt.Point;importjava.awt.event.MouseAdapter;importjava.awt.event.MouseEvent;importjava.awt.geom.Point2D;importjavax.swing.JFrame;importjavax.swing.JLabel;importjavax.swing.JPanel;importjavax.swing.border.EmptyBorder;publicclassTelaTesteextendsJFrame{publicstaticvoidmain(String[]args){EventQueue.invokeLater(newRunnable(){publicvoidrun(){try{TelaTesteframe=newTelaTeste();frame.setVisible(true);}catch(Exceptione){e.printStackTrace();}}});}privateJPanelcontentPane;privateJLabellabel;privatebooleanmovendo;publicTelaTeste(){setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setBounds(100,100,450,300);contentPane=newJPanel();contentPane.addMouseListener(newMouseAdapter(){@OverridepublicvoidmouseClicked(MouseEvente){trataClique(e.getPoint());}});contentPane.setBorder(newEmptyBorder(5,5,5,5));setContentPane(contentPane);contentPane.setLayout(null);label=newJLabel("");label.setBackground(Color.RED);label.setOpaque(true);label.setBounds(0,0,20,20);contentPane.add(label);}privatedoubleangle(Point2Da,Point2Db){doubledeltaX=b.getX()-a.getX();doubledeltaY=b.getY()-a.getY();returnMath.atan2(deltaY,deltaX)*180/Math.PI;}privatedoubledistance(Pointp1,Pointp2){doubledeltaX=p2.getX()-p1.getX();doubledeltaY=p2.getY()-p1.getY();returnMath.sqrt((deltaX*deltaX)+(deltaY*deltaY));}privatePointintPoint(doublex,doubley){returnnewPoint((int)(x+0.5),(int)(y+0.5));}privatePointmove(Pointp,doubledistance,doubleangle){// coordenadas da origemdoublex0=p.getX();doubley0=p.getY();intanguloArredondado=(int)(angle+0.5);switch(anguloArredondado){case0:// ângulo reto para direita, fácilreturnintPoint(x0+distance,y0);case180:// ângulo reto para esquerda, fácilreturnintPoint(x0-distance,y0);case90:// ângulo reto para cima, fácilreturnintPoint(x0,y0+distance);case270:// ângulo reto para baixo, fácilreturnintPoint(x0,y0-distance);default:// não é um ângulo reto, então tem que usar trigonometria// coordenadas da origem com translação no eixo xdoublex1=x0+distance;doubley1=y0;// coordenadas após a rotaçãodoubleradians=Math.toRadians(angle);doublecosA=Math.cos(radians);doublesinA=Math.sin(radians);doublex2=x0+((x1-x0)*cosA-(y1-y0)*sinA);doubley2=y0+((x1-x0)*sinA+(y1-y0)*cosA);// devolver coordenadas rotacionadasreturnintPoint(x2,y2);}}privatevoidtrataClique(Pointdestino){if(movendo){return;// se já está realizando a movimentação, ignora esse clique}movendo=true;ThreadanimacaoAndando=newThread(){publicvoidrun(){try{Pointorigem=label.getLocation();intdeslocamento=2;do{doubledistancia=distance(origem,destino);if(deslocamento>distancia){deslocamento=(int)distancia;}doubledirecao=angle(origem,destino);origem=move(origem,deslocamento,direcao);label.setLocation(origem);Thread.sleep(10);}while(!origem.equals(destino));}catch(InterruptedExceptione){e.printStackTrace();}finally{movendo=false;}}};animacaoAndando.start();}}