Java游戏滞后,如果声明太多了?

时间:2016-06-22 01:06:43

标签: java jpanel keylistener

我正在使用基于Atari游戏冒险的java游戏。我得到了基本的KeyListener部分工作正常,但后来我添加了另一个if语句,使用另一个类来测试玩家是否要撞墙,如果是这样的话就停止移动。我使用的方法也使用if语句,当我运行代码时,它有MAJOR滞后。我先尝试了一个while循环,但这使得它更加滞后。无论如何要让这不是那么多滞后?看起来运行程序看起来并不复杂,我仍然需要添加另一个if语句才能进入另一个房间,所以我必须做一些事情来大规模减少延迟。

这是班级:

class Player extends JPanel implements KeyListener{
   private char c = 'e';
   int x = 400;
   int y = 400;
   int mapX = 0;
   int mapY = 0;


   public Player() {
      this.setPreferredSize(new Dimension(800, 500));
      addKeyListener(this);  
   }

   public void addNotify() {
      super.addNotify();
      requestFocus();
   }
   public void paintComponent(Graphics g) {
      super.paintComponent(g);
      Environment Layout = new Environment();
      Layout.drawRoom(mapX,mapY,g);
      g.fillRect(x , y , 20, 20);       
   }
   public void keyPressed(KeyEvent e) { }
   public void keyReleased(KeyEvent e) { }
   public void keyTyped(KeyEvent e) {
      c = e.getKeyChar();
      repaint();
      Environment Layout = new Environment();
      if(Layout.isWall(x,y,c)){}
      else{
         if (c == 'a'){
            x = x - 3;
         }
         else if (c == 'w'){
            y = y - 3;
         }
         else if (c == 's'){
            y = y + 3;
         }
         else if (c == 'd'){
            x = x + 3;
         }         
      }
   }

   public static void main(String[] s) throws IOException{
      JFrame f = new JFrame();
      f.getContentPane().add(new Player());
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      f.pack();
      f.setVisible(true);
   }
}

我在这里使用的抽奖室方法只是为了把房间的背景放到位。

以下是Environment类的isWall方法:

public boolean isWall(int moveX, int moveY, char let){
      BufferedImage room = null;
      try {
         room = ImageIO.read(new File(xNum + "," + yNum + ".png"));
      } 
      catch (IOException e) {
      }  
      int[][] walls = convertImage(room);   
      boolean blocked = false;
      if(let == 'w') {
         if(walls[moveY-8][moveX] == -3584){blocked = true;}
      }
      else if(let == 's') {
         if(walls[moveY+20][moveX] == -3584){blocked = true;}
      }
      else if(let == 'a') {
         if(walls[moveY][moveX-5] == -3584){blocked = true;}
      }
      else if(let == 'd') {
         if(walls[moveY][moveX+20] == -3584){blocked = true;}
      }
      return blocked;      
   } 

convertImage方法只是将房间的图像转换为int数组,用于颜色的值。 -3584是墙壁的颜色。可能这就是它的落后之处,但这似乎是每个房间自动完成墙壁的最佳方式。

我也试过一个计时器,但要么我做错了,要么就是没有帮助。

如果需要,我可以提供更多代码,但是对此的帮助将非常感激。我对这种东西比较陌生,所以很可能我错过了一些大事。感谢。

3 个答案:

答案 0 :(得分:4)

这里的滞后几乎肯定不是来自if陈述。那些真的很快。我认为更大的问题出在isWall。请注意,只要您想检查墙是否存在,就

  1. 打开文件
  2. 阅读文件内容,
  3. 将文件内容从图像转换为像素网格,
  4. 只读一个像素。
  5. 与查看内存中的值相比,从磁盘读取文件非常慢。例如,常规磁性硬盘驱动器的工作频率约为7200 RPM,因此寻道时间以毫秒为单位。另一方面,您的处理器每秒可以执行大约10亿次操作,因此其他操作需要几纳秒。这意味着,与其他操作相比,磁盘读取的速度大约是百万分之一,这几乎可以肯定您将从中获得延迟!

    要解决此问题,请考虑重写您的isWall代码,以便只读取文件并进行一次转换,然后执行此操作,然后只需查找所需图像部分即可。这会将大量(冰冷)文件读取转换为单个(缓慢但不可避免)文件读取,然后进行大量快速内存读取。

答案 1 :(得分:0)

你似乎比移动玩家更进一步移动墙壁。

通过制作" blocked = true&#34>,你的玩家对象是否可能卡在墙上?连续?

你的角色在每个方向上都会得到+ - 3,但是你的墙壁似乎不一致,范围从8到20到5到左到右20。

答案 2 :(得分:0)

这是对@ templatetypedef的回答的扩展。

除了在调用isWall方法时加载图像文件,您可能还需要考虑在游戏开始时缓存所有墙。

所以我在想;

  1. 具有由<String, Integer>键控的HashMap数据结构。 String是你的坐标。例如。坐标字符串=&#34; 100,238&#34;
  2. 解析目录中的所有.png图像文件,并将坐标存储为键,值可以是任何虚拟值,如1或2。
  3. 然后调用isWall()。给定X和Y坐标,构建坐标字符串,如第1点所述,并检查密钥是否存在。如果确实如此,那么我们就知道它不是一块墙。
  4. 这应该会大大减少I / O磁盘争用。

    将来,如果您希望扩展解决方案以合并诸如isTreasureChest()或isMonster()之类的API。它可以通过构建一个不可变的类调用来扩展&#34; Room&#34;或&#34; Tile&#34;代表对象。然后修改HashMap以接收<String, Room>

相关问题