Hi, I need some help please i could not show the balls,when my pacman is moving,i want my pacman will through balls when it's moving.but i could not show his balls,can you please help me what is wrong or missing in my code.

I appreciate someone can help me

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.TimerTask;


public class Mypacman{


    public Mypacman(){
    }


    public void showUI(){
        JFrame jframe = new JFrame();
        jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jframe.add(new Mypanel());
        jframe.pack();
        jframe.setVisible(true);
    }


    class Mypanel extends JPanel{

        int xPos = 0, yPos = 35;
        int  arcMouth=300;
       Balls ballc = new Balls();
       List<Balls>ball = new ArrayList<Balls>();

        public Mypanel(){
            myTimer();
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.fillArc(xPos,yPos,30,30,30,arcMouth);


        }

        public Dimension getPreferredSize() {
            return new Dimension(250,200);
        }

        public void myTimer(){
            java.util.Timer timer = new java.util.Timer();
            TimerTask timerTask = new TimerTask() {
                @Override
                public void run() {
                    updatePosition();
                }
            };
            timer.scheduleAtFixedRate(timerTask, 0, 100);
        }

        public void updatePosition(){
            xPos += 1;
            yPos += 0;

            if((xPos%2)==0){
                arcMouth=360;

            }
            else{
                arcMouth=300;
                updateball();
                ballc.moveBalls();
            }
            repaint();
        }

        public void updateball(){
            for(Balls bb:ball){
                ball.add(new Balls(xPos,yPos));

            }
        }

    }


    class Balls{
      int x,y;
        public Balls(){

        }

        public Balls(int x,int y){
            this.x = x;
            this.y = y;
        }

        public void setXball(int x ){
          this.x=x;
        }

        public void setYball(int y){
            this.y = y;
        }

        public int getXball(){
            return x;
        }

        public int getYball(){
            return y;
        }

        public void moveBalls(){
            x+=2;
            y+=2;
        }


        protected void drawbullets(Graphics g) {

            g.setColor(Color.blue);
            g.fillRect(getXball(), getYball(), 1, 1);
        }
    }


    public static void main(String[]args){

     SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                Mypacman pacman = new Mypacman();
                pacman.showUI();

            }
        });

    }
}

You're not adding any balls.

for(Balls bb:ball){
    ball.add(new Balls(xPos,yPos));
}

That means: for each ball in the list of balls, add a new ball. The list is empty at first, so how can it ever add new balls this way?

Furthermore, apart from the terribly confusing naming for balls and lists of balls, you call updateball to add balls every few ticks, then you tell one ball, ballc, to move. But that ballc is never set with any info, and it's not a list of balls, even though the type Balls would suggest that has more than one. Lastly, I don't see drawbullets ever being called. And even if it were called, where would it draw its rectangles?

What you need to do is set an amount of balls at the start of the game, draw them. Then when the game starts running; on every tick, or every other tick, you update their position and redraw the balls on their new position, this probably also means you'll have to remove the old drawing of them, or use a way of painting similar to the pacman, or on the same panel as pacman. You could (as an easy beginning) clear the entire panel, and redraw pacman and the balls on that every tick.

And I'd strongly suggest using proper names for your entities and lists, you even seem to be confusing yourself when updating the Balls class instead of a list of balls. To safely change names of variables or methods, in your editor, right click on the item you want to change and select "refactor". This way your editor will automatically update the references to that item, and you won't end up with broken code. If you're not using an editor that supports refactoring it might be handy to find one that does.

Hi,Thank you guys for the reply..this is my updated code but the problem is that the balls are behind with the pacman.

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.TimerTask;


public class Mypacman{


    public Mypacman(){
    }


    public void showUI(){
        JFrame jframe = new JFrame();
        jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jframe.add(new Mypanel());
        jframe.pack();
        jframe.setVisible(true);
    }


    class Mypanel extends JPanel{

        int xPos = 0, yPos = 35;
        int  arcMouth=300;
       Balls pacmanball = new Balls();
       List<Balls>ball = new ArrayList<Balls>();

        public Mypanel(){
            myTimer();
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.fillArc(xPos,yPos,30,30,30,arcMouth);

            for(Balls b:ball){
                b.drawballs(g);

            }

        }

