繁体   English   中英

Component.setBounds调用Component.repaint吗?

[英]Component.setBounds invoking Component.repaint?

所以我正在做一个游戏,我有EnemyAIplayer ,他们都扩展了JPanel 世界的布局为null ,因此我正在使用setBounds(); 以“移动”(实际上我只是移动世界图像)周围的entitiesplayerAI )并正确放置它们。 但是,当我添加(看起来,我已经测试了最小的数目)5时,它完全自己调用了repaint() 这导致玩家在视觉上行走到位。 我添加的实体越多,间隔就越快(即5个实体调用repaint()的速度比500慢得多)。

注意: JFrame下的window只是一个JFrame

主类:

public class Game(){
public static boolean fighting = false;
public static void startGame(){
    WorldPanel game = new WorldPanel();
    game.setPreferredSize(new Dimension(window.getWidth(), window.getHeight()));
    PlayerPane player = new PlayerPane(32,32, "Player 1");
    game.addKeyListener(new KeyListener(){

        public void keyPressed(KeyEvent arg0) {
            if(fighting == false){
                move(player, game, arg0.isShiftDown(), arg0.getKeyCode());
            } else {
                System.out.println("Fighting = " + fighting);
            }
        }
        @Override
        public void keyReleased(KeyEvent arg0) {    
            gameTimer.stop();
            player.setIndex(0);
            game.repaint();
        }
        @Override
        public void keyTyped(KeyEvent arg0) {
        }
    });
    window.add(game);
    game.setLayout(null);
    game.requestFocus();
    setImages(player, PLAYER_DOWN);
    player.setDrawY(349);
    player.setDrawX(493);
    player.updateBounds();
    game.add(player);
    entities.add(player);
    addEntities(game);
    redoWindow();
}
public static void updateEntityBounds(){
    PlayerPane player = null;
    EnemyAI enemy = null;
    for(int i = 0; i < entities.size(); i++){
        if(i == 0){
            player = (PlayerPane) entities.get(i);
        } else {
            enemy = (EnemyAI) entities.get(i);
            if(enemy.getBounds().intersects(player.getBounds())){
                startFight(i);
            }
        }
        if(player != null){
            player.updateBounds();
        }
        if(enemy != null){
            enemy.updateBounds();
        }
    }
}
public static void addEntities(WorldPanel game){
    EnemyAI enemies[] = new EnemyAI[5];
    for(int i = 0; i < enemies.length; i++){
        if(i%6 == 0){
            try{
                enemies[i] = new EnemyAI(32,32, ImageIO.read(new File("H:\\Java\\Game\\src\\res\\SlimeLv3Still.png")));
                enemies[i].start();
            }catch(IOException e){
                e.printStackTrace();
            }
        }else if (i % 2 == 0){
            try{
                enemies[i] = new EnemyAI(32,32, ImageIO.read(new File("H:\\Java\\Game\\src\\res\\SlimeLv2Still.png")));
                enemies[i].setEnX(enemies[i].getRandomX());
                enemies[i].setEnY(enemies[i].getRandomY());
                enemies[i].start();
            }catch(IOException e){
                e.printStackTrace();
            }
        } else {
            try{
                enemies[i] = new EnemyAI(32,32, ImageIO.read(new File("H:\\Java\\Game\\src\\res\\SlimeLv1Still.png")));
                enemies[i].setEnX(enemies[i].getRandomX());
                enemies[i].setEnY(enemies[i].getRandomY());
                enemies[i].start();
            }catch(IOException e){
                e.printStackTrace();
            }
        }
        game.add(enemies[i]);
        entities.add(enemies[i]);
    }
}
    public static void move(PlayerPane player, WorldPanel game, boolean shiftDown, int keyPressed){
     gameTimer = new Timer(50, new ActionListener(){
        public void actionPerformed(ActionEvent e){
            updateEntityBounds();
            redoWindow();
            gameTimer.stop();
        }
    });
    if(gameTimer.isRepeats()){
        gameTimer.setRepeats(false);
    }
        if(shiftDown){
            if(keyPressed == KeyEvent.VK_W && ((game.getImageY() == 0 && player.getDrawY() > 10) || player.getDrawY() >= 349)){
                player.setDrawY(player.getDrawY() - 2);
                setImages(player, PLAYER_UP);
                gameTimer.start();
            } else
            if(keyPressed == KeyEvent.VK_S && ((game.getImageY() == -3868 && player.getDrawY() < 681) || player.getDrawY() <= 349)){
                player.setDrawY(player.getDrawY() + 2);
                setImages(player, PLAYER_DOWN);
                gameTimer.start();
            } else
            if(keyPressed == KeyEvent.VK_A && ((game.getImageX() == 0 && player.getDrawX() > 10) || player.getDrawX() > 493 )){
                player.setDrawX(player.getDrawX() - 2);
                setImages(player, PLAYER_LEFT);
                gameTimer.start();
            } else
            if(keyPressed == KeyEvent.VK_D && ((game.getImageX() == -5126 && player.getDrawX() < player.getHeight() - 10) || player.getDrawX() < 493 )){
                player.setDrawX(player.getDrawX() + 2);
                setImages(player, PLAYER_RIGHT);
                gameTimer.start();
            } else
            if(keyPressed == KeyEvent.VK_W && game.getImageY() < 0){
                if(game.getImageY() == -1){
                    game.setImageY(game.getImageY() + 1);
                } else {
                    game.setImageY(game.getImageY() + 2);
                }
                for(int i = 1; i < entities.size(); i++){
                    EnemyAI enemy = (EnemyAI)entities.get(i);
                    enemy.setEnY(enemy.getEnY() + 2);
                }
                setImages(player, PLAYER_UP);
                gameTimer.start();
            } else
            if(keyPressed == KeyEvent.VK_A && game.getImageX() < 0){
                if(game.getImageX() == -1){
                    game.setImageX(game.getImageX() + 1);
                } else {
                    game.setImageX(game.getImageX() + 2);
                }
                for(int i = 1; i < entities.size(); i++){
                    EnemyAI enemy = (EnemyAI)entities.get(i);
                    enemy.setEnX(enemy.getEnX() + 2);
                }
                setImages(player, PLAYER_LEFT);
                gameTimer.start();
            } else
            if(keyPressed == KeyEvent.VK_S && game.getImageY() > -3868){
                if(game.getImageY() == -3867){
                    game.setImageY(game.getImageY() - 1);
                } else {
                    game.setImageY(game.getImageY() - 2);
                }
                for(int i = 1; i < entities.size(); i++){
                    EnemyAI enemy = (EnemyAI)entities.get(i);
                    enemy.setEnY(enemy.getEnY() - 2);
                }
                setImages(player, PLAYER_DOWN);
                gameTimer.start();
            } else
            if(keyPressed == KeyEvent.VK_D && game.getImageX() > -5126){
                if(game.getImageX() == -5125){
                    game.setImageX(game.getImageX() - 1);
                } else {
                    game.setImageX(game.getImageX() - 2);
                }
                for(int i = 1; i < entities.size(); i++){
                    EnemyAI enemy = (EnemyAI)entities.get(i);
                    enemy.setEnX(enemy.getEnX() - 2);
                }
                setImages(player, PLAYER_RIGHT);
                gameTimer.start();

            }
        } else {
            if(keyPressed == KeyEvent.VK_W && ((game.getImageY() == 0 && player.getDrawY() > 10) || player.getDrawY() > 349)){
                player.setDrawY(player.getDrawY() - 1);
                setImages(player, PLAYER_UP);
                gameTimer.start();
            } else
            if(keyPressed == KeyEvent.VK_S && ((game.getImageY() == -3868 && player.getDrawY() < 681) || player.getDrawY() < 349)){
                player.setDrawY(player.getDrawY() + 1);
                setImages(player, PLAYER_DOWN);
                gameTimer.start();
            } else
            if(keyPressed == KeyEvent.VK_A && ((game.getImageX() == 0 && player.getDrawX() > 10) || player.getDrawX() > 493 )){
                player.setDrawX(player.getDrawX() - 1);
                setImages(player, PLAYER_LEFT);
                gameTimer.start();
            } else
            if(keyPressed == KeyEvent.VK_D && ((game.getImageX() == -5126 && player.getDrawX() < player.getHeight() - 10) || player.getDrawX() < 493 )){
                player.setDrawX(player.getDrawX() + 1);
                setImages(player, PLAYER_RIGHT);
                gameTimer.start();
            } else
                if(keyPressed == KeyEvent.VK_W && game.getImageY() < 0){
                game.setImageY(game.getImageY() + 1);
                setImages(player, PLAYER_UP);
                for(int i = 1; i < entities.size(); i++){
                    EnemyAI enemy = (EnemyAI)entities.get(i);
                    enemy.setEnY(enemy.getEnY() + 1);
                }
                gameTimer.start();
            } else
            if(keyPressed == KeyEvent.VK_A && game.getImageX() < 0){
                game.setImageX(game.getImageX() + 1);
                setImages(player, PLAYER_LEFT);
                for(int i = 1; i < entities.size(); i++){
                    EnemyAI enemy = (EnemyAI)entities.get(i);
                    enemy.setEnX(enemy.getEnX() + 1);
                }
                gameTimer.start();

            } else
            if(keyPressed == KeyEvent.VK_S && game.getImageY() > -3868){
                game.setImageY(game.getImageY() - 1);
                setImages(player, PLAYER_DOWN);
                for(int i = 1; i < entities.size(); i++){
                    EnemyAI enemy = (EnemyAI)entities.get(i);
                    enemy.setEnY(enemy.getEnY() - 1);
                }
                gameTimer.start();                              
            } else
            if(keyPressed == KeyEvent.VK_D && game.getImageX() > -5126){
                game.setImageX(game.getImageX() - 1);
                setImages(player, PLAYER_RIGHT);
                for(int i = 1; i < entities.size(); i++){
                    EnemyAI enemy = (EnemyAI)entities.get(i);
                    enemy.setEnX(enemy.getEnX() - 1);
                }
                gameTimer.start();
            }
        }
    }
}

