简体   繁体   English

Repaint()未调用

[英]Repaint() not called

I'm developing a game for a school project, a Bomberman-like game. 我正在为学校项目开发一款类似于Bomberman的游戏。

I'm using swing and I was using Canvas to draw my graphics but the KeyListener was not working, so I quitted using Canvas and started using paintComponent(Graphics g) . 我正在使用swing并且正在使用Canvas绘制图形,但是KeyListener无法正常工作,因此我退出使用Canvas并开始使用paintComponent(Graphics g) The KeyListener is responding now, but my graphics don't refresh when my while loop calls the repaint() methods. KeyListener现在正在响应,但是当我的while循环调用repaint()方法时,我的图形没有刷新。

My code: 我的代码:

    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);

            }
        });

Then: 然后:

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);
            }
        }
    }
}
}

And : 和:

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 {
}

I hope you understand my problem, and will be able to help me, thank you :) 希望您能理解我的问题,能为您提供帮助,谢谢:)

  1. You are creating different instances of your class direction , hence the issue you are seeing 您正在创建班级direction不同实例,因此会遇到问题
  2. You should not use static like this. 您不应该这样使用static It goes against good OO-programming 它与良好的OO编程背道而驰
  3. Use Swing key-bindings instead of using KeyListener 使用Swing键绑定,而不是使用KeyListener
  4. Follow java naming conventions (your code is really hard to read for now): Classes start with an Upper case letter, methods and variables with a lower-case letter. 遵循Java命名约定(您的代码现在真的很难阅读):类以大写字母开头,方法和变量以小写字母开头。 Use CamelCase to concatenate words. 使用CamelCase连接单词。
  5. Don't extend when not needed ( JFrame , Thread , etc...) 不要在不需要时extendJFrameThread等)
  6. Try to separate the various concepts of your program (one part should be responsible for the display (displaying the board, the enemies, the player), another one to react on user input (left-key pressed, right-key pressed, etc...) and a third one to handle the logic of your game (player location, enemies location, the board, etc...)). 尝试分离程序的各种概念(一部分应负责显示(显示棋盘,敌人,玩家),另一部分应根据用户输入做出反应(按左键,按右键等)。 ..)和第三个用于处理游戏逻辑(玩家位置,敌人位置,棋盘等)的游戏。

Here is a very lame attempt to explain those various advices: 这是解释这些建议的非常la脚的尝试:

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);
                }
            }
        });

    }

}

Please note that the display and the logic of the games are here completely intertwined, so I don't quite follow advice nr 6. 请注意,这里的显示和游戏逻辑是完全交织在一起的,所以我不太遵循建议6。

The direction you assign to the frame/ board is not the same you a trying to paint to. 您分配给框架/ boarddirection与您尝试绘制的方向不同。 You create a new reference in your main loop 您在主循环中创建一个新引用

I'd also suggest you use key bindings over key listeners 我还建议您在按键监听器上使用按键绑定

Updated 更新

You construct a initial direction and then add that to the screen. 您构造一个初始direction ,然后将其添加到屏幕。 This is actually what will be rendered. 这实际上是将要呈现的内容。

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

But in your threadLoop you create a new (disconnected) direction and start trying to update it... 但是在您的threadLoop您创建了一个新的(断开连接) direction并开始尝试对其进行更新...

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

...this will never paint as it has no connection to the screen. ...这将永远无法绘制,因为它与屏幕没有连接。

You also create a third reference in board ... 您还可以在board创建第三个引用...

g = new direction();

All these disconnected direction classes have no one to paint or communicate with each and are unnecessary. 所有这些不连贯的direction类都没有一个可以绘画或与每个direction类通信,因此是不必要的。

I would create a single reference in board , add it to the frame and pass that reference to the threadLoop 我将在board创建单个引用,将其添加到框架中,然后将该引用传递给threadLoop

Updated 更新

You could take a look at this . 你可以看看这个 It's a basic example demonstrating a simple threaded animation engine and key bindings for the movement of a game asset 这是一个基本示例,展示了用于游戏资产移动的简单线程动画引擎和按键绑定

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM