Pipe Game - PipeObject in class PipeObject cannot

2019-08-23 04:17发布

问题:

I keep getting the error "PipeObject in class PipeObject cannot be applied to given types"

public Pipes() {
    pipes.add(new PipeObject(x1, y1));
    pipes.add(new PipeObject(x1 + 200, y2));
    pipes.add(new PipeObject(x1 + 400, y3));
}

I have an object class that I want to be added to a JPanel by a class that controls the objects and draws 3 instances of it to the screen. It needs to be able to give different values to the object class.

My third class is the main() class and should add the class with the grouped objects to a JPanel in a cardLayout. There is also a menu screen with a play button on it, and the objects should not move until boolean playerIsReady = true. The pipe objects should only move after the event listener switches the panel to the game screen.

Also, I wasn't able to get my timers in the Game class to work before. Maybe this will help towards getting that to work. I don't know where I can declare boolean playerIsReady, but I know that it needs to be set to true after the user clicks the play button.

Here are all the class files

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

Pipes.java

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

public class Pipes extends JPanel {
    int x1 = 754;
    int y1 = setHeightVal();
    int y2 = setHeightVal();
    int y3 = setHeightVal();

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

    public Pipes() {
        pipes.add(new PipeObject(x1, y1));
        pipes.add(new PipeObject(x1 + 200, y2));
        pipes.add(new PipeObject(x1 + 400, y3));
    }

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

        g.clearRect(0,0,751,501);
        // Draw PipeObject1
        // Draw PipeObject2
        // Draw PipeObject3
    }

    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() {
        // adjust to need
        return new Dimension(751,501);
    }
}

PipeObject.java

import java.awt.Graphics;

public class PipeObject {
    //Declare and initialiaze variables
    int x2 = 75;                //pipe width, total is 83
    int y1 = -1;                // Y should be -1
    int gap = 130;              //gap height

    public void drawPipe(Graphics g, int x1, int y2) {
        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
    }
}

回答1:

A lot of code, considering that according to the error message (and the code that you posted) there is just a Constructor missing for the PipeObject class:

public class PipeObject {
    //Declare and initialiaze variables
    int x2 = 75;                //pipe width, total is 83
    int y1 = -1;                // Y should be -1
    int gap = 130;              //gap height

    // Add this:
    public PipeObject(int x, int y) {
        this.x2 = x;
        this.y1 = y;
    }

    ...
}

Then you can create a new PipeObject, for example, as in your calls

pipes.add(new PipeObject(x1, y1));


回答2:

"I fixed those errors, could you post a link or a sample of what you mean?"

  • Your drawPipe method should just look like this

    public void drawPipe(Graphics g) {
       ....
    }
    

    The reason you don't need the x and y values passed to to it is because each Pipe object already has has values

    int x2 = 75;           
    int y1 = -1; 
    

The whole point of the constructor is to create a Pipe object with different values. As Marco13 pointed out, your constructor should look like this

    public PipeObject(int x, int y) {
        this.x2 = x;
        this.y1 = y;
    }

So what happens with you create a new PipedObject(100, 100), it gets assigned the values of x2 = 100; y1 = -1;

As I remember from your previous posts though, I'm not sure if this is the constructor you want. The reason is because the y axis should always be constant because you are always moving the pipe along the same y axis, i.e. horizontally. Instead, you probably want to pass a x1 and x2, for the different points of your pipe that you're painting.

  • To loop, as I showed in a previous answer you need to do this

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (Pipe pipe : pipes){
            pipe.drawPipe(g);
        }
    }
    

This is a basic for-each loop. It says for each Pipe object (that we'll call a random name pipe) in the list pipes, invoke the drawPipe method of the pipe object.