hi all. I was wondering if anybody out there knew how to implement a high score system for this game(saucer). SaucerMenu is a gui class where i want the high scores to appear (up to 5 highest). saucer is the class where the game resides. many thanks in advance.

/* A game that is Saucer-like
 * Phillip Wells
 */
 
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 Saucer extends JFrame {
    
    public static final int WIDTH = 400;
    public static final int HEIGHT = 400;
    Image img;
    private PaintSurface canvas;
    
    
    
    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);
        
        ///////////////////////////////
        // this function is necessary to 
        // stop the process when the user 
        // closes the window
        ///////////////////////////////
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    
    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 score = 0;
        int lives = 5;
        
        ///////////////////////////////
        //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;
                    //score -= 100;
                    colorIndex = 0;
                }
                
                else if (ball.getY() + ball.getHeight() >= Saucer.HEIGHT)
                {
                    ball.reset();
                    
                    score += 10;
                    colorIndex = 0;
                }
                ball.move();
                g2.fill(ball);
                
            }
                        
            g2.setColor(Color.GREEN);
            g2.fill(saucer);
            g2.drawString("Score: " + score, 300, 20);    
            g2.drawString("Lives: " + lives, 200, 20); 
            if (lives == 0);
                {
                    Showscore();
                }
            if (score == 50 && balls.size()<2)
            {
                //code to create a second ball on screen
                            
                balls.add(new Ball(20));
                colorIndex++;
                
            }
             if (score == 100 && balls.size()<3)
            {               
                
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 200 && balls.size()<4)
            {
                               
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 500 && balls.size()<5)
            {
               
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 1000 && balls.size()<6)
            {
               
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 1100 && balls.size()<7)
            {
                
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 1300 && balls.size()<8)
            {
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 1500 && balls.size()<9)
            {
                balls.add(new Ball(20));
                colorIndex++;
            }
             if (score == 1800 && balls.size()<10)
            {
                balls.add(new Ball(20));
                colorIndex++;
            }
        }
    }
    
    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
    {
       
       
    }
}
/*Main Menu Graphical User Interface
 * Phillip Wells 10/12/07
 */

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;


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


private JLabel ins1, ins2, ins3, score, 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);
    
    score = new JLabel("Last game score ");
    score.setForeground(Color.BLUE);
    panel1.add(score);
    
    rank = new JLabel("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)
            {
                Saucer game1 = new Saucer();
                game1.init();
            } 
        }
    }    


}

Recommended Answers

All 6 Replies

forgot to add that i am also having trouble getting game to quit to main menu after 5 lives are gone. the lives counter just prints out negative values.many thanks.

Maybe you could create a fairly simple Score class that records the player's name and score, and use an ArrayList of Score objects to record the order of high scores. Then to display them, possibly use a JDialog or JOptionPane? Check out sun's tutorial on using dialogs for more info on how to implement this.

Good luck,
darkagn :)

thanks for the advice darkagn, have read the tutorial before but will revisit to refresh my memory :-) will give it a bash. what i tried (unsuccessfully) to do before was get public void Showscore() to call the menu class, which in turn will call the saucer class for score stats! However I cannot really do this until I get a GAMEOVER state when all the players lives are lost...

Ok, here are some basic changes to get you started in the right direction. Saucer now takes a reference to its SaucerMenu from the constructor, so it can interact with the menu. I've put a returnToMenu() function in that is called when the Saucer frame closes and from showScore().

showScore() was always getting called regardless of whether (lives==0) because you had a semi-colon after the if() condition - essentially an empty statement and what should have been a conditional block was just a regular nested block.

I've put a couple of comments in where I altered things. Now you will need to create some method in SaucerMenu that Saucer can call to report the game score when it closes. That method can also check against a collection of high scores and update it if needed. You'll probably want to write that to a file when the program closes and read it on start up.

Another consideration is just making the game panel be part of the SaucerMenu class instead of a free-standing JFrame, which would do away with the need to interact between the two altogether.

I see that you still have game logic in your paint() method as well. That really should be moved to it's own method separate from the rendering. Your game loop (the animation thread) needs to evaluate the game logic each iteration, update game state, and then trigger repaint. Clean separation of these responsibilities will make your code easier to manage.

/* A game that is Saucer-like
 * Phillip Wells
 */

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 Saucer extends JFrame {
    
    public static final int WIDTH = 400;
    public static final int HEIGHT = 400;
    Image img;
    private PaintSurface canvas;
    
    private SaucerMenu menuFrame;
    
    // Saucer needs a reference to SaucerMenu
    // if it is to interact with it
    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 score = 0;
        int lives = 5;
        
        ///////////////////////////////
        //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;
                    //score -= 100;
                    colorIndex = 0;
                }
                
                else if (ball.getY() + ball.getHeight() >= Saucer.HEIGHT) {
                    ball.reset();
                    
                    score += 10;
                    colorIndex = 0;
                }
                ball.move();
                g2.fill(ball);
                
            }
            
            g2.setColor(Color.GREEN);
            g2.fill(saucer);
            g2.drawString("Score: " + score, 300, 20);
            g2.drawString("Lives: " + lives, 200, 20);
            if (lives == 0)     // don't put a semi-colon here :)
            {
                Showscore();
            }
            if (score == 50 && balls.size()<2) {
                //code to create a second ball on screen
                
                balls.add(new Ball(20));
                colorIndex++;
                
            }
            if (score == 100 && balls.size()<3) {
                
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 200 && balls.size()<4) {
                
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 500 && balls.size()<5) {
                
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 1000 && balls.size()<6) {
                
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 1100 && balls.size()<7) {
                
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 1300 && balls.size()<8) {
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 1500 && balls.size()<9) {
                balls.add(new Ball(20));
                colorIndex++;
            }
            if (score == 1800 && balls.size()<10) {
                balls.add(new Ball(20));
                colorIndex++;
            }
        }
    }
    
    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
    {
        // you will need to call a method here to 
        // update the score in the saucer menu
        returnToMenu();
        
    }
}
/*Main Menu Graphical User Interface
 * Phillip Wells 10/12/07
 */

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;


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


private JLabel ins1, ins2, ins3, score, 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);
    
    score = new JLabel("Last game score ");
    score.setForeground(Color.BLUE);
    panel1.add(score);
    
    rank = new JLabel("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 now takes a references to the SaucerMenu instance
                Saucer game1 = new Saucer(SaucerMenu.this);
                game1.init();
            } 
        }
    }    


}

THanks very much for all your help Ezzaral, my game is coming together quite nicely now with your help. I appreciate it.

Have decided that I shall incorporate the two classes, I believe it will be easier to create a score board that way. This game is forms part of a small collection of games that I am/have creating(or ed!) which are brought together by a comprehensive GUI. this is my first major project into java as a gaming platform, hence the problems! thanks for your help

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.