HI all, been messing around with this game for a while now. last thing I need to do is get the score(bals dodged) to display in the main menu.Now I have had some helpful advice regarding this issue but I have notbeen able to implement it myself. Nevertheless I am grateful for any advice given and this is the penultimate phase of the game. the last thing to do is jar it, so others who don't have a java compiler can run it with simplicity. many thanks

/*Main Menu Graphical User Interface
 * Phillip Wells 10/12/07
 */

import java.awt.*;
import java.awt.Toolkit.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.geom.*;
import java.util.concurrent.*;
import java.util.ArrayList;



public class SaucerMenu extends JFrame 
{
    public static void main (String [] args)
    {
    new SaucerMenu();
    }


private JLabel ins1, ins2, ins3, scorel, rank;
private JButton play;
private JFrame panel1;
Image img;


public SaucerMenu()
    {
    this.setSize(300,300);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setTitle("Welcome to Saucer");
    
    ButtonListener b1 = new ButtonListener();

    JPanel panel1 = new JPanel();
    ImageIcon pic = new ImageIcon("images/welcome.gif");
    panel1.add(new JLabel(pic));
    panel1.setBackground(Color.BLACK);
    this.add(panel1);
    
    play = new JButton("Play!");
    play.setBackground(Color.GREEN);
    play.setForeground(Color.RED);
    play.addActionListener(b1);
    panel1.add(play);
    
    scorel = new JLabel("Last game score ");
    scorel.setForeground(Color.BLUE);
    panel1.add(scorel);
    
    rank = new JLabel("Last game Rank ");
    rank.setForeground(Color.BLUE);
    panel1.add(rank);
    
    ins1 = new JLabel("Use mouse to maneouver saucer. ");
    ins1.setForeground(Color.RED);
    panel1.add(ins1);
    
    ins2 = new JLabel("Dodge the incoming barrage of meteors to score.");
    ins2.setForeground(Color.RED);
    panel1.add(ins2);
    
    ins3 = new JLabel(" Lives are lost if your saucer is struck.");
    ins3.setForeground(Color.RED);
    panel1.add(ins3);
    
    this.setVisible(true);
    }

private class ButtonListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            if (e.getSource() == play)
            {
                // constructor  takes a references to the SaucerMenu instance
                Saucer game1 = new Saucer(SaucerMenu.this);
                game1.init();
            } 
        }
    }    

class Saucer extends JFrame {
    
    public static final int WIDTH = 400;
    public static final int HEIGHT = 400;
    Image img;
    private PaintSurface canvas;
    private SaucerMenu menuFrame;
    
    // Saucer  reference to SaucerMenu
    public Saucer(SaucerMenu menuFrame){
        this.menuFrame = menuFrame;
    }
    
