Pardon the mess, Play My Code is in beta!

READY TO PLAY?
CLICK TO LOG IN!

sign up - lost password

Pong »

You do not own this project, so changes will not be saved

/**
 * Pong
 * 
 * @date 1/5/12
 * @author Curtis Ullerich
 * 
 * The intention of this game is to use as a tool
 * for teaching programming concepts. This implementation
 * is not perfect, but it's pretty solid. I wrote this in 
 * one sitting (a few hours) and it's my first game written
 * from scratch, so it's pretty basic. 
 * 
 * Note about the AI: The "AI" player is very simple. It moves 
 * toward the ball's y position at a pseudorandom speed that is
 * flighted based on the level's difficulty. In an attempt to 
 * make it easier (and possible at all) to beat, the AI paddle
 * only moves when the ball is on the right half of the court.
 * The biggest strategic aid to the human player is that the 
 * velocity of the ball is affected based on the point of contact
 * with the paddle (human only). Hitting at an edge results in a
 * 60% increase in speed and hitting in the center results in a 10% 
 * reduction in speed. Careful contact with the ball causes it to
 * move faster than the AI is able to react. Any suggestions for
 * improving this are welcome.
 * 
 */

$PADDLE_WIDTH = 10
$PADDLE_HEIGHT = 80
$SIM_OFFSET = 0 
$PADDLE_SPEED = 7
$BALL_DIAMETER = 20 //yes, it's really a rectangle. Get over it.
$GAME_STATE = 0 //0 for new, 1 for in play, 2 for game over
$PLAYER_SCORE = 0
$SIM_SCORE = 0
$BOOP = new Sound("pong.wav")
$BOP = new Sound("pong2.wav")
$MAX_SCORE = 10

player = new Paddle(10, getScreenHeight() / 2, false)
sim = new Paddle(getScreenWidth()-10, getScreenHeight()/2, true)

ball = new Ball()
game = new Game()
timer = new Timer(1000)

onEachFrame() do

    if !timer.isExpired() && $GAME_STATE != 0   
        ball.draw()
        //wait
    else
        fill(0,0,0) //if you don't do this at each frame, you end up with trails everywhere    
        if $GAME_STATE == 0 //title screen
            game.titleScreen()  
    
        else if $GAME_STATE == 1 //game currently in play
            game.printScores()
            
            ball.checkCollisions(player, sim)
            ball.update()
    
            player.update(ball.getX(), ball.getY())
            sim.update(ball.getX(), ball.getY())
                
            if (ball.checkPoint())
                ball = new Ball() 
                timer.reset()
            end
            
        else //somebody won
            game.endScreen()
        end
    end

end

//contains functions for printing title and ending screens, 
//initializes scores, and updates scores
class Game
    def new()
        $PLAYER_SCORE = 0   
        $SIM_SCORE = 0
    end

    //doesn't seem to work at the moment.
    //intended to be used after each score so a new ball isn't generated immediately
    def delay(ms)
        
    end

    //the opening screen
    def titleScreen()
        setFont('Arial', 100)
        fillText("Pong",getScreenWidth()/2,getScreenHeight()/2,true)
        setFont('Arial',15)
        fillText("Move your paddle with the arrow keys.\n\nScore ten points to win.\n\nPress any key to play.",getScreenWidth()/2,getScreenHeight()*4/5,true)
        if (getControls().isKeyDown())
            $GAME_STATE = 1
        end
    end

    //after someone wins
    def endScreen()
        setFont('Arial', 100)   
        if $SIM_SCORE == $MAX_SCORE
            fillText("You lose.", getScreenWidth()/2, getScreenHeight()/2,true)
        end
        
        if $PLAYER_SCORE == $MAX_SCORE 
            fillText("You win.",getScreenWidth()/2, getScreenHeight()/2,true)
        end
        
        setFont('Arial', 30)
        fillText("Press space to play again.", getScreenWidth()/2,getScreenHeight()-40,true)
        if (getControls().isKeyDown(:space))
            $GAME_STATE = 1
            $PLAYER_SCORE = 0
            $SIM_SCORE = 0

        end

    end

    //updates scores after each point
    def printScores()    
        setFont('Arial', 50)
        fillText($SIM_SCORE,getScreenWidth()*5/6, getScreenHeight()*5/6)
        fillText($PLAYER_SCORE,getScreenWidth()/6, getScreenHeight()*5/6)
    end
    
end

