java - Sprite 在特定的 JPanel 上生成

标签 java swing jpanel paint keylistener

我正在开发多人游戏,当服务器发送不同的消息时,即。敌人的类型和敌人的数量。该特定 Sprite 加载到屏幕上。我有 4 个 View ,由 CardLayout 和顶部用于在屏幕之间切换的按钮分隔。

这是我设置的链。当我尝试绘制敌人时..我收到错误。

在主类中我有这个方法:

public void handleAttack(String message){
  ViewA.spawnEnemy(type,amt);
}

这是 ViewA 的类,它具有 spawnEnemy() 方法。

public class BattleView extends JPanel implements ActionListener {  
  private Player player;
  private Timer timer;
  private int B_WIDTH;
  private int B_HEIGHT;
  private boolean ingame;
  private ArrayList aliens;

  public BattleView(Player player) {
    this.player = player;
    addKeyListener(new TAdapter());
    setFocusable(true);
    setBackground(Color.RED);
    setDoubleBuffered(true);
    setSize(652, 480);
    ingame = true;
    timer = new Timer(5, this);
    timer.start();
  }

  public void addNotify() {
    super.addNotify();
    B_WIDTH = getWidth();
    B_HEIGHT = getHeight();   

    super.setPreferredSize(new Dimension(B_WIDTH,B_HEIGHT));
  }

  public void spawnEnemy(int type, int amount) {
    aliens = new ArrayList();
    for (int i=1; i<amount+1; i++ ) {
      aliens.add(new Enemy(0-i*40,400));
      System.out.println("Attack Message Recieved "+i);
    }
  }

  public void paint(Graphics g) {
    super.paint(g);

    Graphics2D g2d = (Graphics2D)g;
    g2d.drawImage(background, 0, 0, null);

    if (player.isVisible()){
      g2d.drawImage(player.getImage(), player.getX(), player.getY(), this);
    }
    ArrayList ms = player.getMissiles();

    /* for (int i = 0; i < ms.size(); i++) {
      Missile m = (Missile)ms.get(i);
      g2d.drawImage(m.getImage(), m.getX(), m.getY(), this);
    }*/

    /*    for (int i = 0; i < aliens.size(); i++) {
      Enemy a = (Enemy)aliens.get(i);
      if (a.isVisible()){
        g2d.drawImage(a.getImage(), a.getX(), a.getY(), this);
      }
    }*/

    g2d.setColor(Color.BLACK);
    g2d.drawString("BattleView: ", 5, 15);

    Toolkit.getDefaultToolkit().sync();
    g.dispose();
  }

  @Override public void actionPerformed(ActionEvent e) {
    /* if (aliens.size()==0) {
      //send message to server that enemies have been killed
    }*/

    ArrayList ms = player.getMissiles();
    /*  for (int i = 0; i < ms.size(); i++) {
      Missile m = (Missile) ms.get(i);
      if (m.isVisible()){
        m.move();
      }else{
        ms.remove(i);
      }
    }*/

    /*  for (int i = 0; i < aliens.size(); i++) {
      Enemy a = (Enemy) aliens.get(i);
      if (a.isVisible()){
        a.move();
      }else{
        aliens.remove(i);
      }
    }*/

    player.move();
    checkCollisions();
    repaint();  
  }

  public void checkCollisions() {
    /* Rectangle r3 = player.getBounds();

    for (int j = 0; j<aliens.size(); j++) {
      Enemy a = (Enemy) aliens.get(j);
      Rectangle r2 = a.getBounds();

        if (r3.intersects(r2)) {
          player.setVisible(false);
          a.setVisible(false);
          ingame = false;
        }
    }*/

    ArrayList ms = player.getMissiles();
    /*  for (int i = 0; i < ms.size(); i++) {
      Missile m = (Missile) ms.get(i);

      Rectangle r1 = m.getBounds();
      for (int j = 0; j<aliens.size(); j++) {
        Enemy a = (Enemy) aliens.get(j);
        Rectangle r2 = a.getBounds();

        if (r1.intersects(r2)) {
          m.setVisible(false);
          a.setVisible(false);
        } // r1.intersects
      } // for aliens.size()
    }*/ // for ms.size()
  }

  private class TAdapter extends KeyAdapter {

    public void keyReleased(KeyEvent e) {
      player.keyReleased(e);
    }

    public void keyPressed(KeyEvent e) {
      player.keyPressed(e);
    }
  }
}

当服务器发送消息时,这部分会触发五个 System.out.println("Attack Message Recieved "+i);。因此,如果服务器发送 1,5.. 5 个类型 1 的单元被“接收”,并且 System.out.println 打印 5 次。

现在,当我尝试使用paint(g)使用for循环绘制敌方单位时..我收到一个错误当我注释掉for循环时,一切都编译正常并加载(但不会创建敌人的屏幕 Sprite ,只有 System.out.println 会触发通过服务器发送的 N 次。

如何让它在 System.out.println 开火后立即吸引敌人?

这是错误:

at ViewA.paint(ViewA.java:85)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent._paintImmediately(Unknown Source)
at javax.swing.JComponent.paintImmediately(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.access$700(Unknown Source)
at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

在 ViewA.paint(ViewA.java:85)

对应这一行:

        for (int i = 0; i < aliens.size(); i++) {
            Enemy a = (Enemy)aliens.get(i);
            if (a.isVisible())
                g2d.drawImage(a.getImage(), a.getX(), a.getY(), this);
        }

        g2d.setColor(Color.BLACK);
        g2d.drawString("BattleView: ", 5, 15);

最佳答案

从上往下看

编辑

  1. timer = new Timer(5, this); 5毫秒是所有Native OS延迟下的刷新频率,可以在25下玩或更多


  2. 删除整个代码块 public void addNotify() { 并替换为 getPreferredSize那么,

    a) 所有坐标均基于获取宽度/高度

    b) 在JPanel中绘制的对象可以使用JFrame调整大小

  3. 使用 paintComponent 进行 Swing JComponent 和 Java 中的自定义绘制,而不是 public void Paint(Graphics g) {

  4. public void actionPerformed(ActionEvent e) { 缺少用于以编程方式重绘的代码行 repaint()

  5. 不要对 Swing JComponents 使用 KeyListener,而是使用添加到 JPanelKeyBindings KeyListener

关于java - Sprite 在特定的 JPanel 上生成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17740163/

相关文章:

java - JUnit @理论 : is there a way to throw meaningful exception?

java - 运行 Play 框架项目

java - 使用 JOptionPane 显示容纳的数组

java - Java 中 JTextfield 的表单验证?

java - JPanel 可能重叠?

java - 框架未全屏显示

java - 为什么这个 HashMap 被作为引用传递

java - 在耶拿使用 model.remove (语句)

java - 一框内有 2 个不同宽度的面板

带有 JPanel 的 Java 布局管理器