JPanel中的多个动画(线程)

时间:2015-02-02 17:02:29

标签: java multithreading swing animation jpanel

我正在尝试用Java编写棋盘游戏。

我有11个班,包括Main。 Board类扩展了JPanel并绘制了棋盘图像以及骰子图像。类Player,它扩展了JCoponent并实现了Runnable(Thread)。每个玩家实例都是一个典当动画,它正在全面移动。玩家类在棋盘上绘制棋子。

模式
代码如何:

Board b=new Board(); 
Player p=new Player();
b.add(p);
JPanel panel=new JPanel();
panel.add(b);
add(panel); //adding the panel to the frame.

问题是我在棋盘上不能同时拥有多个棋子。我已经尝试在另一个类中重新绘制所有玩家(作为非动画),但它不起作用。我也试过JLayeredPane,但也许我做错了。不幸的是,我无法改变上述模式,所以不要提出这个建议。

提前感谢您的帮助。

P.S:我不能发布任何代码因为它的巨大。
P.P.S:如果你问我,会给出更多的澄清。

编辑:我改革了我的问题。是否可以在同一个面板上同时拥有两个动画?如果答案是肯定的..我可以这样做吗?

2 个答案:

答案 0 :(得分:2)

最有可能让许多组件同时移动。使用javax.swing.Timer或SwingWorker来实现此目的。

这是一个向您展示的快速示例。它将16个棋子放在棋盘上并随机地从一个地方移动到另一个地方。

Board animation

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestAnimation {

    private static final String PAWN_URL = "http://files.chesskidfiles.com/images_users/tiny_mce/BoundingOwl/bishop_happywhite.png";

    private Image pawn;

    private Map<Location, Pawn> pawnLocations = new HashMap<>();

    private Board board;

    private Timer timer;

    private JLayeredPane glassPane;

    public TestAnimation() {
        try {
            pawn = new ImageIcon(new URL(PAWN_URL)).getImage();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    private static class Location {
        public final int row;
        public final int col;

        public Location(int row, int col) {
            super();
            this.row = row;
            this.col = col;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + col;
            result = prime * result + row;
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            Location other = (Location) obj;
            return (col == other.col && row == other.row);
        }
    }

    private static class Cell extends JPanel {

        private final Location location;

        public Cell(Location location) {
            super(new BorderLayout());
            this.location = location;
            setOpaque(true);
            setBackground(((location.row + location.col) % 2) == 0 ? Color.WHITE : Color.BLACK);
        }

        @Override
        protected void addImpl(Component comp, Object constraints, int index) {
            while (getComponentCount() > 0) {
                remove(0);
            }
            super.addImpl(comp, constraints, index);
        }
    }

    private static class Board extends JPanel {

        private Map<Location, Cell> cells = new HashMap<>();

        public Board() {
            super(new GridLayout(8, 8));
            for (int i = 0; i < 8; i++) {
                for (int j = 0; j < 8; j++) {
                    Cell cell = new Cell(new Location(i, j));
                    add(cell);
                    cells.put(new Location(i, j), cell);
                }
            }
        }

        public void add(Pawn pawn, Location location) {
            cells.get(location).add(pawn);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        public Cell getCell(Location location) {
            return cells.get(location);
        }
    }

    private class Pawn extends JComponent {
        public Pawn() {
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(pawn, 0, 0, getWidth(), getHeight(), this);
        }
    }

    protected void initUI() {
        JFrame frame = new JFrame(TestAnimation.class.getSimpleName());
        board = new Board();
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 2; j++) {
                Location location = new Location(i, j);
                Pawn aPawn = new Pawn();
                board.add(aPawn, location);
                pawnLocations.put(location, aPawn);
            }
        }
        for (int i = 0; i < 8; i++) {
            for (int j = 6; j < 8; j++) {
                Location location = new Location(i, j);
                Pawn aPawn = new Pawn();
                board.add(aPawn, location);
                pawnLocations.put(location, aPawn);
            }
        }
        timer = new Timer(7000, new Animation());
        timer.setInitialDelay(0);
        timer.setRepeats(true);
        timer.setCoalesce(false);
        glassPane = new JLayeredPane();
        glassPane.setOpaque(false);
        frame.add(board);
        frame.setGlassPane(glassPane);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
        timer.start();
        glassPane.setVisible(true);
    }

    public class Animation implements ActionListener {

        private Map<Location, Pawn> futureLocations;

        private Random random = new Random();

        private Timer subTimer;

        private List<Pawn> movingPawns;

        private Map<Pawn, Point> originalCoordinates = new HashMap<>();
        private Map<Pawn, Point> futureCoordinates = new HashMap<>();

        @Override
        public void actionPerformed(ActionEvent e) {
            futureLocations = new HashMap<>();
            movingPawns = new ArrayList<>();
            for (Pawn p : pawnLocations.values()) {
                int row = random.nextInt(8);
                int col = random.nextInt(8);
                Location location;
                while (futureLocations.containsKey((location = new Location(row, col)))) {
                    row = random.nextInt(8);
                    col = random.nextInt(8);
                }
                futureLocations.put(location, p);
                Cell futureCell = board.getCell(location);
                futureCoordinates.put(p, SwingUtilities.convertPoint(futureCell, 0, 0, glassPane));
                movingPawns.add(p);
            }
            for (Pawn p : movingPawns) {
                Point locationInGlassPane = SwingUtilities.convertPoint(p.getParent(), 0, 0, glassPane);
                glassPane.add(p);
                p.setLocation(locationInGlassPane);
                originalCoordinates.put(p, locationInGlassPane);
            }
            subTimer = new Timer(50, new AnimationSteps());
            subTimer.setInitialDelay(0);
            subTimer.setCoalesce(true);
            subTimer.setRepeats(true);
            subTimer.start();
        }

        public class AnimationSteps implements ActionListener {

            private int step = 0;

            @Override
            public void actionPerformed(ActionEvent e1) {
                if (step < 50 + 1) {
                    for (Pawn p : movingPawns) {
                        Point p1 = originalCoordinates.get(p);
                        Point p2 = futureCoordinates.get(p);
                        int x = (int) (p1.x + ((p2.x - p1.x) * (double) step / 50));
                        int y = (int) (p1.y + ((p2.y - p1.y) * (double) step / 50));
                        p.setLocation(x, y);
                    }
                } else {
                    for (Entry<Location, Pawn> e : futureLocations.entrySet()) {
                        board.add(e.getValue(), e.getKey());
                    }
                    board.revalidate();
                    subTimer.stop();
                    pawnLocations = futureLocations;
                }
                step++;

            }

        }
    }

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
            UnsupportedLookAndFeelException {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestAnimation().initUI();
            }
        });
    }
}

答案 1 :(得分:0)

也许你的问题是尝试用每个对象的线程开发一个程序,大多数流行的游戏用一个线程运行,最多两个。原因是:将线程彼此同步会非常复杂,更不用说你的性能会很差。甚至Java中的图形引擎也是单线程的,这意味着你不会同时绘制两个线程。