2013-04-10 78 views
0

我正在開發一個學校項目的遊戲,一個類似炸彈人的遊戲。重繪()不叫

我使用的是swing,我使用畫布繪製圖形,但KeyListener沒有工作,所以我使用Canvas退出並開始使用paintComponent(Graphics g)。 KeyListener現在正在響應,但是當我的while循環調用repaint()方法時,我的圖形不刷新。

我的代碼:

dispose(); 

     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       board b = new board(); 
       b.setSize(630, 650); 
       b.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       b.setVisible(true); 
       direction dessin = new direction(); 
       b.add(dessin); 
       b.setVisible(true); 
       dessin.setBackground(Color.BLACK); 

      } 
     }); 

然後:

package Bm; 

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Toolkit; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.awt.image.BufferStrategy; 

import javax.swing.JComponent; 
import javax.swing.JPanel; 

@SuppressWarnings("serial") 
public class direction extends JPanel implements Runnable { 

static float bmx = 35; 
static float bmy = 35; 
static float ex = 520; 
static float ey = 520; 
static float v = 0.03f; 

static boolean gauche; 
static boolean droite; 
static boolean haut; 
static boolean bas; 

static void movEnnemi() { 

    int r = 1 + (int) (Math.random() * ((4 - 1) + 1)); 
    Ennemi.droite = false; 
    Ennemi.gauche = false; 
    Ennemi.bas = false; 
    Ennemi.haut = false; 

    switch (r) { 
    case 1: 
     Ennemi.droite = true; 
     break; 
    case 2: 
     Ennemi.gauche = true; 
     break; 
    case 3: 
     Ennemi.bas = true; 
     break; 
    case 4: 
     Ennemi.haut = true; 
     break; 
    } 

    try { 
     Thread.sleep(5); 
    } catch (Exception e) { 
    } 
    ; 

} 

public direction() { 
    super(); 
} 

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

    for (int ligne = 0; ligne < board.gridHauteur; ligne++) { 
     for (int colonne = 0; colonne < board.gridLargeur; colonne++) { 

      switch (board.plateau1[ligne][colonne]) { 
      case 0: 
       g.setColor(Color.lightGray); 
       g.fillRect(30 * ligne, 30 * colonne, 30, 30); 
       break; 
      case 1: 
       g.setColor(Color.black); 
       g.fillRect(30 * ligne, 30 * colonne, 30, 30); 
       board.plateau1[ligne][colonne] = board.BLOCKED; 
       break; 
      case 2: 
       g.setColor(Color.darkGray); 
       g.fillRect(30 * ligne, 30 * colonne, 30, 30); 
       board.plateau1[ligne][colonne] = board.BLOCKED; 
       break; 
      } 
     } 
    } 
    g.setColor(Color.blue); 
    g.fillRect((int) ex, (int) ey, 20, 20); 
    g.setColor(Color.red); 
    g.fillRect((int) bmx, (int) bmy, 21, 21); 
    g.dispose(); 
} 

public void run() { 

    long dernierTempsLoop = System.currentTimeMillis(); 

    while (true) { 

     long delta = (System.currentTimeMillis() - dernierTempsLoop); 
     dernierTempsLoop = System.currentTimeMillis(); 
     movEnnemi(); 

     for (int i = 0; i < delta/5; i++) { 
      logic(5); 
      Ennemi.logic(5); 
     } 
     if ((delta % 5) != 0) { 
      logic(delta % 5); 
      Ennemi.logic(delta % 5); 
     } 

     System.out.println((int) (bmx/30) + " - " + (int) (bmy/30)); 

     try { 
      Thread.sleep(20); 
     } catch (Exception e) { 
     } 
     ; 
     repaint(); // <== HERE 
    } 
} 

public static void logic(long delta) { 

    float dx = 0; 
    float dy = 0; 
    if (gauche) { 
     dx--; 
    } 
    if (droite) { 
     dx++; 
    } 
    if (haut) { 
     dy--; 
    } 
    if (bas) { 
     dy++; 
    } 
    if ((dx != 0) || (dy != 0)) { 
     joueur.mouvement(dx * delta * v, dy * delta * v); 
     if (joueur.mouvement((dx * delta * v), (dy * delta * v)) == false) { 
      if (joueur.mouvement(0, dy * delta * v)) { 
       joueur.mouvement(0, dy * delta * v); 
      } 
      if (joueur.mouvement(dx * delta * v, 0)) { 

       joueur.mouvement(dx * delta * v, 0); 
      } 
     } 
    } 
} 
} 

和:

package Bm; 

import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.util.Timer; 

import javax.swing.*; 