玩家:

public class PlayerPane extends JPanel{
    private static final long serialVersionUID = 8946273935579723365L;
    private ImageIcon images[] = new ImageIcon[9];
    public static final int PLAYER_FRAMES = 9;
    private String name;
    private int index;
    private int imageX, imageY;
    private int HP = 100;



    public PlayerPane(int width, int height, String playerName) {
            setPreferredSize(new Dimension(width, height));
            imageX = imageY = 0;
            name = playerName;
        //      Border border = BorderFactory.createBevelBorder(BevelBorder.RAISED);
        //      PlayerPane.this.setBorder(border);
        }
        public String getName(){
            return name;
        }
        public void paintComponent(Graphics g){
            try {
                g.drawImage(ImageIO.read(new File("H:\\Java\\Game\\src\\res\\TransparentImg.png")),0,0,getWidth(),getHeight(), null);
            } catch (IOException e) {
                e.printStackTrace();
            }
                g.drawImage(images[index].getImage(), 0,0, null);

            if(index == images.length-1){
                index = 0;
            } else {
                index++;
            }
        }
        public void setIndex(int index){
            this.index = index;
        }
        public void stop(){
            index = 0;
        }
        public void addImage(ImageIcon image, int x){
            images[x] = image;
        }
        public void setDrawX(int x){
            imageX = x;
        }
        public void setDrawY(int y){
            imageY = y;
        }
        public int getDrawY(){
            return imageY;
        }
        public int getDrawX(){
            return imageX;
        }
        public void updateBounds(){
            setBounds(imageX, imageY, 32,32);
        }
        public int getHP(){
                return HP;
            }
            public void setHP(int hp){
                HP = hp;
            }
        }

