如何同时滚动多个对象? [英] How can I scroll more than one object at the same time?

查看:27
本文介绍了如何同时滚动多个对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此之后提出了新问题,在此处找到.

New question was asked after this one, found here.

我是 Java 新手,但我正在重新制作Flappy Bird"以了解有关 Java 和图形显示方式的更多信息.非常感谢对我的任何问题的任何解决方案或建议.谢谢!

I'm new to Java, but I am working on a recreation of "Flappy Bird" to learn more about java and the way that graphics are displayed. Any solutions or suggestions to any of my questions is greatly appreciated. Thanks!

现在,我的程序制作了一个随机管道并滚动它,但是当 x1-3 = -83(这是管道将完全离开屏幕,不再需要).

Right now, my program makes a random pipe and scrolls it, but I don't need it to keep scrolling when x1-3 = -83 (this is when the pipe will be off of the screen completely and is no longer needed).

问题

如何让我的 Game.class 滚动多个 Pipes.class 实例,同时在它们之间添加预设距离?我可以找出它们之间的距离,但就显示不止一个而言,我不知道该怎么做.最多同时显示3个管道.

How can I make my Game.class scroll more than one instance of Pipes.class while adding a preset distance between them? I could find out the distance to put between them, but as far as displaying more than one, I'm not sure how to do that. At most, 3 pipes have to be displayed at the same time.

如何显示主菜单的面板,然后在按下开始按钮后切换到管道面板?

How can I display a panel for the main menu, and then switch to the pipes panel after a start button is pressed?

课程

游戏.java

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

public class Game {

    Pipes panel = new Pipes();

    public Game() {
        JFrame f = new JFrame();

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(panel);
        f.setTitle("Pipe Game");
        f.setResizable(false);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);

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

        Timer refresh = new Timer(30, new ActionListener() {    //refresh rate
            @Override
            public void actionPerformed(ActionEvent e) {
                panel.repaint();
            }
        });
        refresh.start();


    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Game();
            }
        });
    }
}

Pipes.java

import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;

public class Pipes extends JPanel {
    //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

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(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;
    }

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

推荐答案

如何让我的 Game.class 滚动多个 Pipes.class 实例,同时在它们之间添加预设距离?"

"How can I make my Game.class scroll more than one instance of Pipes.class while adding a preset distance between them? "

这是一些简单的逻辑.您想使用数据结构来保存管道.这个数据结构将保存需要绘制的任何数据,例如 x、y、坐标.对于这个任务,我更喜欢用它自己的 draw 方法创建一个新类,我将 paintComponent 的 Graphics 上下文传递给它.例如

Here's some simple logic. You want to use a data structure to hold you pipes. What this data structure will hold is whatever data is required to paint then, like x, y, coordinates. For this task, I prefer just to create a new class with it's own draw method, that I pass the paintComponent's Graphics context to. For example

public class Pipe {
    int x;
    int y;
    public class Pipe(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void drawPipe(Graphics g) {
        g.fillRect(x, y, 50, 100);
    }
}

现在这只是一个示例类.上面只画了一个矩形,但这只是为了告诉你你应该做什么.

Now this is just an example class. The above only draws a rectangle, but this is just to show you what you should be doing.

所以接下来您需要使用数据结构来保存三个 Pipe 对象,例如一个数组.我更喜欢使用 List.您需要在您的 Pipes 类中使用 List,并向其添加三个 Pipe 对象.您可以将 x 指定为您喜欢的任何值,以使它们保持相同的距离

So next you want to have the data structure to hold three Pipe objects, like an array. I prefer to use a List. You'll want that List in your Pipes class, and add three Pipe object to it. You can specify the x to be anything you like, to keep them the same distance apart

public class Pipes extends JPanel {
    List<Pipe> pipes = new ArrayList<Pipe>();

    public Pipes() {
        pipes.add(new Pipe(50, 100));
        pipes.add(new Pipe(150, 100));
        pipes.add(new Pipe(250, 100));
    }
}

现在在 paintComponent 方法中,您需要做的就是遍历它们并使用它的 drawPipe 方法

Now in the paintComponent method, all you need to do is loop through them and use its drawPipe method

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

