2013-11-13 2 views
0

Я пытаюсь создать программу с движущимся шаром и платформой, на которой он будет сидеть. Я тоже слишком новый java, и я не могу понять, как определить, когда перекрываются 2 объекта swing. Мой код ниже, и мне интересно, как лучше всего обнаружить перекрывающиеся объекты.Обнаружение перекрывающихся объектов в java Swing

KeyDemo.java:

import javax.swing.*; 
    import java.awt.*; 
    import java.awt.event.*; 

    public class KeyDemo 
    { 
     public static void main(String[] args) 
    { 
    JFrame frame = new JFrame(); 
    JPanel panel = new JPanel(); 
    LayoutManager overlay = new OverlayLayout(panel); 
    panel.setLayout(overlay); 

    final int FRAME_WIDTH = 800; 
    final int FRAME_HEIGHT = 600; 

    frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); 
    frame.setTitle("Move the Ball"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    final WallComponent wc1 = new WallComponent(400, 400); 
    final BallComponent bc = new BallComponent(400, 300); 
    panel.add(wc1); 
    panel.add(bc); 
    frame.add(panel); 

    KeyboardController kc = new KeyboardController(bc); 
    frame.addKeyListener(kc); 

    frame.setVisible(true); 




    class AnimationListener implements ActionListener{ 
     public void actionPerformed(ActionEvent event){ 
      bc.tick(); 
      //wc1.checkOverlap(bc); 
     } 
    } 

    ActionListener aListener = new AnimationListener(); 

    final Timer timer = new Timer(1, aListener); 
    timer.start(); 

    } 
} 

KeyboardController.java:

import java.awt.*; 
    import java.awt.event.*; 

public class KeyboardController implements KeyListener 
{ 
BallComponent bComp; 

public KeyboardController(BallComponent t) 
{ 
    bComp = t; 
} 

/** Handle the key pressed event from the text field. */ 
public void keyPressed(KeyEvent e) { 
    int keyCode = e.getKeyCode(); 
    if(keyCode == 38) 
    { 
     System.out.println("Pressed Up!"); 
     bComp.moveUp(); 
    } 
    if(keyCode == 37) 
    { 
     System.out.println("Pressed Left!"); 
     bComp.moveLeft(); 
    } 
    if(keyCode == 39) 
    { 
     System.out.println("Pressed Right!"); 
     bComp.moveRight(); 
    } 
    if(keyCode == 40) 
    { 
     System.out.println("Pressed Down!"); 
     bComp.moveDown(); 
    } 
} 

/** Handle the key released event from the text field. */ 
public void keyReleased(KeyEvent e) { 
    int keyCode = e.getKeyCode(); 
    if(keyCode == 38) 
    { 
     System.out.println("Released Up!"); 
     bComp.stopY(); 
    } 
    if(keyCode == 37) 
    { 
     System.out.println("Released Left!"); 
     bComp.stopX(); 
    } 
    if(keyCode == 39) 
    { 
     System.out.println("Released Right!"); 
     bComp.stopX(); 
    } 
    if(keyCode == 40) 
    { 
     System.out.println("Pressed Down!"); 
     bComp.stopY(); 
    }  
} 


public void keyTyped(KeyEvent e) { 
} 


    } 

BallComponent.java:

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

    public class BallComponent extends JComponent 
    { 
int xSpeed; 
int ySpeed; 
int x; 
int y; 

public BallComponent(int x, int y) 
{ 
    super(); 
    this.x = x; 
    this.y = y; 
} 

public void paintComponent(Graphics g) 
{ 
    Graphics2D g2 = (Graphics2D)g; 

    Ellipse2D.Double ball = new Ellipse2D.Double(x-10,y-10,10,10); 
    g2.setColor(Color.RED); 
    g2.fill(ball); 
    g2.draw(ball); 
} 

public void moveLeft() 
{ 
    xSpeed=-1; 
} 
public void moveRight() 
{ 
    xSpeed=1; 
} 
public void moveUp() 
{ 
    ySpeed=-1; 
} 
public void moveDown() 
{ 
    ySpeed=1; 
} 
public void tick() 
{ 
    x=x+xSpeed; 
    y=y+ySpeed; 

    repaint(); 
} 
public void stopY() 
{ 
    ySpeed=0; 
} 
public void stopX() 
{ 
    xSpeed=0; 
} 

    } 

