Почему он рисует линии не в том месте?
У меня с этим проблема... Когда я рисую линию, символ следует за линией, которую я нарисовал, но компьютер рисует линию где-то еще:
Так кто-нибудь знает, что происходит?My code:
@SuppressWarnings({"serial","rawtypes","unchecked"})
public class someGame extends JFrame implements MouseListener, KeyListener{
ArrayList lines = new ArrayList();
Point2D.Double start;
final Color BROWN = new Color(156,93,82);
Slider thread;
Rectangle cow = null;
boolean drawGuy = false;
public someGame(){
super("Some Game");
setSize(700,700);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addMouseListener(this);
addKeyListener(this);
}
public void paint(Graphics g){
super.paint(g);
g.setColor(Color.black);
for(int i = 0; i < lines.size(); i++){
Line2D.Double temp = (Line2D.Double) lines.get(i);
int x1 = Integer.parseInt(""+Math.round(temp.getX1()));
int x2 = Integer.parseInt(""+Math.round(temp.getX2()));
int y1 = Integer.parseInt(""+Math.round(temp.getY1()));
int y2 = Integer.parseInt(""+Math.round(temp.getY2()));
g.drawLine(x1,x2,y1,y2);
}
if(drawGuy){
try{
URL url = this.getClass().getResource("resources/img/world/char.png");
Image image = Toolkit.getDefaultToolkit().getImage(url);
g.drawImage(image, cow.x, cow.y, this);
} catch(Exception exc){}
}
}
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mousePressed(MouseEvent e){
start = new Point2D.Double(e.getX(),e.getY());
}
public void mouseReleased(MouseEvent e){
Point2D.Double end = new Point2D.Double(e.getX(),e.getY());
lines.add(new Line2D.Double(start,end));
repaint();
}
public void keyPressed(KeyEvent e){}
public void keyReleased(KeyEvent e){}
public void keyTyped(KeyEvent e){
if(e.getKeyChar()=='p'||e.getKeyChar()=='P'){
thread = new Slider();
thread.start();
thread.action(true);
}
if(e.getKeyChar()=='q'||e.getKeyChar()=='Q'){
thread.action(false);
drawGuy = false;
thread = null;
}
}
private class Slider extends Thread{
double velocity, gravity;
boolean go = false;
public void run(){
if(go){
initGuy();
velocity = 0;
gravity = 1;
}
while(go){
try{
Line2D.Double lineTaken = null;
boolean onLine = false;
int firstOnLine = -1;
for(int i = lines.size()-1; i>=0; i--){
Line2D.Double temp = (Line2D.Double) lines.get(i);
if(temp.intersects(cow.x,cow.y,50,50)){
lineTaken = temp;
onLine = true;
if(firstOnLine!=i){
firstOnLine = i;
gravity = 0;
}
break;
}
}
if(onLine){
double grav = (lineTaken.y2-lineTaken.y1)/50;
double vlct = (lineTaken.x2-lineTaken.x1)/100;
if(velocity<5)velocity+=vlct;
if(gravity<2.5)gravity+=grav;
}
else{
gravity+=.2;
}
cow.x+=velocity;
cow.y+=gravity;
Thread.sleep(75);
repaint();
}catch(Exception e){break;}
}
}
public void action(boolean b){
go = b;
}
public void initGuy(){
Line2D.Double firstLine = (Line2D.Double) lines.get(0);
int x = Integer.parseInt(""+Math.round(firstLine.x1));
int y = Integer.parseInt(""+Math.round(firstLine.y1));
cow = new Rectangle(x+30,y-20,30,30);
drawGuy = true;
}
}
Извините за большой код, но я понятия не имею, что пошло не так...
Большое спасибо всем, кто ответит :) ...и да, основной метод -
someGame g = new someGame();
1 ответ:
1) вы никогда не должны использовать
paint(..)
без уважительной причины. скорее расширьтеJPanel
класс и переопределитеpaintComponent(...)
.2) не расширять класс
JFrame
, если не добавить функциональность3) Не забывайте, что все создание компонентов Swing и манипуляции должны выполняться в потоке отправки событий EDT -
4) соглашение об именовании Java является CamelCase, и каждое новое слово для имени класса должно начинаться с заглавных букв, т. е.SomeGame
5) Не используйте
[22]}6) ИспользованиеsetSize
, а переопределите компонентgetPreferredSize
и возвращают нужный размер, а затем вызываютpack()
наJFrame
Перед установкой видимого.Keybindings
вместоKeyListener
7) Использование
MouseAdapter
вместоMouseListener
8) не расширяйте
9) не очень хорошая идея выполнять длительные задачи, такие как загрузка изображений или выполнять любую другую работу, кроме необходимых для рисование объектов в методе paint вы должны загрузить picture etc на инициализацию класса или, по крайней мере, вне методов paint компонентов. (Я не реализовал это в приведенном ниже коде) 10) Ваша самая большая проблема в том, что линии не рисуются правильно, была:Thread
класс , а реализуйтеRunnable
и создатьstart()
метод для запуска потока в классе runnable (я не реализовал это в приведенном ниже коде)g.drawLine(x1,x2,y1,y2);
Так и должно быть.
drawLine(int x1,int y1,int x2,int y2)
:g.drawLine(x1,y1,x2,y2);
Вот код (нет времени объяснять прямо сейчас, надеюсь, вы сможете понять):
Я добавил некоторые дополнительные вещи, такие как кастинг в
Graphics2D
и использованиеRenderHints
для Сглаживание, как предложил @MadProgrammer в своем комментарии ниже.import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.net.URL; import java.util.ArrayList; import javax.swing.AbstractAction; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; public class SomeGame { public SomeGame() { JFrame frame = new JFrame("Some Game"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); DrawPanel dp = new DrawPanel(); frame.add(dp); frame.pack(); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new SomeGame(); } }); } } class DrawPanel extends JPanel { ArrayList lines = new ArrayList(); Point2D.Double start; final Color BROWN = new Color(156, 93, 82); Slider thread; Rectangle cow = null; boolean drawGuy = false; public DrawPanel() { addMouseListener(new MouseAdapter() { @Override public void mouseReleased(MouseEvent me) { super.mouseReleased(me); Point2D.Double end = new Point2D.Double(me.getX(), me.getY()); lines.add(new Line2D.Double(start, end)); repaint(); } @Override public void mousePressed(MouseEvent me) { super.mousePressed(me); start = new Point2D.Double(me.getX(), me.getY()); } }); setKeyBindings(); } private void setKeyBindings() { getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_P, 0), "P"); getActionMap().put("P", new AbstractAction() { @Override public void actionPerformed(ActionEvent ae) { thread = new Slider(DrawPanel.this); thread.action(true); thread.start(); } }); getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0), "q"); getActionMap().put("Q", new AbstractAction() { @Override public void actionPerformed(ActionEvent ae) { thread.action(false); drawGuy = false; thread = null; } }); } @Override public Dimension getPreferredSize() { return new Dimension(700, 700); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); //lets go 2D :) Graphics2D g2d = (Graphics2D) g; //turn on anti aliasing g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setColor(Color.black); for (int i = 0; i < lines.size(); i++) { Line2D.Double temp = (Line2D.Double) lines.get(i); int x1 = Integer.parseInt("" + Math.round(temp.getX1())); int x2 = Integer.parseInt("" + Math.round(temp.getX2())); int y1 = Integer.parseInt("" + Math.round(temp.getY1())); int y2 = Integer.parseInt("" + Math.round(temp.getY2())); g2d.drawLine(x1, y1, x2, y2); } if (drawGuy) { try { URL url = this.getClass().getResource("resources/img/world/char.png"); Image image = Toolkit.getDefaultToolkit().getImage(url); g.drawImage(image, cow.x, cow.y, this); } catch (Exception exc) { } } } private class Slider extends Thread { double velocity, gravity; boolean go = false; private final DrawPanel dp; private Slider(DrawPanel dp) { this.dp = dp; } public void run() { if (go) { initGuy(); velocity = 0; gravity = 1; } while (go) { try { Line2D.Double lineTaken = null; boolean onLine = false; int firstOnLine = -1; for (int i = lines.size() - 1; i >= 0; i--) { Line2D.Double temp = (Line2D.Double) lines.get(i); if (temp.intersects(cow.x, cow.y, 50, 50)) { lineTaken = temp; onLine = true; if (firstOnLine != i) { firstOnLine = i; gravity = 0; } break; } } if (onLine) { double grav = (lineTaken.y2 - lineTaken.y1) / 50; double vlct = (lineTaken.x2 - lineTaken.x1) / 100; if (velocity < 5) { velocity += vlct; } if (gravity < 2.5) { gravity += grav; } } else { gravity += .2; } cow.x += velocity; cow.y += gravity; Thread.sleep(75); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { dp.repaint(); } }); } catch (Exception e) { break; } } } public void action(boolean b) { go = b; } public void initGuy() { Line2D.Double firstLine = (Line2D.Double) lines.get(0); int x = Integer.parseInt("" + Math.round(firstLine.x1)); int y = Integer.parseInt("" + Math.round(firstLine.y1)); cow = new Rectangle(x + 30, y - 20, 30, 30); drawGuy = true; } } }