EnemyAI类:

public class EnemyAI extends AI{
    private static final long serialVersionUID = -2417438750134536982L;

    private Rectangle rect;
    private BufferedImage backgroundImg;
    private int HP = 1;
    private int damage = 15;

    public EnemyAI(int width, int height, BufferedImage backgroundImg){
        super();
        rect = new Rectangle(width, height);
        this.backgroundImg = backgroundImg;
    }
    @Override
    public void paintComponent(Graphics g) {
        try{
            g.drawImage(ImageIO.read(new File("H:\\Java\\Game\\src\\res\\TransparentImg.png")), 0,0,null);
        }catch(IOException e){
            e.printStackTrace();
        }

        g.drawImage(backgroundImg, 0, 0, null);
    }
    public boolean intersects(Rectangle r){
        return rect.intersects(r);
    }
    public int getRandomX(){
        Random ran = new Random();
        int rand = ran.nextInt(6144);
        return rand;
    }
    public int getRandomY(){
        Random ran = new Random();
        int rand = ran.nextInt(4608);
        return rand;
    }
    public int getHP(){
        return HP;
    }
    public void setHP(int hp){
        HP = hp;
    }
    public int getDamage(){
        return damage;
    }
}

以上课程扩展的AI课程:

public abstract class AI extends JPanel implements Runnable{
    private static final long serialVersionUID = 283692586329054555L;