@SuppressWarnings("serial") 
class board extends JFrame implements KeyListener { 

static JPanel p; 
public Timer fpstimer; 
public direction g; 
static final int BLOCKED = 1; 
static int gridLargeur = 21; 
static int gridHauteur = 21; 
int fenLargeur = 630; 
int fenHauteur = 650; 
public static int plateau1[][] = { 
     { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 
     { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 
     { 1, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1 }, 
     { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 
     { 1, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1 }, 
     { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 
     { 1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1 }, 
     { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 
     { 1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1 }, 
     { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 
     { 1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1 }, 
     { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 
     { 1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1 }, 
     { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 
     { 1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1 }, 
     { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 
     { 1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1 }, 
     { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 
     { 1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1 }, 
     { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 
     { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; 

public board() { 
    super("Bomberman"); 
    g = new direction(); 
    addKeyListener(this); 
    threadLoop p = new threadLoop("loop"); 
    p.start(); 
} 

public static boolean blocked(double d, double e) { 

    return plateau1[(int) d][(int) e] == BLOCKED; 

} 

public void keyPressed(KeyEvent e) { 

    if (e.getKeyCode() == KeyEvent.VK_LEFT) { 
     direction.gauche = true; 
    } 
    if (e.getKeyCode() == KeyEvent.VK_RIGHT) { 
     direction.droite = true; 
    } 
    if (e.getKeyCode() == KeyEvent.VK_DOWN) { 
     direction.bas = true; 
    } 
    if (e.getKeyCode() == KeyEvent.VK_UP) { 
     direction.haut = true; 
    } 
    if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { 
     System.exit(0); 
    } 
} 

public void keyReleased(KeyEvent e) { 
    if (e.getKeyCode() == KeyEvent.VK_LEFT) { 
     direction.gauche = false; 
    } 
    if (e.getKeyCode() == KeyEvent.VK_RIGHT) { 
     direction.droite = false; 
    } 
    if (e.getKeyCode() == KeyEvent.VK_DOWN) { 
     direction.bas = false; 
    } 
    if (e.getKeyCode() == KeyEvent.VK_UP) { 
     direction.haut = false; 
    } 
} 

public void keyTyped(KeyEvent e) { 
} 
} 

class threadLoop extends Thread { 

public direction g; 

threadLoop(String name) { 
    super(name); 
} 

public void run() { 
    g = new direction(); 
    g.run(); 

} 

} 

public class Jouer { 
} 

我希望你明白我的問題,並能夠幫助我,謝謝: )

+0

Btw:'((4 - 1)+ 1)'就像寫作只是'4' – 2013-04-10 11:18:31

回答

2
  1. 你創建你的direction類的不同實例,因此,這個問題你看到
  2. 你不應該使用static喜歡這個。它違背了良好的OO編程
  3. 使用Swing鍵綁定而不是使用KeyListener
  4. 遵循java命名約定(您的代碼現在真的很難閱讀):類以大寫字母,方法和變量一個小寫字母。使用CamelCase連接單詞。
  5. 不要extend在不需要時(JFrameThread等)
  6. 儘量分開你的程序的各種概念(一個部分應該是負責顯示(顯示板,敵人的玩家),另一個對用戶輸入做出反應(左鍵按下,右鍵按下等)和第三個來處理你的遊戲邏輯(玩家位置,敵人位置,棋盤等)。 ))。

這裏是一個非常蹩腳的試圖解釋這些不同的意見:

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.util.Random; 

import javax.swing.AbstractAction; 
import javax.swing.ImageIcon; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 
import javax.swing.SwingUtilities; 

public class Game { 

    private static final String ICON_URL = "http://images2.wikia.nocookie.net/__cb20100515002803/fanon/images/a/a2/Bomberman_sprite.png"; 

    private static final int GRID_SIZE = 24; 
    private static final int SQUARE_SIZE = 30; 

    private JFrame frame; 

    private Board board; 

    private static class Board extends JPanel { 

     private int[][] grid; 

     private int playerX; 
     private int playerY; 

     private ImageIcon playerIcon; 

     public Board() throws MalformedURLException { 
      // Some code to generate a random pseudo-board 
      Random random = new Random(); 
      grid = new int[GRID_SIZE][]; 
      for (int i = 0; i < GRID_SIZE; i++) { 
       grid[i] = new int[GRID_SIZE]; 
       for (int j = 0; j < GRID_SIZE; j++) { 
        int r = random.nextInt(10); 
        grid[i][j] = r > 8 ? 2 : r > 6 ? 1 : 0; 
       } 
      } 
      playerIcon = new ImageIcon(new URL(ICON_URL)); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(GRID_SIZE * SQUARE_SIZE, GRID_SIZE * SQUARE_SIZE); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      // pseudo-board painting 
      for (int i = 0; i < grid.length; i++) { 
       for (int j = 0; j < grid[i].length; j++) { 
        switch (grid[i][j]) { 
        case 1: 
         g.setColor(Color.GREEN); 
         g.fillRect(i * SQUARE_SIZE, j * SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE); 
         break; 
        case 2: 
         g.setColor(Color.RED); 
         g.fillRect(i * SQUARE_SIZE, j * SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE); 
         break; 

        default: 
         break; 
        } 
       } 
      } 
      // Player painting 
      int x = playerX * SQUARE_SIZE + (SQUARE_SIZE - playerIcon.getIconWidth())/2; 
      int y = playerY * SQUARE_SIZE + (SQUARE_SIZE - playerIcon.getIconHeight())/2; 
      g.drawImage(playerIcon.getImage(), x, y, this); 
     } 

     public int getPlayerX() { 
      return playerX; 
     } 

     public int getPlayerY() { 
      return playerY; 
     } 

     public void setPlayerX(int playerX) { 
      if (playerX >= 0 && playerX < GRID_SIZE && grid[playerX][playerY] == 0) { 
       this.playerX = playerX; 
       repaint(); 
      } 
     } 

     public void setPlayerY(int playerY) { 
      if (playerY >= 0 && playerY < GRID_SIZE && grid[playerX][playerY] == 0) { 
       this.playerY = playerY; 
       repaint(); 
      } 
     } 
    } 

    private class MoveLeftAction extends AbstractAction { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      board.setPlayerX(board.getPlayerX() - 1); 
     } 

    } 

    private class MoveRightAction extends AbstractAction { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      board.setPlayerX(board.getPlayerX() + 1); 
     } 

    } 

    private class MoveUpAction extends AbstractAction { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      board.setPlayerY(board.getPlayerY() - 1); 
     } 

    } 

    private class MoveDownAction extends AbstractAction { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      board.setPlayerY(board.getPlayerY() + 1); 
     } 

    } 

    private class ExitAction extends AbstractAction { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      int i = JOptionPane.showConfirmDialog(board, "Are you sure you want to exit?"); 
      if (i == JOptionPane.YES_OPTION) { 
       System.exit(0); 
      } 
     } 

    } 

    protected void initUI() throws MalformedURLException { 
     frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setResizable(false); 
     board = new Board(); 
     board.setBackground(Color.BLACK); 
     board.registerKeyboardAction(new MoveLeftAction(), KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), JComponent.WHEN_FOCUSED); 
     board.registerKeyboardAction(new MoveRightAction(), KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), JComponent.WHEN_FOCUSED); 
     board.registerKeyboardAction(new MoveUpAction(), KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), JComponent.WHEN_FOCUSED); 
     board.registerKeyboardAction(new MoveDownAction(), KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), JComponent.WHEN_FOCUSED); 
     board.registerKeyboardAction(new ExitAction(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); 
     frame.add(board); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        new Game().initUI(); 
       } catch (MalformedURLException e) { 
        e.printStackTrace(); 
        JOptionPane.showMessageDialog(null, "Could not load icon from Internet", "Unable to start", JOptionPane.ERROR_MESSAGE); 
       } 
      } 
     }); 

    } 

} 

