0

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
    }
}
Cyber Storm
  • 217
  • 1
  • 13

2 Answers2

2

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));
Marco13
  • 53,703
  • 9
  • 80
  • 159
  • @CyberStorm take a look at [**Constructors**](http://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html). Also you don't need to pass the `x` `y` values to the `drawPipe`, just the `Graphics`. What you want to do in the `paintComponent` is then [**Loop**](http://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html) through the list of `Pipe` and use the `drawPipe(g)` method – Paul Samsotha Feb 09 '14 at 04:24
  • @peeskillet I fixed those errors, could you post a link or a sample of what you mean by "Loop through the list of Pipe and use the drawPipe(g) method"? – Cyber Storm Feb 09 '14 at 05:27
1

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

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • Thanks, that makes since, I just haven't seen a loop for a list before. And about which values I need in the constructor, I actually need x1, y2. I'm using the x1 to determine the horizontal position of the top and bottom half of the pipe, and the y2 has to do with the size of the pipe, how long it is (height). I understand that part might look confusing, but I'm going to keep the values the same for now. I might take the time to redo them later. For example, my y2 value is smaller than my y4 value, and I should probably be using y4 for the height instead of y2. – Cyber Storm Feb 09 '14 at 06:26
  • What should I do with the getPreferredSize() method? Does it need to go in the object class? If not, then where? – Cyber Storm Feb 09 '14 at 06:50
  • It looks fine to me where it's currently at – Paul Samsotha Feb 09 '14 at 06:52
  • I tested it too, ha it packed to the size of the button when I moved it. So, I know that all of this code works now (after edits to the above code). The only problem I'm having is trying to get the object to move and repaint in the loop. I can just post the fixes tomorrow, if you aren't sure about a solution. – Cyber Storm Feb 09 '14 at 07:00
  • If you decide to post another question, just link it here :) – Paul Samsotha Feb 09 '14 at 07:10
  • The problem I'm having now is making them move. If I change the values of where the pipes start, I can see them all. I guess I'm just not sure how to animate these grouped pipes. – Cyber Storm Feb 09 '14 at 07:17
  • LOOP!... See previous answers. Each `PipeObject` need to have its own `move` method. It should not be in the `Pipe` class – Paul Samsotha Feb 09 '14 at 07:19
  • Ha I did that, but if they all draw at the same time, where do I put a clearRect()? And where does the move() need to be? – Cyber Storm Feb 09 '14 at 07:22
  • 1
    You don't need `clearRect()` at all. Put `move` in the `PipeObject`. loop through all the `PipeObject`s in your `Timer` calling `pipe.move()` in the loop. Then `repaint()` – Paul Samsotha Feb 09 '14 at 07:23
  • Okay, more sense-making. – Cyber Storm Feb 09 '14 at 07:26
  • I will post the updated code in a new question tomorrow, at least I'm making progress. – Cyber Storm Feb 09 '14 at 07:59
  • New question can be found [here](http://stackoverflow.com/questions/21689021/pipegame-game-objects-not-being-drawn-by-for-each-loop). – Cyber Storm Feb 10 '14 at 22:14