    private boolean running = false;
    private Thread moveThread;
    private int x = 0, y = 0;

    public AI(){
        moveThread = new Thread(this);
    }
    public void start(){
        running = true;
        moveThread.start();
    }
    public void stop(){
        running = false;
    }
    public boolean isRunning(){
        return running;
    }

    public void run(){
        while(running){
            if(Game.fighting == false){
                Random direction = new Random();
                int dir = direction.nextInt(4);
                switch(dir){
                case 1: 
                    if(this.getX() < Game.getWindowWidth()){
                    this.setEnX(this.getX() + 1);
                    }
                    break;
                case 2:
                    if(this.getX() > 0){
                        this.setEnX(this.getX() - 1);
                    }
                    break;
                case 3:
                    if(this.getX() < Game.getWindowHeight()){
                        this.setEnY(this.getY() + 1);
                    }
                    break;
                case 4:
                    if(this.getX() < 0){
                        this.setEnY(this.getY() - 1);
                    }
                    break;
                }
                updateBounds();
                try{
                    Thread.sleep(200);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
        }
    }
    public void setEnX(int x){
        this.x = x;
    }
    public void setEnY(int y){
        this.y = y;
    }
    public int getEnX(){
        return x;
    }
    public int getEnY(){
        return y;
    }
    public void updateBounds(){
        setBounds(x, y, 32,32);
    }
    public abstract void paintComponent(Graphics g);
}

我了解我只是向你们扔了很多代码。 我尝试不这样做,但是回头看一下,我试图提供一个运行示例。 如果我错过任何代码,请告诉我,然后我将其添加。

无论如何,我需要知道的是如何使setBounds()停止调用repaint() (除了使用少于5个entities )。 另外,添加entities时我也删除了EnemyAI.start()并确实停止了它。 因此,我有理由相信问题出在AIrun()方法之内。 几乎只是调用setBounds()

这是正常现象,这就是为什么您不能在paintComponent内修改状态。 我们无法控制何时进行重绘:系统有时会自行进行重绘。

这是我的意思的示例,您不应该这样做:

public class PlayerPane extends JPanel{
    ...

    public void paintComponent(Graphics g){
        ...

        // modifying index
        if(index == images.length-1){
            index = 0;
        } else {
            index++;
        }
    }
}

您需要遍历所有代码,以查找在paintComponent内修改了此类变量的每个位置,然后将其移至其他位置。

附带说明一下,还应该移动ImageIO.read调用,使它们不在paintComponent 程序启动后,将图像加载到static变量或类似的变量中。

作为一般提示,您应该只用绘画来观看动画,而不是尝试对组件进行动画处理。 从长远来看,它将为您带来巨大的好处。


因此,总而言之:

  • 保持paintComponent无状态。
  • 在非UI对象中以游戏/动画状态包装图像。
  • paintComponent绘制这些图像。

这是一个最小的示例,它通过动画落在窗口上的形状来演示这一点:

下降的形状

import java.net.*;
import javax.swing.*;
import javax.imageio.*;
import java.awt.image.*;
import java.awt.event.*;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.Graphics;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;

class FallingShapes implements Runnable {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new FallingShapes());
    }