請注意,顯示和遊戲的邏輯在這裏完全交織在一起,所以我不太明白的建議NR 6.

1

direction您分配給幀/ board是不一樣的,你試圖繪製。你在你的主循環

創建一個新的參考我還建議你使用key bindings對關鍵聽衆

更新

您構建一個初始direction,然後添加到屏幕上。這實際上會呈現什麼。

direction dessin = new direction(); 
b.add(dessin); 

但是你threadLoop您創建一個新的(斷開)direction並開始嘗試更新了它......

public void run() { 
    g = new direction(); 
    g.run(); 
} 

...這永遠不會畫,因爲它具有屏幕不連接。

您還可以創建在board第三參考...

g = new direction(); 

所有這些斷開direction類沒有一個油漆或相互溝通,是不必要的。

我會在board創建一個單一的基準,將其添加到框架,並通過該參考threadLoop

更新

你可以在this看一看。這是一個基本的例子演示了遊戲資產的運動的簡單螺紋動畫引擎和鍵綁定

+0

我真的不知道你的意思,我正在等待我的程序運行正確使用鍵綁定:) – 2013-04-10 09:37:08

+0

在你的threadLoop類中,你創建了一個新的方向。這不會添加到任何可以實際繪製它的東西中,但是您將它用作渲染的基礎。它將無法呈現,它沒有連接到屏幕 – MadProgrammer 2013-04-10 09:44:19

+0

如果我刪除它,我得到這個錯誤「線程中的異常」循環「java.lang.NullPointerException \t at Bm.threadLoop.run(Jouer.java: 105)「我在做別的事嗎? – 2013-04-10 09:51:11