Thursday, November 7, 2013

Pong: Fully Operational

My "final" version of Pong includes some changes to the code (including a ball that speeds up the more it's hit by the paddles) and some updates to the Score Counter.

Let's begin with the "Board" class (which is my "world"):
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * The Board class is my world.
 * @Robert Griffith
 * @11/05/2013
 */
public class Board extends World
{
    public Board()
    {    
        // Create a new world with 600x400 cells with a cell size of 1x1 pixels.
        super(640, 480, 1); 
        prepare();
    }
    private void prepare()
    {
        Ball ball = new Ball();
        addObject(ball, 320, 240);
        
        Scores scores = new Scores();
        addObject(scores, 320, 20);
        
        Paddle1 paddle1 = new Paddle1();
        addObject(paddle1, 10, 240);
        Paddle2 paddle2 = new Paddle2();
        addObject(paddle2, 630, 240);

    }
}
Next we will add the "Scores" class (a subclass of Actor):
import greenfoot.*;
import java.awt.Color;

/**
 * Score Display using  "getObjects" and java.awt.Color to write on screen.
 */
public class Scores extends Actor
{
    int maxScore = 10;
    int score1 = 0;
    int score2 = 0;

    public void act()   
    {    
        if (!getWorld().getObjects(Ball.class).isEmpty())   
        {    
            int score1 = ((Ball) getWorld().getObjects(Ball.class).get(0)).getScore1(); 
            int score2 = ((Ball) getWorld().getObjects(Ball.class).get(0)).getScore2(); 
            setImage(new GreenfootImage(" Player One: " + score1 + "              Player Two: "+score2+" ", 24, Color.white, Color.black));
            if (score1 == maxScore)
            {
                setImage(new GreenfootImage(" Player 1 Wins! ", 48, Color.white, Color.black));
                Greenfoot.stop();
            }
            if (score2 == maxScore)
            {
                setImage(new GreenfootImage(" Player 2 Wins! ", 48, Color.white, Color.black));
                Greenfoot.stop();
            }}    
    }    
}
Then the "Ball" class -- which does most of the work in the program:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * This is the Ball for our Pong game.
 * @Robert Griffith 
 * @11/05/2013
 */
public class Ball extends Actor
{
    double x = 320; // (getWorld().getWidth())/2;  // Half my world width
    double y = 240; // (getWorld().getHeight())/2; // Half my world height
    double yDirection;
    double xDirection;
    double ballSpeedStart = 2.000;
    double ballSpeed = ballSpeedStart;
    double speedIncrease = 0.001;
    int score1 = 0;
    int score2 = 0;
    int start = 0;

    // Cycle through the main program.
    public void act() 
    {
        if (start == 0){ startup(); }
        paddleBounce(); // Test for paddle bounce
        edgeBounce(); // Test for edge bounce
        x = x + xDirection;
        y = y + yDirection;
        int x1 = (int) x;
        int y1 = (int) y;
        setLocation(x1, y1);
    } 
    // Set the direction and speed of the Ball -- randomly at first.
    public void startup(){  
        start++;
        if ( Greenfoot.getRandomNumber(100) < 50 ) 
        { yDirection = -1*ballSpeedStart; } 
        else { yDirection = ballSpeedStart; }
        if ( Greenfoot.getRandomNumber(100) < 50 ) 
        { xDirection = -1*ballSpeedStart; } 
        else { xDirection = ballSpeedStart; }
    }
    // If we reach the edge of the world, bounce.
    public void edgeBounce()
    {
        if (atWorldEdge())
        {
            Greenfoot.playSound("4389__noisecollector__pongblipf-3.wav");
            if (x > 640) // Give Player1 Score & Launch Another Ball
            { 
                score1++;
                x = (getWorld().getWidth())/2;
                y = (getWorld().getHeight())/2;
                ballSpeed = ballSpeedStart;
                start = 0;
            }
            if (x < 0) // Give Player2 Score & Launch Another Ball
            { 
                score2++;
                x = (getWorld().getWidth())/2;
                y = (getWorld().getHeight())/2;
                ballSpeed = ballSpeedStart;
                start = 0;
            }
            if (y < 0 || y > getWorld().getHeight()) {yDirection = yDirection * -1;} // Bounce off roof or floor.
        }
    }
    // If the ball hits either paddle, reverse the direction of the ball.
    public boolean paddleBounce()
    {
        if (canSee(Paddle1.class))
        {
            Greenfoot.playSound("4391__noisecollector__pongblipf-5.wav");
            ballSpeed = ballSpeed + speedIncrease;
            xDirection = xDirection - ballSpeed;
            xDirection = (xDirection) * (-1);

        }
        if (canSee(Paddle2.class))
        {
            Greenfoot.playSound("4391__noisecollector__pongblipf-5.wav");
            ballSpeed = ballSpeed + speedIncrease;
            xDirection = xDirection + ballSpeed;
            xDirection = (xDirection) * (-1);
        }
        return false;
    }
    // Check to see if we can see an object.
    public boolean canSee(Class clss)  
    {  
        Actor actor = getOneObjectAtOffset(0, 0, clss);  
        return actor != null;          
    }  
    // Test if we are close to one of the edges of the world. Return true if we are.
    public boolean atWorldEdge()
    {
        if(getX() < 10 || getX() > getWorld().getWidth() - 10)
            return true;
        if(getY() < 10 || getY() > getWorld().getHeight() - 10)
            return true;
        else
            return false;
    }
    // Holds score1 variable to be called by the Scores class for display.
    public int getScore1()
    {return score1;}  
    // Holds score2 variable to be called by the Scores class for display.
    public int getScore2() // The Scores class reads this for display
    {return score2;}  
}
Finally, we will implement the paddles. First, Paddle1:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * The left paddle (Paddle1) class.
 * @Robert Griffith
 * @11/05/213
 */
public class Paddle1 extends Actor
{
    int y = 240;
    int paddleSpeed = 10;

    /**
     * Run the program.
     */
    public void act() 
    {
        checkKeys();
    }    

    /**
     *  Check keys and move the paddle
     */
    public void checkKeys()
    {
        if ( Greenfoot.isKeyDown("a"))
        {
            y=y-paddleSpeed;
            if (y < 48) {y = 48; } // y = half my paddle height
            setLocation(10, y); // Set the x coordinate at 10
        }
        if ( Greenfoot.isKeyDown("z"))
        {
            y=y+paddleSpeed;
            if (y > 432) {y = 432; } // y = world width - half my paddle height
            setLocation(10, y); // Set the x coordinate at 10
        }
    }
}
And Paddle2 -- which is nearly identical to Paddle1:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Paddle1 here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Paddle2 extends Actor
{
    int y = 240;
    int paddleSpeed = 10;
    
    
    /**
     * Act - do whatever the Paddle1 wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        checkKeys();
    }    
    
    /**
     *  Check keys and move the paddle
     */
    public void checkKeys()
    {
        if ( Greenfoot.isKeyDown("up"))
        {
            y=y-paddleSpeed;
            if (y < 48) {y = 48; }
            setLocation(630, y);
        }
         if ( Greenfoot.isKeyDown("down"))
        {
            y=y+paddleSpeed;
            if (y > 432) {y = 432; }
            setLocation(630, y);
        }
       
    }
}

No comments:

Post a Comment