    @Override
    public void run() {
        List<Entity> entities = new ArrayList<Entity>();

        int w = 0;
        int h = 0;

        for (BufferedImage img : Resources.images) {
            entities.add(new Entity(img));

            w += img.getWidth();
            h += img.getHeight();
        }

        PaintPanel p = new PaintPanel(entities);
        p.setPreferredSize(new Dimension(w, (2 * h)));

        JFrame f = new JFrame();

        f.setContentPane(p);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setResizable(false);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);

        new Animator((1000 / 60), p, entities).start();
    }

    static class Animator implements ActionListener {
        int period;
        JPanel context;
        int height;
        List<Entity> entities;

        Animator(int period, JPanel context, List<Entity> entities) {
            this.context  = context;
            this.height   = context.getHeight();
            this.period   = period;
            this.entities = entities;
        }

        @Override
        public void actionPerformed(ActionEvent a) {
            for (Entity e : entities) {
                double dist =
                    (period / 1000.0) * (height * e.rate);

                e.y += dist;
                e.y %= height;
            }

            context.repaint();
        }

        void start() {
            Random r = new Random();
            int    x = 0;
            for (Entity e : entities) {
                e.x    = x;
                e.y    = r.nextInt(height);
                e.rate = (0.25 + (0.75 * r.nextDouble()));

                x += e.width;
            }

            new Timer(period, this).start();
        }
    }

    static class Entity {
        BufferedImage img;

        double x, y, rate;
        int width, height;

        Entity(BufferedImage img) {
            this.img    = img;
            this.width  = img.getWidth();
            this.height = img.getHeight();
        }

        void paint(Graphics g, JPanel context) {
            int x = (int) Math.round(this.x);
            int y = (int) Math.round(this.y);
            g.drawImage(img, x, y, null);

            int cHeight = context.getHeight();
            if ((y + height) > cHeight) {
                g.drawImage(img, x, y - cHeight, null);
            }
        }
    }

    static class PaintPanel extends JPanel {
        List<Entity> entities;

        PaintPanel(List<Entity> entities) {
            this.entities = entities;

            setBackground(Color.white);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            for (Entity e : entities) {
                e.paint(g, this);
            }
        }
    }

    static class Resources {
        static final String[] paths = {
            "http://i.stack.imgur.com/wCF8S.png",
            "http://i.stack.imgur.com/5v2TX.png",
            "http://i.stack.imgur.com/F0JHK.png",
            "http://i.stack.imgur.com/4EVv1.png",
            "http://i.stack.imgur.com/xj49g.png",
        };

        static final List<BufferedImage> images =
            new ArrayList<BufferedImage>();
        static {
            for (String path : paths) {
                try {
                    images.add(ImageIO.read(new URL(path)));
                } catch (Exception e) {
                    throw new AssertionError(e);
                }
            }
        }
    }
}

(图片来自这里 。)

动画和绘画的其他有用示例:

暂无
暂无

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

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