2013-06-27 104 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,而是直接绘制一个容器。