        public Dimension getPreferredSize() {
            return new Dimension(250,200);
        }

        public void myTimer(){
            java.util.Timer timer = new java.util.Timer();
            TimerTask timerTask = new TimerTask() {
                @Override
                public void run() {

                    updatePosition();
                }
            };
            timer.scheduleAtFixedRate(timerTask, 0, 100);
        }

        public void updatePosition(){
            xPos += 1;
            yPos += 0;

            if((xPos%2)==0){
                arcMouth=360;

            }
            else{
                arcMouth=300;
                updateball();
                pacmanball.moveBalls();

            }
            repaint();
        }

        public void updateball(){

            ball.add(new Balls(xPos,yPos));

        }

    }


    class Balls{
      int x,y;
      protected  int speed = 30;
        public Balls(){

        }

        public Balls(int x,int y){
            this.x = x;
            this.y = y;
        }

        public void setXball(int x ){
          this.x=x;
        }

        public void setYball(int y){
            this.y = y;
        }

        public int getXball(){
            return x;
        }

        public int getYball(){
            return y;
        }

        public void moveBalls(){
            x+=speed;
            y+=speed;



        }


        protected void drawballs(Graphics g) {

            g.setColor(Color.blue);
            g.fillRect(getXball(), getYball(), 5, 5);

        }
    }


    public static void main(String[]args){

     SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                Mypacman pacman = new Mypacman();
                pacman.showUI();
            }
        });

    }
}

Edited 2 Years Ago by toring

If by behind you mean they don't get updated at the same pace as pacman it's because you're only updating the balls when pacman has its mouth open.

@Traevel,do you mean to put also this two method
updateball();
pacmanball.moveBalls();

in the if statement ?...Thank you in advance.

Placing outside of both will make it update at the same pace, if that's what you meant with being behind yes.

if((xPos%2)==0){
    arcMouth=360;
}
else{
    arcMouth=300;
}
updateball();
pacmanball.moveBalls();

Duplicating code is something you should avoid at all costs. It makes it hard to implement changes.

why is it cannot replace the drawballs method in my Balls Class into this

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

            g.setColor(Color.blue);
            g.fillRect(getXball(), getYball(), 5, 5);

        }

my code will get error if i will do that. "cannot resolve main component(java.awt.Graphics)..it is pointing to super.paintComponent

Because Balls does not extend jPanel (more specifically, a jComponent). You're overriding the method paintComponent in the super class.

If you add @Override above that method in the Mypanel class, and hover over it you will see the following information:

Overrides: paintComponent(...) in JComponent
paintComponent
protected void paintComponent(Graphics g)
Calls the UI delegate's paint method, if the UI delegate is non-null. We pass the delegate a copy of the Graphics object to protect the rest of the paint code from irrevocable changes (for example, Graphics.translate). 
If you override this in a subclass you should not make permanent changes to the passed in Graphics. For example, you should not alter the clip Rectangle or modify the transform. If you need to do these operations you may find it easier to create a new Graphics from the passed in Graphics and manipulate it. Further, if you do not invoker super's implementation you must honor the opaque property, that is if this component is opaque, you must completely fill in the background in a non-opaque color. If you do not honor the opaque property you will likely see visual artifacts. 

The passed in Graphics object might have a transform other than the identify transform installed on it. In this case, you might get unexpected results if you cumulatively apply another transform.

Parameters:
g - the Graphics object to protect
See Also:
paint(java.awt.Graphics), ComponentUI

So it's a method you're overriding, that means it has to be present in the super class. Balls doesn't have a super class.

@Traevel, so if i will not extend my Class Balls to JPanel,I could not use the method paintComponent in my Balls Class ?...

Thank you in avdvance.

If you don't extend Balls to a jComponent, then no you can't use that method in that manner.

Ok,Thanks for that idea.,.. why it's still behind on my pacman?.I could not get the idea how to make this work...I created 10 balls in default constructor.but still now working.

Thank you in avdvance.

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.TimerTask;


public class Mypacman{


    public Mypacman(){
    }


    public void showUI(){
        JFrame jframe = new JFrame();
        jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jframe.add(new Mypanel());
        jframe.pack();
        jframe.setVisible(true);
    }


