如何使用ArrayList显示移动对象?

时间:2014-02-07 00:30:47

标签: java swing arraylist timer jpanel

我对如何使用ArrayList有一些疑问。我是java的新手,所以我想知道它的实际用途以及使用它的正确方法。我被告知我可以使用数组列表来显示我的对象,但我似乎无法理解如何将其添加到我当前的项目中。

我正在努力同时显示3个管道,用定时器控制速度和刷新率。我想我终于理解了JFrameJPanel的基础知识,但最近我已经介绍了 mystical CardLayout,所以关于它的任何例子也都是有帮助的。

到目前为止,我已经能够添加一个开始菜单,其中包含一个播放按钮。用户点击“播放!”后,菜单应由游戏面板替换,并将playerIsReady设置为true,启动应向屏幕添加三个pipe.java实例的计时器,每一个被称为“速度”的timer向左移动。所有管道都从屏幕右侧开始。

我想更好地了解如何在每个pipe对象之间添加间距。 我也对如何在屏幕上加载和打印本地图像感兴趣。

如果您尝试回答上述任何问题,请详细解释每个步骤,因为我是Java的新手。感谢您抽出宝贵时间提供帮助。如果你不是在这里回答问题,我希望你能从这里的任何代码/答案中学到一些东西。

游戏

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
import javax.swing.SwingUtilities;

public class Game {

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {             
                // the GUI as seen by the user (without frame)
                final CardLayout cl = new CardLayout();
                final JPanel gui = new JPanel(cl);
                // remove if no border is needed
                gui.setBorder(new EmptyBorder(10,10,10,10));

                JPanel menu = new JPanel(new GridBagLayout());
                JButton playGame = new JButton("Play!");
                ActionListener playGameListener = new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        cl.show(gui, "game");
                    }
                };
                playGame.addActionListener(playGameListener);
                Insets margin = new Insets(20, 50, 20, 50);
                playGame.setMargin(margin);
                menu.add(playGame);
                gui.add(menu);
                cl.addLayoutComponent(menu, "menu");

                final JPanel pipes = new Pipes();
                gui.add(pipes);
                cl.addLayoutComponent(pipes, "game");

                JFrame f = new JFrame("Pipes Game");
                f.add(gui);
                // Ensures JVM closes after frame(s) closed and
                // all non-daemon threads are finished
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                // See http://stackoverflow.com/a/7143398/418556 for demo.
                f.setLocationByPlatform(true);

                // ensures the frame is the minimum size it needs to be
                // in order display the components within it
                f.pack();
                // should be done last, to avoid flickering, moving,
                // resizing artifacts.
                f.setVisible(true);

                /*if (playerIsReady) { 
                    Timer speed = new Timer(10, new ActionListener() {  //pipe speed
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            pipes.move();
                        }
                    });
                    speed.start();

                    Timer refresh = new Timer(30, new ActionListener() {    //refresh rate
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            pipes.repaint();
                        }
                    });
                    refresh.start();
                }*/
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }
}

PipeObject

import java.awt.Graphics;

public class PipeObject {
    //Declare and initialiaze variables
    int x1 = 754;               //xVal start
    int x2 = 75;                //pipe width
                                //total width is 83
    int y1 = -1;                //yVal start
    int y2 = setHeightVal();    //pipe height
    int gap = 130;              //gap height

    public void drawPipe(Graphics g) {

        g.clearRect(0,0,750,500);                       //Clear screen
        g.drawRect(x1,y1,x2,y2);                        //Draw part 1
        g.drawRect(x1-3,y2-1,x2+6,25);                  //Draw part 2
        g.drawRect(x1-3,y2+25+gap,x2+6,25);             //Draw part 3
        g.drawRect(x1,y2+25+gap+25,x2,500-y2-49-gap);   //Draw part 4
    }

    public void move() {
        x1--;
    }

    public int getMyX() {   //To determine where the pipe is horizontally
        return x1-3;
    }

    public int getMyY() {   //To determine where the pipe is vertically
        return y2+25;
    }

    public int setHeightVal() {     //Get a random number and select a preset height
        int num = (int)(9*Math.random() + 1);
        int val = 0;
        if (num == 9)
        {
            val = 295;
        }
        else if (num == 8)
        {
            val = 246;
        }
        else if (num == 7)
        {
            val = 216;
        }
        else if (num == 6)
        {
            val = 185;
        }
        else if (num == 5)
        {
            val = 156;
        }
        else if (num == 4)
        {
            val = 125;
        }
        else if (num == 3)
        {
            val = 96;
        }
        else if (num == 2)
        {
            val = 66;
        }
        else
        {
            val = 25;
        }
        return val;
    }
}

1 个答案:

答案 0 :(得分:2)

所以你的PipeObject类只是一个数据模型类。 drawPipe方法实际上并没有自己绘制任何东西。您需要JPanel类来呈现此数据,并在drawPipe的{​​{1}}方法中调用paintComponent方法,并将JPanel上下文传递给它。

此外,如果您希望拥有不同的Graphics位置值,则需要构造函数来接收不同的x值。似乎x值应该相同,因为总会保留在同一y轴上。 y类中的构造函数应该类似于

PipeObject

当您创建int x1; // no need to give them values. int x2; // This will be done when you create a new PipeObject object public PipeObject(int x1, int x2) { this.x1 = x1; this.x1 = x2; } 对象时,您将向其传递不同的值。总结以上两点,你会得到类似的东西。

new PipeObject

然后,您可以在框架中添加public class PipePanel extends JPanel { List<PipeObject> pipes = new ArrayList<PipeObject>(); public PipePanel() { pipes.add(new PipeObject(100, 90)); pipes.add(new PipeObject(300, 290)); pipes.add(new PipeObject(500, 490)); } protected void paintComponent(Graphics g) { super.paintComponent(g); for ( PipeObject pipe : pipes ){ pipe.drawPipe(g); } } } 的实例。另请注意,在您的PipesPanel中,您应该覆盖PipesPanel,因此它会有一个首选尺寸,您只需getPreferredSize框架

pack()

此外,当您想要操纵@Override public Dimension getPreferredSize() { return new Dimension(800, 500); // or what ever values you want for screen size } PipeObject时,您只需调用methods like move(), then call重绘一个。像

这样的东西
Timer timer = new Timer(50, new ActionListener(){
    public void actionPerformed(ActionEvent e) {
        for (PipeObject pipe : pipes) {
            pipe.move();
        }
        repaint();
    }
});