    public void init() {
        
        this.setSize(WIDTH, HEIGHT);
        this.setTitle("Saucer");
        canvas = new PaintSurface();
        img = Toolkit.getDefaultToolkit().getImage("images/space.gif");
        this.getContentPane().add(canvas, BorderLayout.CENTER);
        ScheduledThreadPoolExecutor executor =
          new ScheduledThreadPoolExecutor(3);
        executor.scheduleAtFixedRate(new AnimationThread(this),
          0L, 20L, TimeUnit.MILLISECONDS);
        setVisible(true);
        
        menuFrame.setVisible(false);
        
        ///////////////////////////////
        // this function is necessary to
        // stop the process when the user
        // closes the window
        ///////////////////////////////
        //this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        // window listener will now call returnToMenu()
        // when user closes the game frame
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e){
                returnToMenu();
            }
        });
    }
    
    private void returnToMenu(){
        
        dispose();
        menuFrame.setVisible(true);
    }
    
    
    class AnimationThread implements Runnable {
        JFrame c;
        
        public AnimationThread(JFrame c) {
            this.c = c;
        }
        
        public void run() {
            c.repaint();
        }
    }
    
    class PaintSurface extends JComponent {
        int saucer_x = 0; // start position of saucer
        int saucer_y = 180;               
        int lives = 5;
        int score = 0;
        
        ///////////////////////////////
        //use an Array of Balls
        ///////////////////////////////
        ArrayList<Ball> balls;
        
        Color[] color = {Color.RED, Color.BLUE};
        int colorIndex;
        
        public PaintSurface() {
            addMouseMotionListener(new MouseMotionAdapter() {   //for mouse movement
                public void mouseMoved(MouseEvent e) {
                    saucer_x = e.getX() -30;
                    saucer_y = e.getY() -0;
                    
                }
            } );
            
            ///////////////////////////////
            //initialize the array
            balls = new ArrayList<Ball>();
            //create the first ball:
            balls.add(new Ball(20));
            ///////////////////////////////
        }
        
        public void paint(Graphics g) {
            Graphics2D g2 = (Graphics2D)g;
            g2.setRenderingHint(
              RenderingHints.KEY_ANTIALIASING,
              RenderingHints.VALUE_ANTIALIAS_ON);
            Shape saucer = new Ellipse2D.Float(
              saucer_x, saucer_y, 60, 10); // saucer dimensions
            g2.drawImage(img, 0, 0, this);
            g2.setColor(color[colorIndex % 6]);
            
            //loop to iterate among the balls:
            for(int i=balls.size()-1; i>=0; i--){
                
                Ball ball = balls.get(i);
                if (ball.intersects(saucer_x, saucer_y, 60, 10)
                && ball.y_speed > 0) {
                    
                    //set the ball position,
                    ball.reset();
                    
                    lives -= 1;
                    colorIndex = 0;
                }
                
                else if (ball.getY() + ball.getHeight() >= Saucer.HEIGHT) {
                    ball.reset();
                    
                    score += 1;
                    colorIndex = 0;
                    
                }
                ball.move();
                g2.fill(ball);
                
            }
            
            g2.setColor(Color.GREEN);
            g2.fill(saucer);
            g2.drawString("Balls Dodged: " + score, 30, 20);
            g2.drawString("Lives: " + lives, 300, 20);
            if (lives == 0)     
            {
                Showscore();
            }
            if (score == 5 && balls.size()<2) {
                //code to create a second ball on screen
                
                balls.add(new Ball(20));
                colorIndex++;
                
            }
            if (score == 10 && balls.size()<3) {
                
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 20 && balls.size()<4) {
                
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 50 && balls.size()<5) {
                
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 100 && balls.size()<6) {
                
                balls.add(new Ball(20));
                colorIndex++;
                lives += 1;
            }
            if (score == 110 && balls.size()<7) {
                
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 130 && balls.size()<8) {
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 150 && balls.size()<9) {
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 180 && balls.size()<10) {
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 195 && balls.size()<11) {
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 205 && balls.size()<12) {
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 220 && balls.size()<13) {
                balls.add(new Ball(20));
                colorIndex++;
                lives += 1;
            }
            if (score == 350 && balls.size()<14) {
                balls.add(new Ball(20));
                colorIndex++;
                lives += 1;
            }
             if (score == 500 && balls.size()<15) {
                balls.add(new Ball(20));
                colorIndex++;
                lives += 2;
            }
            if (score == 600 && balls.size()<16) {
                balls.add(new Ball(20));
                colorIndex++;
                lives += 3;
            }
        }
    }
    
    class Ball extends Ellipse2D.Float {
        public int x_speed, y_speed;
        private int d;
        private int width = Saucer.WIDTH;
        private int height = Saucer.HEIGHT;
        
        public Ball(int diameter) {
            super((int)(Math.random() * (Saucer.WIDTH - 20) + 1),
              0, diameter, diameter);
            this.d = diameter;
            this.x_speed = (int)(Math.random() * 2 - 3);
            this.y_speed = (int)(Math.random() * 5 + 5);
        }
        
        public void move() {
            if (super.x < 0 || super.x > width - d)
                x_speed = -x_speed;
            if (super.y < 0 || super.y > height - d)
                y_speed = -y_speed;
            super.x += x_speed;
            super.y += y_speed;
        }
        
        public void reset(){
            this.x = (float)(Math.random() * (Saucer.WIDTH - 20) + 1);
            this.y = 0; //ball position on screen
            this.x_speed = (int)(Math.random() * 3 - 2); //ball x axis speed and direction
            this.y_speed = (int)(Math.random() * 3 + 4);
        }
        
    }
    
    public void main(String[] args){
//        Saucer frame = new Saucer();
//        frame.setVisible(true);
//        frame.init();
    }
    
    public void Showscore() // show score when all lives lost
    {
        // need to call a method here to 
        // update the score in the saucer menu
    // updateScore();
       
      returnToMenu();
        
    }
    //public void updateScore();
    {
        
    }
}

}

Just one piece of advice. I noticed that if you maximize the screen the saucer can move really far away from the balls without them coming even close to it. (Notice my 11 lives and ~3000 balls dodged, that was from letting it run for a few minutes)

lol that is something i was not aware of! thanks for pointing that out, I shall make it so the user is unable to resize window- that'll do the trick!

You seem to have misunderstood my suggestion to incorporate the Saucer game class into the SaucerMenu. I was implying that you really only need a single frame for the menu and game. Just moving the Saucer class definition to be an inner class of SaucerMenu doesn't really help you much as you are still managing two frames and now you have even more nested class levels to keep straight.

Of course, Saucer does have direct access to the internal methods and state of SaucerMenu now, but it probably shouldn't from a design standpoint if you intend to keep it as a separate class and you are still using it as such. If you wish to keep the menu and game frames separate, you may as well put Saucer back into its own file for clarity and to avoid the unnecessary scope nesting of multiple inner classes.

As far as the score, it will depend on how you wish to delineate the class responsibilities. Should Saucer report its score to the menu when the game is finished or should the menu have to ask Saucer what the score was after the games is ended. This leads to the question: does SaucerMenu know when a game is running and when it ends?

Deciding upon clear responsibilities for the entities (classes) in your program and ensuring that those entities maintain that contract of separate responsibility in their interactions is an important part of program design.

i would prefer the former, whereby the score is thrown back to the menu. in regards to the nested classes I understand your point now, admttedly I did misunderstand you initially.However I think I shall leave it as the one class, because I have 5 other classes built already for this app, with more planned. I like to keep class size down if i can help it ! cheers

Decided to just have last score obtained shown in menu. this was acheived by declaring new variable 'scorefinal' and set this as equal to 'score' and used the setText method to apply score to jbutton on menu!Ezzaral/Jasimp if you two want the code then let me know and I shall mail it to you. many thanks! Game is finished now! (apart from layout managers - yuk lol).

This question has already been answered. Start a new discussion instead.