2013-06-27 109 views
0

即時創造一個小小的「遊戲」,就像2D AirForce射手。 所以,我有刪除未使用的enemys問題。如何刪除JPanel對象?

敵人是一個簡單的JPanel,它作爲數組List保存在主邏輯中。

public static ArrayList<Enemy> enemys = new ArrayList<Enemy>(); 

敵人運行邏輯將執行以下操作:

while(!destroyed){ 
     if(Game.running){ 
      x--; 
      if(getBounds().intersects(Field.player.getBounding())){ 
       Player.death = true; 
      } 
      if(x < 0){ 
       Field.deleteEnemy(this); 
      } 
      setBounds((int) x, (int) y, 100, 50); 
      try{Thread.sleep(10);}catch(InterruptedException e){} 
     } 
    } 

所以,你可以有似乎我已經試着撥打方法deleteEnemy,只是給它未使用的敵人。

但它不是可能的 - 當我只是這樣做:

public static void deleteEnemy(Enemy e){ 
    System.out.println("test"); 
    enemys.remove(e); 
} 

它會從列表中刪除剛,但coninues現有的主要的JPanel。 我不能說

remove(e); 

因爲那時我嘗試調用靜態非靜態函數。 那麼,我怎麼能刪除敵人?有人知道嗎?

感謝您的幫助!

孔代碼:(Game.java)

而且,Enemy.java:

package Game; 

import java.awt.*; 
import java.awt.event.*; 
import java.util.ArrayList; 

import javax.swing.JOptionPane; 
import javax.swing.JPanel; 

public class Field extends JPanel implements Runnable{ 


    public static Player player = new Player(); 
    public static ArrayList<Enemy> enemys = new ArrayList<Enemy>(); 
    private Thread moveBackground = new Thread(this); 
    private boolean bgMoving = false; 
    public static boolean addMob = false; 
    private int x = 0; 
    private int bgSpeed = -1; 


    public Field(){ 
     setBounds(0, 0, 800, 600); 
     setFocusable(true); 
     setLayout(null); 
     addKeyListener(new Handler()); 

     add(player); 
    } 

    public void paintComponent(Graphics g){ 
     Field.super.paintComponent(g); 
     g.drawImage(Images.images[0], x, 0, this); 
    } 

    public static void deleteEnemy(Enemy e){ 
     System.out.println("test"); 
     enemys.remove(e); 
    } 

    public void run(){ 
     while(!Player.death){ 
      if(bgMoving){ 
       bgMoving = true; 
       x += bgSpeed; 
       if(x < -(Images.images[0].getWidth(this) - this.getWidth() - 20)){ 
        bgMoving = false; 
       } 
       repaint(); 
       try { Thread.sleep(20); } catch (InterruptedException e) {} 
      } 
      if(addMob){ 
       enemys.add(new Enemy()); 
       add(enemys.get(enemys.size() - 1)); 
       addMob = false; 
      } 
     } 
     JOptionPane.showMessageDialog(null, "DIED!"); 
    } 

    public class Handler extends KeyAdapter { 

     public void keyPressed(KeyEvent e) { 
      player.KeyPressed(e); 
      if(!bgMoving){ 
       if(Game.running){ 
        bgMoving = true; 
        if(moveBackground.getState().toString() == "NEW"){ 
         moveBackground.start(); 
        } 
       } 
      } 
     } 

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

    } 

} 

而且,Enemy.java:

package Game; 

import java.awt.Color; 
import java.awt.Graphics; 
import javax.swing.JPanel; 

public class Enemy extends JPanel implements Runnable{ 

    Thread t = new Thread(this); 
    private double x = Game.width(); 
    private double y = Math.random() * Game.height(); 
    private double xF = 0, yF = 0; 
    private boolean destroyed = false; 

    public Enemy(){ 
     setBounds((int) x, (int) y, 100, 50); 
     setOpaque(false); 
     t.start(); 
    } 

    public void paintComponent(Graphics g){ 
     Enemy.super.paintComponent(g); 
     g.setColor(Color.GREEN); 
     g.drawImage(Images.images[2], 0, 0, this); 
    } 

    public void run() { 
     while(!destroyed){ 
      if(Game.running){ 
       x--; 
       if(getBounds().intersects(Field.player.getBounding())){ 
        Player.death = true; 
       } 
       if(x < 0){ 
        Field.deleteEnemy(this); 
       } 
       setBounds((int) x, (int) y, 100, 50); 
       try{Thread.sleep(10);}catch(InterruptedException e){} 
      } 
     } 
    } 
} 
+3