    class Mypanel extends JPanel{

        int xPos = 0, yPos = 35;
        int  arcMouth=300;
       Balls pacmanball = new Balls();
       List<Balls>listball = new ArrayList<Balls>();

        public Mypanel(){

            for (int i = 0; i < 10; i++) {
                listball.add(new Balls(xPos,yPos));
            }

            myTimer();
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.fillArc(xPos,yPos,30,30,30,arcMouth);

            for(Balls b:listball){
                b.drawballs(g);
            }

        }

        public Dimension getPreferredSize() {
            return new Dimension(250,200);
        }

        public void myTimer(){
            java.util.Timer timer = new java.util.Timer();
            TimerTask timerTask = new TimerTask() {
                @Override
                public void run() {

                    updatePosition();

                }
            };
            timer.scheduleAtFixedRate(timerTask, 0, 100);
        }

        public void updatePosition(){
            xPos += 1;
            yPos += 0;

            if((xPos%2)==0){
                arcMouth=360;
            }
            else{
                arcMouth=300;
                updateball();
            }
            repaint();
        }

        public void updateball(){


           pacmanball.moveBalls();

        }

    }


    class Balls{
      int x,y;
      protected  int speed = 30;
        public Balls(){

        }

        public Balls(int x,int y){
            this.x = x;
            this.y = y;
        }

        public void setXball(int x ){
          this.x=x;
        }

        public void setYball(int y){
            this.y = y;
        }

        public int getXball(){
            return x;
        }

        public int getYball(){
            return y;
        }

        public void moveBalls(){
            x+=speed;
            y+=speed;


        }

        public void drawballs(Graphics s) {

            s.setColor(Color.blue);
            s.fillRect(getXball(), getYball(), 5, 5);

        }
    }


    public static void main(String[]args){

     SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                Mypacman pacman = new Mypacman();
                pacman.showUI();
            }
        });

    }
}

You mean behind in drawing position? If I run your code now the balls are not moving and it just draws a rectangle at the first coordinate position. Which is the same as the top-left corner of your pacman.

If you read the javadoc of fillArc:

x - the x coordinate of the upper-left corner of the arc to be filled. 
y - the y coordinate of the upper-left corner of the arc to be filled.
width - the width of the arc to be filled.
height - the height of the arc to be filled.
startAngle - the beginning angle.
arcAngle - the angular extent of the arc, relative to the start angle.

So the x and y are for upper-left corner of the arc. If you want the rectangle to appear in front of the pacman you'll have to adjust the x and y you give to the ball upon creation. Probably something along the lines of current pacman x + pacman width + however far in front you want it to be.

Hi,I think it's working,can you please run this updated code.

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.TimerTask;


public class Mypacman{


    public Mypacman(){
    }


    public void showUI(){
        JFrame jframe = new JFrame();
        jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jframe.add(new Mypanel());
        jframe.pack();
        jframe.setVisible(true);
    }


    class Mypanel extends JPanel{

        int xPos = 0, yPos = 35;
        int  arcMouth=300;

       List<Balls>listball = new ArrayList<Balls>();

        public Mypanel(){

            for (int i = 0; i < 10; i++) {
                listball.add(new Balls(xPos+5,yPos+15));
            }

            myTimer();
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.fillArc(xPos,yPos,30,30,30,arcMouth);

            for(Balls b:listball){
                b.drawballs(g);
            }

        }

        public Dimension getPreferredSize() {
            return new Dimension(250,200);
        }

        public void myTimer(){
            java.util.Timer timer = new java.util.Timer();
            TimerTask timerTask = new TimerTask() {
                @Override
                public void run() {
                    updatePosition();
                }
            };
            timer.scheduleAtFixedRate(timerTask, 0, 100);
        }

        public void updatePosition(){
            xPos += 1;
            yPos += 0;

            if((xPos%2)==0){
                arcMouth=360;
            }
            else{
                arcMouth=300;
                updateball();
            }
            repaint();
        }

        public void updateball(){




            for(Balls b:listball){
                b.moveBalls();
            }


        }

    }


    class Balls{
      int x,y;
      protected  int speed = 10;
        public Balls(){

        }

