/* --- CSU213 Fall 2006 Lecture Notes --------- Copyright 2006 Viera K. Proulx Lecture 11:October 2, 2006 The Pong Game */ import draw.*; import colors.*; import geometry.*; import java.util.Random; /* A Game of Pong +-------------------------------+ | | | | |* | | * | | * | | * | | * | | * | +-----------XXXX----------------+ Rules: A ball starts at a random height on the left and falls from the left side diagonally down. At the bottom is a paddle that can move left and right controlled by the arrow keys.When the ball hits the bottom, but misses the paddle, it disappears from the game. When the ball hits the paddle, it bounces back and continues diagonally up to the right. When the ball exits the playing field, a new ball comes into play. Classes needed: Ball - a Posn Paddle - a Posn World - contains Ball and Paddle */ /* // // // ++++: ++++: // +$$$$* ---$* ---$* // ++ +$ $* $* // ++ :$ -+$$+ $* $* // ++ -++ :* -++ $* $* // +$$@+ ++ $* $* // ++ *++ *+++ $* $* // ++ -@: *$+:++ $* $* // ++ $+ $+ ++ $* $* // ++ *@: ++ -+$ $* $* // +@@$$+ :$$+:$$ $* $* // // // */ // to represent a ball in a Pong game class Ball { Posn pos; int direction; // direction: +1 down-right, -1 up-right int UP = -1; int DOWN = 1; Ball(Posn pos, int direction) { this.pos = pos; this.direction = direction; } // move the ball diagonally down-right or up-right by three pixels Ball moveBall(){ return new Ball(new Posn(this.pos.x + 3, this.pos.y + 3 * this.direction), this.direction); } // reverse the ball direction as it bounces off the paddle // and move it a bit up as well Ball bounce(){ return new Ball(new Posn(this.pos.x + 3, this.pos.y - 3), this.UP); } // did the ball hit the bottom, given the height of the canvas? boolean hitBottom(int height){ return this.pos.y >= height; } // is the ball out of bounds, given the width of the canvas // we only are concerned about the right and top bounds boolean outOfBounds(int width, int height){ return this.pos.x < 0 || this.pos.x > width || this.pos.y < 0 || this.pos.y > height; } // draw this ball on the given canvas boolean draw(Canvas c){ return c.drawDisk(this.pos, 10, new Red()); } } /* // // // +: +: ++++: // +$$$$+ $* $* ---$* // +$ $+ $* $* $* // +$ ++ -+$$+ +$$*$* +$$*$* $* -+$+- // +$ $+ :* -++ *$+-+$* *$+-+$* $* -$+-+$ // +$:*+$ ++ ++ $* ++ $* $* ++ -@: // +$+++ *+++ $* $* $* $* $* $++++$* // +$ *$+:++ @: $* @: $* $* $+++++- // +$ $+ ++ ++ $* ++ $* $* ++ // +$ ++ -+$ ++--+$* ++--+$* $* *$* // +$ :$$+:$$ $@$-$* $@$-$* $* +$$$$* // // // */ // to represent a paddle in a Pong game class Paddle { Posn pos; Paddle(Posn pos) { this.pos = pos; } // move the paddle left or right, depending on the given key Paddle movePaddle(String ke){ if (ke.equals("left")) return new Paddle(new Posn(this.pos.x - 3, this.pos.y)); else if (ke.equals("right")) return new Paddle(new Posn(this.pos.x + 3, this.pos.y)); else return this; } // did this paddle hit the given ball? boolean hitBall(Ball b){ return this.isWithin(b.pos.x, this.pos.x - 15, this.pos.x + 15) && this.isWithin(b.pos.y, this.pos.y - 3, this.pos.y); } // is x between low and high? boolean isWithin(int x, int low, int high){ return (x >= low) && (x <= high); } // draw this paddle on the given canvas boolean draw(Canvas c){ return c.drawRect(new Posn(this.pos.x - 15, this.pos.y - 5), 30, 5, new Blue()); } } /* // // // +: +: ++++: ++++: +: // +$$$$+ $* $* ---$* +* +- ---$* $* // +$ $+ $* $* $* ++ $ $* $* // +$ ++ -+$$+ +$$*$* +$$*$* $* -+$+- ++ *+ $ ++$+ +**+$+ $* +$$*$* // +$ $+ :* -++ *$+-+$* *$+-+$* $* -$+-+$ *+ +@--+ +$: +$ $++*++ $* *$+-+$* // +$:*+$ ++ ++ $* ++ $* $* ++ -@::+ ++*:+ $+ @+ $+ -- $* ++ $* // +$+++ *+++ $* $* $* $* $* $++++$*-$ $++++-@: $+ $+ $* $* $* // +$ *$+:++ @: $* @: $* $* $+++++- @:+:++*-@- ++ $+ $* @: $* // +$ $+ ++ ++ $* ++ $* $* ++ $++ $+- @+ $+ $+ $* ++ $* // +$ ++ -+$ ++--+$* ++--+$* $* *$* +$: $$ ++- +$ $+ $* ++--+$* // +$ :$$+:$$ $@$-$* $@$-$* $* +$$$$* +@ +$ +$$$: $+ $* $@$-$* // // // */ // to represent a the Pong game world class PaddleWorld extends World { Ball ball; Paddle paddle; Color BACKG = new Black(); int HEIGHT = 200; int WIDTH = 300; int UP = -1; int DOWN = 1; PaddleWorld(Ball ball, Paddle paddle) { this.ball = ball; this.paddle = paddle; } // draw this game world boolean draw() { return this.theCanvas.drawRect(new Posn(0, 0), this.WIDTH, this.HEIGHT, this.BACKG) && this.ball.draw(this.theCanvas) && this.paddle.draw(this.theCanvas); } // erase this game world boolean erase() { return this.theCanvas.drawRect(new Posn(0, 0), this.WIDTH, this.HEIGHT, this.BACKG); } // produce a new game world form this game world moving the ball // in the given direction PaddleWorld move() { return new PaddleWorld(this.ball.moveBall(), this.paddle); } // produce a new game world from this game world in response to a key event World onKeyEvent(String ke) { return new PaddleWorld(this.ball, this.paddle.movePaddle(ke)); } // produce a new game world from this game world as it changes at each tick World onTick() { if (this.paddle.hitBall(this.ball)) return new PaddleWorld(this.ball.bounce(), this.paddle); else if (this.ball.outOfBounds(this.WIDTH, this.HEIGHT)) return new PaddleWorld(new Ball(new Posn(0, randomHeight()), this.DOWN), this.paddle); else return new PaddleWorld(this.ball.moveBall(), this.paddle); } // produce a random initial height of the ball int randomHeight(){ return new Random().nextInt() % (this.HEIGHT / 2); } } /* // // // ++++: // +$$$$$* ---$* // ++ $* // ++ ++ +: -+$$+ :+*$-*$* ++*+$* $* -+$+- *+$$+ // ++ *$: ++ :* -++ *+++++++ +++*+@ $* -$+-+$ -$: :* // +$$$$+ +$:$ ++ *$ *$ *+ ++ $* $* ++ -@: *$ // ++ $$+ *+++ *+ *+ *+ ++ ++ $* $++++$* +$+- // ++ +@* *$+:++ *+ *+ *+ ++ ++ $* $+++++- *+@+ // ++ +++$ $+ ++ *+ *+ *+ ++ $+ $* ++ *@ // ++ :$ ++ ++ -+$ *+ *+ *+ +$- +$ $* *$* :- +$ // +@@@@@+ $* -$+ :$$+:$$*+ *+ *+ +++$$: $* +$$$$* +$$$+: // ++ // ++ // +* */ // Examples of data and tests of all methods class Examples { Examples() {} int UP = -1; int DOWN = 1; Ball b1 = new Ball(new Posn( 20, 30), this.UP); Ball d1 = new Ball(new Posn( 20, 30), this.DOWN); Ball b2 = new Ball(new Posn( 180, -2), this.UP); Ball b3 = new Ball(new Posn( 201, 20), this.UP); Ball b4 = new Ball(new Posn( 152, 99), this.UP); Ball b5 = new Ball(new Posn( -2, 99), this.UP); Paddle p1 = new Paddle(new Posn(150, 100)); Canvas c = new Canvas(300, 100); // boolean start = c.show(); // test the moveBall method in the class Ball boolean testMoveBall = (check this.d1.moveBall() expect new Ball(new Posn(23, 33), this.DOWN)) && (check this.b1.moveBall() expect new Ball(new Posn(23, 27), this.UP)); // test the bounce method in the class Ball boolean testBounce = (check this.d1.bounce() expect new Ball(new Posn(23, 27), this.UP)) && (check this.b1.bounce() expect new Ball(new Posn(23, 27), this.UP)); // test the hitBottom method in the class Ball boolean testHitBottom1 = check this.b1.hitBottom(100) expect false; boolean testHitBottom2 = check this.b1.hitBottom(10) expect true; // test the outOfBounds method in the class Ball boolean testOutOfBounds1 = check this.b1.outOfBounds(100, 200) expect false; boolean testOutOfBounds2 = check this.b2.outOfBounds(200, 200) expect true; boolean testOutOfBounds3 = check this.b3.outOfBounds(200, 200) expect true; boolean testOutOfBounds4 = check this.b4.outOfBounds(200, 80) expect true; boolean testOutOfBounds5 = check this.b5.outOfBounds(100, 10) expect true; // test the movePaddle method in the class Paddle boolean testMovePaddle1 = check this.p1.movePaddle("left") expect new Paddle(new Posn(147, 100)); boolean testMovePaddle2 = check this.p1.movePaddle("right") expect new Paddle(new Posn(153, 100)); // test the isWithin method in the class Paddle boolean testIsWithin1 = check this.p1.isWithin(10, 5, 30) expect true; boolean testIsWithin2 = check this.p1.isWithin(10, 15, 30) expect false; boolean testIsWithin3 = check this.p1.isWithin(20, 5, 10) expect false; // test the hitBall method in the class Paddle boolean testHitBall1 = check this.p1.hitBall(this.b2) expect false; boolean testHitBall2 = check this.p1.hitBall(this.b4) expect true; // see that you can actually display the Ball boolean showCanvas(){ return this.c.show() && this.b1.draw(c) && this.b2.draw(c) && this.b3.draw(c) && this.b4.draw(c) && this.p1.draw(c); } // construct a paddle world to play the game PaddleWorld paddleWorldUP = new PaddleWorld(new Ball(new Posn(0, 0), this.UP), new Paddle(new Posn(150, 200))); PaddleWorld paddleWorldDOWN = new PaddleWorld(new Ball(new Posn(0, 0), this.DOWN), new Paddle(new Posn(150, 200))); // test the method move in the class PaddleWorld boolean testMove = (check this.paddleWorldUP.move() expect new PaddleWorld(new Ball(new Posn(3, -3), this.UP), new Paddle(new Posn(150, 200)))) && (check this.paddleWorldDOWN.move() expect new PaddleWorld(new Ball(new Posn(3, 3), this.DOWN), new Paddle(new Posn(150, 200)))); // test the method onKeyEvent in the class PaddleWorld boolean testOnKeyEvent = (check this.paddleWorldUP.onKeyEvent("left") expect new PaddleWorld(new Ball(new Posn(0, 0), this.UP), new Paddle(new Posn(147, 200)))) && (check this.paddleWorldUP.onKeyEvent("right") expect new PaddleWorld(new Ball(new Posn(0, 0), this.UP), new Paddle(new Posn(153, 200)))) && (check this.paddleWorldUP.onKeyEvent("up") expect this.paddleWorldUP); // test the method onTick in the class PaddleWorld boolean testTick = // when the paddle hits the ball (check this.paddleWorldUP.onTick() expect new PaddleWorld(new Ball(new Posn(3, -3), this.UP), new Paddle(new Posn(150, 200)))) && // when the ball is out of bounds (check this.paddleWorldUP.onTick() expect new PaddleWorld(new Ball(new Posn(3, -3), this.UP), new Paddle(new Posn(150, 200)))) && // when the ball goes on down (check this.paddleWorldUP.onTick() expect new PaddleWorld(new Ball(new Posn(3, -3), this.UP), new Paddle(new Posn(150, 200)))) && // when the ball goes on up (check this.paddleWorldUP.onTick() expect new PaddleWorld(new Ball(new Posn(3, -3), this.UP), new Paddle(new Posn(150, 200)))); // test the method randomHeight() in the class PaddleWorld boolean testRandomHeight = (check (this.p1.isWithin(this.paddleWorldUP.randomHeight(), 0, 100)) expect true); // play the game boolean playGame(double speed){ return this.paddleWorldDOWN.bigBang(this.paddleWorldDOWN.WIDTH, this.paddleWorldDOWN.HEIGHT, speed) && this.paddleWorldDOWN.draw(); } boolean go = this.playGame(0.01); }