2016-03-13 2 views
0

В настоящее время я пытаюсь узнать больше о живописи в качелях, и я создаю небольшую игру, но, похоже, я застрял. Я пытаюсь добавить пару прямоугольников (Enemies) в ArrayList, затем нарисуйте их в методе paintComponent(), но он не работает.Невозможно нарисовать прямоугольники на JPanel

Вот мой класс Enemy

import utils.RandomUtils; 

import java.awt.*; 
import java.awt.geom.Rectangle2D; 

public class Enemy 
{ 
    double x, y, w, h; 
    Shape enemy; 

    Toolkit tk = Toolkit.getDefaultToolkit(); 
    double width = tk.getScreenSize().width; 
    double height = tk.getScreenSize().height; 

    RandomUtils utils = new RandomUtils(); 

    public Enemy(int w, int h) 
    { 
     this.w = w; 
     this.h = h; 

     enemy = new Rectangle2D.Double(setX(), setY(), w, h); 
    } 

    private double setX() 
    { 
     return x = utils.randInt((int) w, (int) width); 
    } 

    private double setY() 
    { 
     return y = utils.randInt((int) h, (int) height); 
    } 

    public Shape getEnemy() 
    { 
     return enemy; 
    } 
} 

Вот мой совет класс

import players.Enemy; 

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.util.ArrayList; 

public class Board extends JPanel 
{ 
    int x, y, speed = 1, height = 25, width = 25; 

    public Board() 
    { 
     addControls(); 
    } 

    public void addControls() 
    { 
     Action upAction = new AbstractAction() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       y = y - speed; 
       repaint(); 
      } 
     }; 

     getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke("W"), "Up Action"); 
     getActionMap().put("Up Action", upAction); 

     Action downAction = new AbstractAction() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       y = y + speed; 
       repaint(); 
      } 
     }; 

     getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke("S"), "Down Action"); 
     getActionMap().put("Down Action", downAction); 

     Action leftAction = new AbstractAction() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       x = x - speed; 
       repaint(); 
      } 
     }; 

     getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke("A"), "Left Action"); 
     getActionMap().put("Left Action", leftAction); 

     Action rightAction = new AbstractAction() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       x = x + speed; 
       repaint(); 
      } 
     }; 

     getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke("D"), "Right Action"); 
     getActionMap().put("Right Action", rightAction); 
    } 

    boolean enemiesDrawn = false; 
    java.util.List<Enemy> enemies = new ArrayList<>(); 
    java.util.List<Shape> enemyShapes = new ArrayList<>(); 

    public void setEnemies() 
    { 
     for(int enemyCount = 0; enemyCount < 15; enemyCount++) 
     { 
      System.out.println(enemyCount); 
      enemies.add(new Enemy(15, 15)); 
      enemyShapes.add(enemies.get(enemyCount).getEnemy()); 
     } 
    } 

    @Override 
    public void paintComponent(Graphics g) 
    { 
     super.paintComponent(g); 

     Graphics2D g2 = (Graphics2D) g; 

     g.setColor(Color.RED); 
     g.fillOval(x, y, width, height); 

     if(!enemiesDrawn) 
     { 
      setEnemies(); 

      g2.setColor(Color.BLUE); 
      g2.setBackground(Color.BLUE); 

      enemyShapes.forEach(g2::draw); 

      enemiesDrawn = true; 
     } 
    } 
} 

Util класс

import java.util.Random; 

public class RandomUtils 
{ 
    public RandomUtils() 
    { 
    } 

    public int randInt(int min, int max) 
    { 
     Random rand = new Random(); 
     return rand.nextInt((max - min) + 1) + min; 
    } 
} 

И главный класс

import javax.swing.*; 

public class MainFrame 
{ 
    JFrame mainFrame; 

    public MainFrame() 
    { 
     mainFrame = new JFrame("Game"); 

     addComponents(); 

     mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH); 
     mainFrame.setLocationRelativeTo(null); 
     mainFrame.pack(); 
     mainFrame.setVisible(true); 
    } 

    public void addComponents() 
    { 
     mainFrame.add(new Board()); 
    } 

    public static void main(String[] args) 
    { 
     SwingUtilities.invokeLater(MainFrame::new); 
    } 
} 

Картина Овал (игрок) работает отлично, я просто не могу изобразить врагов в Списке. Что мне следует сделать, чтобы это исправить?

+0

Какой смысл иметь два ArrayLists? Подумайте о том, чтобы обеспечить runnable пример, который демонстрирует вашу проблему. – MadProgrammer

+0

Один для самих врагов и один для форм врагов. Я выложу полный код. – Jonah

+1

Рекомендация стороны, никогда не удаляйте объект Graphics, 'g2.dispose();', предоставленный вам JVM. Выбирайте только те, которые вы сами создаете, например, из изображений или из других объектов Graphics. Это может привести к повреждению цепи окраски. –

ответ

2

Так что ваша главная проблема здесь ...

if (!enemiesDrawn) { 
    setEnemies(); 

    g2.setColor(Color.BLUE); 
    g2.setBackground(Color.BLUE); 

    System.out.println("..."); 
    enemyShapes.forEach(g2::draw); 

    enemiesDrawn = true; 
} 

После paintComponent вызывается один раз, враги никогда не будут окрашены снова. paintComponent можно назвать много раз (часто в быстрой последовательности), каждый раз, когда он вызывается, вы, как ожидается, снова перерисуете все состояние компонента с нуля.

Посмотрите Painting in AWT and Swing и Performing Custom Painting для получения более подробной информации о том, как покрасочные работы в свинг

Наблюдения ...

Это вроде бессмысленно ...

mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH); 
mainFrame.setLocationRelativeTo(null); 
mainFrame.pack(); 

You 're установить кадр максимизирован но затем пытаясь упаковать его? Это может вызвать проблемы в некоторых системах, поэтому будьте осторожны.

RandomUtils должен создать один экземпляр Random, потому что, как она работает, вы рискуете иметь Random возвращения то же значение, в том же порядке. Вы можете просто о уйти с одноплодной

public enum RandomUtils { 

    INSTANCE; 

    private Random rand = new Random(); 

    public int randInt(int min, int max) { 
     return rand.nextInt((max - min) + 1) + min; 
    } 
} 

Использование Toolkit в вашем Enemy не очень хорошая идея, за исключением того, что противник должен иметь мало знаний о внешнем мире, Toolkit не самый лучший выбор для определения фактического размера экрана, видимого на экране, учитывая тот факт, что у вашего окна есть декорации, а на рабочем столе есть такие вещи, как панели задач, это создает риск того, что некоторые из ваших врагов появятся на экране

Из-за того, как работает ваша программа, было бы сложно предложить что-то, что бы воспроизвести выход. Но в основном вы должны передать желаемое местоположение/размер конструктору класса Enemy.

Вы можете использовать ComponentListener и контролировать componentResized метод, который он первым стабилизируется, вы могли бы создать врагов на основе текущего размера компонента

+0

Ahhh, я вижу! Спасибо за ответ. Теперь он полностью работает. – Jonah

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