WallComponent.java:

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

    public class WallComponent extends JComponent 
    { 
int x; 
int y; 

public WallComponent(int x, int y) 
{ 
    super(); 
    this.x = x; 
    this.y = y; 
} 

public void paintComponent(Graphics g) 
{ 
    Graphics2D g2 = (Graphics2D)g; 

    Rectangle wall = new Rectangle(x-40,y-40,40,40); 
    g2.setColor(Color.YELLOW); 
    g2.fill(wall); 
    g2.draw(wall); 
} 
public void checkOverlap(BallComponent bc){ 
    if (this.contains(bc.getLocation())){ 
     bc.stopY(); 
     bc.stopX(); 
    } 
} 
    } 
+0

Начните с того, что вы вызываете 'super.paintComponent' перед тем, как выполнять свою обычную роспись, особенно при расширении с' JComponent' – MadProgrammer

+0

Не используйте «магические числа».Никто не знает, что означают 37, 38, 39 и 40. Прочтите API KeyEvent для использования правильных имен переменных (KeyEvent.VK_RIGHT ...). Лучше еще не использовать KeyListener. См. [Движение с помощью клавиатуры]() для лучшего подхода, использующего «Ключевые привязки». – camickr

ответ

2

Все компоненты Swing имеют понятие «границы». Это прямоугольная область, в которой они «нарисованы».

Если вы контролируете размер и положение правильно, вы должны быть в состоянии использовать contains метод Rectangle который возвращается из вызова Component#getBounds

Таким образом, вы checkOverlap метод может выглядеть следующим образом ...

public void checkOverlap(BallComponent bc){ 
    if (getBounds().intersects(bc.getBounds())){ 
     bc.stopY(); 
     bc.stopX(); 
    } 
} 

Вы также должны убедиться, что вы звоните super.paintComponent перед выполнением любой пользовательской картины, особенно при использовании компонентов, которые простираются от JComponent. Это гарантирует, что Graphics контекст готов для правильной покраски ...

Обновлено

Там в каскад вопросов. В принципе, вместо того, чтобы самостоятельно размещать компоненты в родительском контейнере (как я думал, вы это сделали), вы поместили каждый компонент для заполнения родительского контейнера и только «нарисовали» объекты ... Это делает жизнь более сложный

Вместо этого, если вы собираетесь использовать компоненты, я бы использовал макет null (или даже возможно использовать в качестве родительского контейнера JLayeredPane).

Я бы тогда изменить физическое положение компонентов, например ...

