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