爲了更快提供更好的幫助,請發佈[SSCCE](http://sscce.org/)。 *「洞代碼:」*不僅人們通常不希望看到整個代碼,但顯然這不是整個代碼,因爲它不是一個小程序,並且沒有'main(String [ ])'定義。最好發佈SSCCE .. –

+0

整個遊戲中唯一的靜態方法或字段應該是啓動GUI的主要方法。 –

回答

0

你在哪裏添加EnemyJPanel

基本上,你應該叫去除FieldJPanel

public void deleteEnemy(Enemy e){ 
    System.out.println("test"); 
    enemys.remove(e); 
    this.remove(e); 
} 

的方法不應該是static

+0

問題是,我嘗試從靜態上下文中調用此方法... – GFP

+0

考慮到他/她的數組是靜態的,我不能看到這導致問題(不是它的一個好設計)。但我沒有看到數組用於什麼,無處不在數組正在迭代和'JPanel's使用..所以從數組中刪除它什麼也不做,我猜OP需要從它的容器中刪除'JPanel'使用'組件#remove(組件c)' –

1

[過長評論]

我認爲這個問題是在邏輯上移除Enemy/JPanel

你是隻將其從ArrayList中刪除,那麼您將其添加到的JPanel/JFrame? 您必須從其容器(可能是另一個JPanelJFrame)中刪除JPanel,而不是通過Component#remove(Component c)刪除ArrayList

如果您通過迭代ArrayList直接在容器的paintComponent(...)中繪製敵人圖像;將它從ArrayList中刪除就足夠了,因爲它將不再位於陣列中,因此不會再在下一個repaint()上繪製。

+1 @optional,您可能需要調用revalidate()repaint()在容器上的的去除JPanel/Enemy要顯示的影響。

另外,作爲@darijan提到,靜態變量和實例一起使用並不是一個很好的設計(儘管對於某些設計來說這可能很好)。

在你的情況下,如果你需要訪問另一個類中的另一個類的實例方法,只需將你希望訪問的類的實例傳遞給將訪問它的對象。

這裏是表達太多的上述問題/解決方案一些僞代碼:

public class Field extends JPanel { 
    private ArrayList<Enemy> enemies; 

    public Field() { 
     ... 

     enemies.add(new Enemy(this));//create a new enemy and pas it the JPanel instance so it may access instance methods of this class 
    } 

    //ONLY USED IF JPanel for Enemy is ommited and Enemy class created which represents Enemy object and not Enemy object and aJPanel 
    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 

     ArrayList<Enemy> enemiesClone = new ArrayList<>(enemies);//copy array into another so we don't get a ConcurrentModificaton exception if removeEnemy is called while iterating the list 
     if(!enemiesClone.isEmpty()) 
      for(Enemy e:enemiesClone) {//iterate through array of images 
       draw(e.getImage(),e.getX(),e.getY(),this); 
      } 
    } 

    public void removeEnemy(Enemy e) { 
     enemies.remove(e);//remove from the array 

     //ONLY USED IF JPanels are used as Enemy 
     remove(e);//remove from the JPanel 
     //so the changes of removed panel can be visible seen 
     revalidate(); 
     repaint(); 
    } 
} 

class Enemy extends JPanel //extends JPanel should be ommited for paintComponent method of drawing an enemy onscreen 
{ 
    private int x,y; 
    private BufferedImage image; 
    private Field f; 

    public Enemy(Field f) {//constructor accepts Field instance to access instance method for the class 
     this.f=f; 
    } 

    public void update() { 
     if(offscreen||dead) { 
      f.removeEnemy(this);//call removeEnemy which is an instance method of Field 
     } 
    } 

    //BELOW METHODS ONLY USED WHEN Enemy represents object and not a JPanel which can draw its image itself (and update position by simply changing co-ordinates) 

    public BufferedImage getImage() { 
     return image; 
    } 
    public int getX() { 
     return x; 
    } 
    public int getY() { 
     return y; 
    } 
} 

如需更詳細的外觀檢查Game Development Loop, Logic and Collision detection Java Swing 2D我做了,這將給你所需要的大部分2D遊戲的基本知識。但是我不使用JPanel,而是直接繪製一個容器。