我怎么可以滚动多个对象多在同一时间? [英] How can I scroll more than one object at the same time?

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

问题描述

新的问题是这个后问,找到<一href=\"http://stackoverflow.com/questions/21592492/how-can-i-switch-between-jpanels?lq=1\">here.

我是新来的Java,但我的笨鸟先飞的娱乐合作,以了解更多关于Java和显示图形的方式。任何解决方案或建议的任何我的问题是很大的AP preciated。谢谢!

现在,我的程序,使一个随机管和卷轴,但我并不需要它来保持滚动时 X1-3 = -83 这是当管道将完全关闭屏幕,并且不再需要)。

问题

我怎样才能让我的 Game.class 滚动超过 Pipes.class的一个实例,同时增加了$它们夹住的p $ pset的距离是多少?我可以找出它们之间放距离,但据显示一多,我不知道该怎么做。至多,3管具有在同一时间被显示。

我怎样才能显示主菜单面板,然后切换到启动按钮后,管板是pressed?

Game.java

 进口java.awt.event.ActionEvent中;
进口java.awt.event.ActionListener;
进口javax.swing.JFrame中;
进口javax.swing.JPanel中;
进口javax.swing.SwingUtilities中;
进口javax.swing.Timer中;公共类游戏{    管道面板=新管道();    公共游戏(){
        JFrame的F =新的JFrame();        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(面板);
        f.setTitle(管子·游戏);
        f.setResizable(假);
        f.pack();
        f.setLocationRelativeTo(NULL);
        f.setVisible(真);        定时器定时器=新定时器(10,新的ActionListener(){//管速度
            @覆盖
            公共无效的actionPerformed(ActionEvent的五){
                panel.move();
            }
        });
        timer.start();        定时刷新=新的定时器(30,新的ActionListener(){//刷新率
            @覆盖
            公共无效的actionPerformed(ActionEvent的五){
                panel.repaint();
            }
        });
        refresh.start();
    }    公共静态无效的主要(字符串ARGS []){
        SwingUtilities.invokeLater(Runnable的新(){            @覆盖
            公共无效的run(){
                新游戏();
            }
        });
    }
}

Pipes.java

 进口java.awt.Dimension中;
进口java.awt.Graphics;
进口javax.swing.JPanel中;公共类管道继承JPanel {
    //声明和initialiaze变量
    INT X1 = 754; // XVAL启动
    INT X2 = 75; //宽管
                                //总宽度为83
    INT Y1 = -1; //利用yval启动
    INT Y2 = setHeightVal(); //管高度
    INT差距= 130; //间隙高度    @覆盖
    公共无效的paintComponent(图形G){
        super.paintComponent方法(G);        g.clearRect(0,0,750,500); //清屏
        g.drawRect(X1,Y1,X2,Y2); //绘制第1部分
        g.drawRect(X1-3,Y2-1,2 + 6,25); //绘制第2部分
        g.drawRect(X1-3,Y2 + 25 +的差距,X2 + 6,25); //绘制第3部分
        g.drawRect(X1,Y2 + 25 +缺口+ 25,x2,500-y2-49间隙); //绘制部分4
    }    公共无效移动(){
        x1--;
    }    公众诠释getMyX(){//若要确定管水平
        返回X1-3;
    }    公众诠释getMyY(){//若要确定管道垂直
        回Y2 + 25;
    }    公众诠释setHeightVal(){//获得一个随机数,选择preSET高度
        INT NUM =(int)的(9 *的Math.random()+ 1);
        INT VAL = 0;
        如果(NUM == 9)
        {
            VAL = 295;
        }
        否则,如果(NUM == 8)
        {
            VAL = 246;
        }
        否则,如果(NUM == 7)
        {
            VAL = 216;
        }
        否则,如果(NUM == 6)
        {
            VAL = 185;
        }
        否则,如果(NUM == 5)
        {
            VAL = 156;
        }
        否则,如果(NUM == 4)
        {
            VAL = 125;
        }
        否则,如果(NUM == 3)
        {
            VAL = 96;
        }
        否则,如果(NUM == 2)
        {
            VAL = 66;
        }
        其他
        {
            VAL = 25;
        }
        返回VAL;
    }    @覆盖
    公共尺寸的get preferredSize(){
        返回新尺寸(751,501);
    }
}


解决方案

  

我怎样才能让我的Game.class滚动Pipes.class的多个实例,同时增加它们之间的preset的距离?


下面是一些简单的逻辑。你想用一个数据结构来保存你的管道的。的任何数据需要油漆然后,像的x,y这是什么数据结构将保持是,坐标。对于这个任务,我preFER只是为了创造一个新的类,它有自己方法,我通过的paintComponent 的图形上下文。例如:

 公共类管{
    INT X;
    诠释Ÿ;
    公共类管材(INT X,int y)对{
        this.x = X;
        this.y = Y;
    }    公共无效drawPipe(图形G){
        g.fillRect(X,Y​​,50,100);
    }
}

现在这只是一个例子类。以上仅绘制一个矩形,但这只是为了告诉你,你应该做的事情。