    for ( Pipe pipe : pipes ){
        pipe.drawPipe(g);
    }
}

现在你移动它们,你需要做的就是在计时器中移动 x 个位置,然后调用 repaint.您可能还想检查 x 以确保它不会离开屏幕,或者如果您将它们向右移动,您可以将它们放在最左边,然后乳清离开屏幕,就像传送带一样.所以你可以做这样的事情

Now you move them all you need to do is move there x positions in the timer, and call repaint. You may also want to check against the x to make sure it doesn't do off the screen, or if you moving them the right, you could put them the the very left then whey go off the screen, like a conveyor belt. So you could do something like this

private static final int X_INC = 5;
...
Timer timer = new Timer(40, new ActionListener(){
    public void actionPerformed(ActionEvent e) {
        for (Pipe pipe : pipes ){
            if (pipe.x >= screenWidth) {
                pipe.x = 0;
            } else {
                pipe.x += X_INC;
            }
        }
        repaint();
    }
});

如您所见,我所做的是遍历 List 并更改其所有 x 坐标,然后更改 repaint().因此,您可以使用您需要绘制的任何值创建自己的 Pipe 类,然后在循环中移动它们.

As you can see, what I do is loop through the List and just change all their x coordinates, then repaint(). So you can create your own Pipe class with whatever values you need to paint, and just move them around in the loop.

对于速度的改变,不要使用像 10 这样的硬编码 vakue 作为计时器,而是使用变量 delay,您可以通过点击一个按钮

For the changing of speed, instead of using a hard coded vakue like 10 for the timer, use a variable delay, that you can change like with the click of a button

int delay = 100;
JButton speedUp = new JButton("Speed UP");
JButton slowDown = new JButton("Slow Down");
Timer timer = null;
public Pipes() {
    timer = new Timer(delay, new ActionListener(){
        ...
    });
    timer.start();

    speedUp.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
            if (!((delay - 20) < 0)) {
                delay -=20;
                timer.setDelay(delay);
            }
        }
    });
    // do the same for slowDown, but decrease the delay
}

<小时>

测试一下


Test this out

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;


public class Mario extends JPanel {

    private static final int D_W = 800;
    private static final int D_H = 300;
    private static final int X_INC = 5;

    BufferedImage bg;
    BufferedImage pipeImg;

    List<Pipe> pipes = new ArrayList<>();

    int delay = 50;

    Timer timer = null;

    public Mario() {

        try {
            bg = ImageIO.read(new URL("http://farm8.staticflickr.com/7341/12338164043_0f68c73fe4_o.png"));
            pipeImg = ImageIO.read(new URL("http://farm3.staticflickr.com/2882/12338452484_7c72da0929_o.png"));
        } catch (IOException ex) {
            Logger.getLogger(Mario.class.getName()).log(Level.SEVERE, null, ex);
        }

        pipes.add(new Pipe(100, 150, pipeImg));
        pipes.add(new Pipe(400, 150, pipeImg));
        pipes.add(new Pipe(700, 150, pipeImg));

        timer = new Timer(delay, new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                for (Pipe pipe : pipes) {
                    if (pipe.x > D_W) {
                        pipe.x = 0;
                    } else {
                        pipe.x += X_INC;
                    }
                }
                repaint();
            }
        });
        timer.start();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(bg, 0, 0, getWidth(), getHeight(), this);
        for (Pipe pipe : pipes) {
            pipe.drawPipe(g);
        }
    }

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

    public class Pipe {

        int x;
        int y;
        Image pipe;

        public Pipe(int x, int y, Image pipe) {
            this.x = x;
            this.y = y;
            this.pipe = pipe;
        }

        public void drawPipe(Graphics g) {
            g.drawImage(pipe, x, y, 75, 150, Mario.this);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame("Mario Pipes");
                frame.add(new Mario());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

这篇关于如何同时滚动多个对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