//A simple rectangular paddle. Either "ai" or human-controlled.
class Paddle
    def new(x,y, isSim)
        @x = x 
        @isSim = isSim 
        @y = y
        @dY = $PADDLE_SPEED //the velocity of the paddle in pixels per frame
    end

    def getX()
        return @x
    end
    
    def getY()
        return @y
    end    

    //updates the position of the paddle based on control or ai
    def update(ball_x, ball_y)
        
        //this logic determines how fast the ai paddle moves towards the ball.
        //dependent on what the highest current score is
        cap = $PLAYER_SCORE
        if $SIM_SCORE > $PLAYER_SCORE
            cap = $SIM_SCORE
        end
        if cap < 4
            cap = 4
        end

        if @isSim //move paddle towards ball
            if (@y < ball_y - 20 && ball_x > getScreenWidth() / 2) 
                @y = @y + cap + $SIM_OFFSET
            end
            if (@y > ball_y + 20 && ball_x > getScreenWidth() / 2)
                @y = @y - cap - $SIM_OFFSET
            end
        end

        if !@isSim //respond to user control
            if (getControls().isKeyDown( :down ) && @y <= (getScreenHeight() - $PADDLE_HEIGHT / 2))
               @y = @y + @dY
            end
            
            if (getControls().isKeyDown( :up ) && @y >= ($PADDLE_HEIGHT / 2) )
                @y = @y - @dY
            end
        end

        //draw the rectangle based on the updated coordinates. 
        //called once per frame in main loop
        fillRect(@x, @y, $PADDLE_WIDTH, $PADDLE_HEIGHT,true)
    end    
    
end

//the ball. Actually a rectangle.
class Ball
    def new()
        @x = getScreenWidth() / 2
        @y = getScreenHeight() / 2

        //this determines the highest randomly generated speed
        //for a ball at time of spawning
        cap = $PLAYER_SCORE
        if $SIM_SCORE > $PLAYER_SCORE
            cap = $SIM_SCORE
        end
        if cap < 3
            cap = 3
        end        

        //randomly (50% of spawns) sends a ball
        //left instead of right
        pos = 1
        if randBoolean()
            pos = -1
        end

        //determines the initial velocity of the ball based on
        //x and y delta values
        @dX = pos * rand(2, cap)
        @dY = pos * rand(2, cap)
                
    end

    //checks to see if the ball is out of bounds 
    //i.e. if there is a score to update
    def checkPoint()
        refresh = false
        if @x < 0
            $SIM_SCORE = $SIM_SCORE + 1
            return true
        end
        if @x > getScreenWidth()
            $PLAYER_SCORE = $PLAYER_SCORE + 1
            return true
        end 

        //ends the game if somebody reached ten points
        if $SIM_SCORE == $MAX_SCORE || $PLAYER_SCORE == $MAX_SCORE
            $GAME_STATE = 2
        end
        
        return false

    end

    //checks to see if a paddle has made contact with a ball
    def checkCollisions(player, sim)        

        //checks the player's paddle
        if (isRectOverlap( @x, @y, $BALL_DIAMETER, $BALL_DIAMETER, player.getX(), player.getY(), $PADDLE_WIDTH, $PADDLE_HEIGHT,true))

            //reset the ball's x position so it's never "inside" the paddle, which causes multiple collisions
            @x = player.getX()+$PADDLE_WIDTH/2+$BALL_DIAMETER/2 

            @dX = @dX * -1
            offset = (player.getY() - @y).abs() / ($PADDLE_HEIGHT / 2)   
            @dX = @dX * (offset *.6 +.9)
            @dY = @dY * (offset *.6 +.9)
            $SIM_OFFSET = rand(-1,3)
            $BOOP.play()
        end

        //checks the ai paddle
        if (isRectOverlap( @x, @y, $BALL_DIAMETER, $BALL_DIAMETER, sim.getX(), sim.getY(), $PADDLE_WIDTH, $PADDLE_HEIGHT,true))

            @dX = @dX * -1
            $SIM_OFFSET = rand(-1,3)
            $BOOP.play()
        end

        //checks upper and lower boundaries
        if (@y > getScreenHeight() - $BALL_DIAMETER/2 || @y < $BALL_DIAMETER/2)
            @dY = @dY * -1        
            $BOP.play()
        end        
    end

    def getX()
        return @x
    end
    
    def getY() 
        return @y
    end
    
    def update()
        @x = @x + @dX
        @y = @y + @dY
        fillRect(@x,@y,$BALL_DIAMETER, $BALL_DIAMETER,true)
    end
    
    def draw()
        fillRect(@x,@y,$BALL_DIAMETER, $BALL_DIAMETER,true)     
    end    
        
end

ERRORS

YOUR BROWSER DOES NOT SUPPORT HTML5!

Please use one of these instead

Our games cannot run in your browser