所以,下次你想拥有的数据结构来举行三次管道对象,如数组。我preFER使用列表。你会想是列表管道类,并添加三个管道反对。您可以指定 X 是任何你喜欢的,保持它们分开相同的距离

 公共类管道继承JPanel {
    清单&LT;管道和GT;管道=新的ArrayList&LT;管道和GT;();    公共管道(){
        pipes.add(新管(50,100));
        pipes.add(新管(150,100));
        pipes.add(新管(250,100));
    }
}

现在在的paintComponent 方法,所有你需要做的是循环通过他们,并使用其 drawPipe 方法

 保护无效paintComponent(图形G){
    super.paintComponent方法(G);    对于(管管材:管){
        pipe.drawPipe(G);
    }
}

现在你移动他们所有你需要做的是移动有 X 在定时器位置,并调用重绘 。您可能还需要核对的X,以确保它不会做了屏幕,或者如果您移动它们的权利,你可以把它们放在最左边,然后乳清熄灭屏幕,像一个传送带。所以,你可以做这样的事情。

 私有静态最终诠释X_INC = 5;
...
定时器定时器=新定时器(40,新的ActionListener(){
    公共无效的actionPerformed(ActionEvent的五){
        对于(管管材:管){
            如果(pipe.x&GT; =屏幕宽度){
                pipe.x = 0;
            }其他{
                pipe.x + = X_INC;
            }
        }
        重绘();
    }
});

正如你所看到的,我做的是通过列表循环键,只是改变他们所有的 X 坐标,那么重绘()。所以,你可以创建你需要画,只是移动它们围绕在循环的任何值你自己的管道类。


有关速度的变化,而是采用了硬codeD vakue像 10 定时器,使用一个变量延迟,你可以像一个按钮,点击更改

  INT延迟= 100;
JButton的加速比=的新的JButton(加快);
JButton的放缓=的新的JButton(减速);
定时器定时= NULL;
公共管道(){
    定时器=新定时器(延迟,新的ActionListener(){
        ...
    });
    timer.start();    speedUp.addActionListener(新的ActionListener(){
        公共无效的actionPerformed(ActionEvent的五){
            如果(((延迟 - 20)&LT;!0)){
                延迟 - = 20;
                timer.setDelay(延迟);
            }
        }
    });
    //做放​​缓相同,但降低了延迟
}


测试了这一点。

 进口java.awt.Dimension中;
进口java.awt.Graphics;
进口java.awt.Image中;
进口java.awt.event.ActionEvent中;
进口java.awt.event.ActionListener;
进口java.awt.image.BufferedImage中;
进口java.io.IOException异常;
进口的java.net.URL;
进口的java.util.ArrayList;
进口的java.util.List;
进口java.util.logging.Level中;
进口java.util.logging.Logger中;
进口javax.imageio.ImageIO中;
进口javax.swing.JFrame中;
进口javax.swing.JPanel中;
进口javax.swing.SwingUtilities中;
进口javax.swing.Timer中;
公共类马里奥继承JPanel {    私有静态最终诠释D_W = 800;
    私有静态最终诠释D_H = 300;
    私有静态最终诠释X_INC = 5;    BG的BufferedImage;
    的BufferedImage pipeImg;    清单&LT;管道和GT;管道=新的ArrayList&LT;&GT;();    INT延迟= 50;    定时器定时= NULL;    公共马里奥(){        尝试{
            BG = ImageIO.read(新URL(http://farm8.staticflickr.com/7341/12338164043_0f68c73fe4_o.png));
            pipeImg = ImageIO.read(新URL(http://farm3.staticflickr.com/2882/12338452484_7c72da0929_o.png));
        }赶上(IOException异常前){
            。Logger.getLogger(Mario.class.getName())日志(Level.SEVERE,空,前);
        }        pipes.add(新管(100,150,pipeImg));
        pipes.add(新管(400,150,pipeImg));
        pipes.add(新管(700,150,pipeImg));        定时器=新定时器(延迟,新的ActionListener(){
            公共无效的actionPerformed(ActionEvent的五){
                对于(管管材:管){
                    如果(pipe.x&GT; D_W){
                        pipe.x = 0;
                    }其他{
                        pipe.x + = X_INC;
                    }
                }
                重绘();
            }
        });
        timer.start();
    }    @覆盖
    保护无效paintComponent(图形G){
        super.paintComponent方法(G);
        g.drawImage(BG,0,0,的getWidth(),的getHeight(),这一点);
        对于(管管材:管){
            pipe.drawPipe(G);
        }
    }    @覆盖
    公共尺寸的get preferredSize(){
        返回新的Dimension(D_W,D_H);
    }    公共类管{        INT X;
        诠释Ÿ;
        图片管;        公共管道(INT X,INT Y,图像管){
            this.x = X;
            this.y = Y;
            this.pipe =管;
        }        公共无效drawPipe(图形G){
            g.drawImage(管,X,Y,75,150,Mario.this);
        }
    }    公共静态无效的主要(字串[] args){
        SwingUtilities.invokeLater(Runnable的新(){
            公共无效的run(){
                JFrame的帧=新的JFrame(马里奥管道);
                frame.add(新马里奥());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(NULL);
                frame.setVisible(真);
            }
        });
    }
}

New question was asked after this one, found here.

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!

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

Questions

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?

Classes

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

解决方案

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

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.

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

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

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

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.


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天全站免登陆