        public Balls(int x,int y){
            this.x = x;
            this.y = y;
        }

        public void setXball(int x ){
          this.x=x;
        }

        public void setYball(int y){
            this.y = y;
        }

        public int getXball(){
            return x;
        }

        public int getYball(){
            return y;
        }

        public void moveBalls(){
            x+=speed;


        }

        public void drawballs(Graphics s) {

            s.setColor(Color.blue);
            s.fillRect(getXball(), getYball(), 5, 5);

        }
    }


    public static void main(String[]args){

     SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                Mypacman pacman = new Mypacman();
                pacman.showUI();
            }
        });

    }
}

please correct me if i am wrong thank you in advance.

Edited 2 Years Ago by toring

I don't know what your goal is, but what I'm seeing is a blue rectangle moving away from pacman yes. It could be that there are 10 balls that all start in the same spot moving at the same pace, judging from what I'm seeing in your constructor though.

Ok,thanks..sorry for that rectangle i forgot to draw it a circle..I'm changing it now to a circle...by the way can i ask,is there other way to draw the object not inside the paintComponent?..

 protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.fillArc(xPos,yPos,30,30,30,arcMouth);

            for(Balls b:listball){//how to perform this without inside
                b.drawballs(g);  //in painComponent ?
            }

        }

is it possible to do my forloop not inside in the paintComponent ?

Edited 2 Years Ago by toring

You could request the Graphics object from the super class (in this case, the jPanel you're drawing on). But you have be sure that it's not null. In other words, you can't draw the balls until the jPanel has a Graphics object to return. Also, you will have to move updateball to a position after the repaint method or the balls will never stay visible long enough for you to see.

        public void updatePosition(){
            xPos += 1;
            yPos += 0;

            if((xPos%2)==0){
                arcMouth=360;
            }
            else{
                arcMouth=300;
            }
        repaint();
        updateball();
        }

        public void updateball(){
            for(Balls b:listball){
                b.moveBalls();
                if(super.getGraphics()!=null){
                    b.drawballs(super.getGraphics());
                }
            }
        }

I don't know if it's more efficient though. I mean it makes sense to keep it in paintComponent since you're also drawing other stuff there. And it's all on the same panel anyway.

No no no!

Only ever draw on a Swing Graphics when you override paintComponent(Graphics g) (or, sometimes, paint(Graphics g))
Swing has all kinds of internal optimisation, including double-buffering that you don't see. If you start drawing to Swing's internal Graphics at random times then there's a major risk that it will just be ignored becauase the buffering isn't updated, and then simply overwritten next time any of Swing's paintXXX methods get executed (not under your control).
The standard solution is a Timer-controlled update method that just changes the internal state of your model and calls repaint, plus an overridden paintComponent that draws everything according to its current state. You can delegate some of the drawing by having your paintComponent call other methods passing it's Graphics. If that's not working for you then it's a bug on your implementation somewhere, but the approach is right so don't change that.

Comments
Thanks! I did not know that

@JamesCherrill,Thank you for the reply..are you talking to this post

     protected void paintComponent(Graphics g) {
       super.paintComponent(g);
       g.setColor(Color.RED);
       g.fillArc(xPos,yPos,30,30,30,arcMouth);
        for(Balls b:listball){//how to perform this without inside
        b.drawballs(g); //in painComponent ?
       }    
    }

No, I was referring to the post immediately before mine, specifically to super.getGraphics() etc.

The code you just quoted is 100% OK as it is.

The overall structure of your code is right, just some details of the implementation were giving you problems.

Edited 2 Years Ago by JamesCherrill

@JamesCherrill, from what part of my code

"just some details of the implementation were giving you problems."

?

Edited 2 Years Ago by toring

I don't have the latest version of yur code, and I don't know whether you have now fixed all the problems. My point was that the structure/architecture for you updating and painting was right, so any remaining problems will just be in the details. If you still have problems you can't fix, please explain them here and someone will help.

ps [Message to everyone in general] Thank you for not making any of the obvious jokes about this thread's subject. Your maturity is appreciated. ;)

Edited 2 Years Ago by JamesCherrill

This article has been dead for over six months. Start a new discussion instead.