import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.LayoutManager; 
import java.awt.Rectangle; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.awt.geom.Ellipse2D; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.OverlayLayout; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class TestGame { 

    public static void main(String[] args) { 
     new TestGame(); 
    } 

    public TestGame() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame(); 
       JPanel panel = new JPanel(); 
       panel.setLayout(null); 

       final int FRAME_WIDTH = 800; 
       final int FRAME_HEIGHT = 600; 

       frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); 
       frame.setTitle("Move the Ball"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

       final WallComponent wc1 = new WallComponent(400, 400); 
       final BallComponent bc = new BallComponent(400, 300); 
       panel.add(wc1); 
       panel.add(bc); 
       frame.add(panel); 

       KeyboardController kc = new KeyboardController(bc); 
       frame.addKeyListener(kc); 

       frame.setVisible(true); 

       class AnimationListener implements ActionListener { 

        public void actionPerformed(ActionEvent event) { 
         bc.tick(); 
         wc1.checkOverlap(bc); 
        } 
       } 

       ActionListener aListener = new AnimationListener(); 

       final Timer timer = new Timer(1, aListener); 
       timer.start(); 

      } 
     }); 
    } 

    public class KeyboardController implements KeyListener { 

     BallComponent bComp; 

     public KeyboardController(BallComponent t) { 
      bComp = t; 
     } 

     /** 
     * Handle the key pressed event from the text field. 
     */ 
     public void keyPressed(KeyEvent e) { 
      int keyCode = e.getKeyCode(); 
      if (keyCode == 38) { 
       System.out.println("Pressed Up!"); 
       bComp.moveUp(); 
      } 
      if (keyCode == 37) { 
       System.out.println("Pressed Left!"); 
       bComp.moveLeft(); 
      } 
      if (keyCode == 39) { 
       System.out.println("Pressed Right!"); 
       bComp.moveRight(); 
      } 
      if (keyCode == 40) { 
       System.out.println("Pressed Down!"); 
       bComp.moveDown(); 
      } 
     } 

     /** 
     * Handle the key released event from the text field. 
     */ 
     public void keyReleased(KeyEvent e) { 
      int keyCode = e.getKeyCode(); 
      if (keyCode == 38) { 
       System.out.println("Released Up!"); 
       bComp.stopY(); 
      } 
      if (keyCode == 37) { 
       System.out.println("Released Left!"); 
       bComp.stopX(); 
      } 
      if (keyCode == 39) { 
       System.out.println("Released Right!"); 
       bComp.stopX(); 
      } 
      if (keyCode == 40) { 
       System.out.println("Pressed Down!"); 
       bComp.stopY(); 
      } 
     } 

     public void keyTyped(KeyEvent e) { 
     } 

    } 

    public class BallComponent extends JComponent { 

     int xSpeed; 
     int ySpeed; 

     public BallComponent(int x, int y) { 
      super(); 
      setBounds(x, y, 10, 10); 
     } 

     public void paintComponent(Graphics g) { 
      Graphics2D g2 = (Graphics2D) g; 

      Ellipse2D.Double ball = new Ellipse2D.Double(0, 0, 9, 9); 
      g2.setColor(Color.RED); 
      g2.fill(ball); 
      g2.draw(ball); 
     } 

     public void moveLeft() { 
      xSpeed = -1; 
     } 

     public void moveRight() { 
      xSpeed = 1; 
     } 

     public void moveUp() { 
      ySpeed = -1; 
     } 

     public void moveDown() { 
      ySpeed = 1; 
     } 

     public void tick() { 
      int x = getX() + xSpeed; 
      int y = getY() + ySpeed; 

      setLocation(x, y); 

      repaint(); 
     } 

     public void stopY() { 
      ySpeed = 0; 
     } 

     public void stopX() { 
      xSpeed = 0; 
     } 

    } 

    public class WallComponent extends JComponent { 

     public WallComponent(int x, int y) { 
      super(); 
      setBounds(x, y, 40, 40); 
     } 

     public void paintComponent(Graphics g) { 
      Graphics2D g2 = (Graphics2D) g; 

      Rectangle wall = new Rectangle(0, 0, 40, 40); 
      g2.setColor(Color.YELLOW); 
      g2.fill(wall); 
      g2.draw(wall); 
     } 

     public void checkOverlap(BallComponent bc) { 

      System.out.println(" me: " + getBounds()); 
      System.out.println("you: " + bc.getBounds()); 

      if (getBounds().intersects(bc.getBounds())) { 
       bc.stopY(); 
       bc.stopX(); 
      } 
     } 
    } 
} 

Теперь вы можете использовать «нарисованные» объекты, но в этом случае я бы виртуальную концепцию Ball и Wall, которые вы можете рисовать в одном компоненте. Эти объекты должны будут предоставить информацию о местоположении и размере, которые вы могли бы снова проверить с помощью Rectangle#intersects ...

+0

Это только выходит как истина. –

+0

Проверить обновление ... – MadProgrammer

1

Как правило, попробуйте сделать «ограничительную рамку» для ваших объектов. Это будет невидимый прямоугольник, который идет с объектом. Затем просто сделайте if (rectangle1.intersects (rectangle2)) ... Метод пересечений работает только с прямоугольниками, поэтому вам нужен ограничивающий прямоугольник.

Смежные вопросы