我怎样才能同时滚动多个对象?
在这之后,在这里find了一个新的问题。
我是Java新手,但是我正在做一个“Flappy Bird”的娱乐活动,以便学习更多关于java和graphics显示的方式。 任何解决scheme或对我的任何问题的build议,非常感谢。 谢谢!
现在,我的程序做了一个随机的pipe道并且滚动它,但是当x1-3 = -83
( 这是pipe道完全离开屏幕并且不再需要的时候 )我不需要它来保持滚动。
问题
我怎样才能让我的Game.class
滚动多个Game.class
实例,同时增加它们之间的预设距离? 我可以找出他们之间的距离,但只要展示不止一个,我不知道该怎么做。 最多3个pipe道必须同时显示。
如何显示主菜单的面板,然后在按下开始button后切换到pipe道面板?
类
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); } }
“我怎样才能让我的Game.class滚动多个Pipes.class实例,同时在它们之间增加一个预设的距离?
这是一些简单的逻辑。 你想用一个数据结构来保存你的pipe道 。 这个数据结构所能容纳的是任何需要绘制的数据,比如x,y,坐标。 对于这个任务,我更喜欢用自己的draw
方法创build一个新的类,我将paintComponent
的Graphics上下文传递给它。 例如
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); } }
现在这只是一个例子。 上面只画了一个矩形,但这只是为了告诉你你应该做什么。
所以接下来你想拥有数据结构来保存三个Pipe
对象,就像一个数组。 我更喜欢使用一个List
。 你需要在Pipes
类中使用这个List
,并向它添加三个Pipe
对象。 你可以指定x
是你喜欢的任何东西,使它们保持相同的距离
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
方法
protected void paintComponent(Graphics g) { super.paintComponent(g); for ( Pipe pipe : pipes ){ pipe.drawPipe(g); } }
现在你移动它们,你需要做的就是在定时器中移动x
位置,然后调用repaint
。 你也可以检查x,确保它不会脱离屏幕,或者如果你把它们移到右边,你可以把它们放在左边,然后乳清离开屏幕,像传送带一样。 所以你可以做这样的事情
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()
。 所以你可以用你需要绘制的任何值创build你自己的Pipe
类,然后在循环中移动它们。
为了改变速度,不要使用像10
这样的硬编码的vakue作为定时器,而是使用一个可变的delay
,你可以像点击一个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 }
testing一下
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); } }); } }