/* *Class Ball * *Created by Martin Carlsson * *Internetprogrammering 1 - Course **/ import javax.swing.*; import java.awt.*; /**Ball is a threaded class that implements the Runnable interface and takes care of Ball positions. *If a player is in "active mode" the thread starts and the ball position *is passed on to the Sender class to be sent to the opponent peer. *If - on the other hand - the player is in "passive mode" the *only thing class Ball does is keeping track of the ball status. * *@author Martin Carlsson * */ public class Ball extends JPanel implements Runnable { private int frequency = 100; // loopes each 100:e millisekond private int radie; private int height; private int width; private int xPos; private int yPos; private int xStep; // how big steps, horizontally private int yStep; // how big steps, vertically private int speed ; // velocity private final int initSpeed = 5; private final int maxSpeed = 45; private boolean looping=false; private MagnificentBall gui; private GameArea gA; private Player p1,p2; private Sender sender; private Color color = Color.red; /** *Constructs a Ball object(instance) with references to the GUI(MagnificentBall), *the game area(GameArea), both players(objects of class Player), and class Sender. *@param gui GUI reference *@param gA Game area reference *@param p1 Player 1 reference *@param p2 Player 2 reference *@param sender reference to the Sender object *@see MagnificentBall *@see GameArea *@see Player *@see Sender */ public Ball(MagnificentBall gui, GameArea gA, Player p1, Player p2, Sender sender) { this.gA = gA; this.p1 = p1; this.p2 = p2; this.gui = gui; this.sender = sender; radie = gA.getYmax() / 25; height = width = radie * 2; xStep = yStep =speed = initSpeed; } /** *Loops at a certain frequency and calls the internal method handleBall(), *as well as the paintComponent() method in class GameArea. *@see GameArea *@see #handleBall() */ public void run() { while(true) { try { Thread.sleep(frequency); synchronized(this) { while (!looping) wait(); // used to paus the ball/game } // end synchronized block } //end try catch (InterruptedException e) { } // end catch handleBall(); // call to the method that handles all the logic gA.paintGameComponents(); // updates the game area } // end while } // end run /** *To loop or not to loop *@param b true or false */ public synchronized void setLooping(boolean b) { looping = b; if (looping) notify(); } /** *Returns ball color *@return a Color object */ public Color getColor() { return color; } /** *Sets the looping frequency. *@param i frequency number */ public void setFrequency(int i) { frequency = i; } /** *Returns the ball radius. *@return the ball radius */ public int getRadie() { return radie; } /** *Sets the ball's x-position @param xPos Ball x-position */ public void setXPos(int xPos) { this.xPos = xPos; } /** *Sets the ball's y-position @param yPos Ball y-position */ public void setYPos(int yPos) { this.yPos = yPos; } /** *Returns ball x-position *@return balls x-position */ public int getXPos() { return xPos; } /** *Returns the ball's y-position. @return ball y-position */ public int getYPos() { return yPos; } /** *Returns the ball height @return ball height */ public int getHeight() { return height; } /** *Returns ball width *@return ball width */ public int getWidth() { return width; } /** *Returns the ball's initial speed *@return initial speed */ public int getInitSpeed() { return initSpeed; } /** *Returns max speed *@return ball max speed */ public int getMaxSpeed() { return maxSpeed; } /** *Returns ball step lenght, horizontal step length *@return horizontal ball step length */ public int getXStep() { return xStep; } /** *Sets ball step length, horizontal step length *@param xStep horizontal ball step length */ public void setXStep(int xStep) { this.xStep = xStep; } /** *Returns ball step lenght, vertical step length *@return vertical ball step length */ public int getYStep() { return yStep; } /** *Sets ball step lenght, vertical step length @param yStep vertical ball step length */ public void setYStep(int yStep) { this.yStep = yStep; } /** *Sets ball speed @param speed ball speed */ public void setSpeed(int speed) { this.speed = speed; } /** *Controls ball behaviour and how the ball should move within the game area */ protected void handleBall() { if(xPos - radie <= p1.getWidth()) { // is the ball on the left player(the player one's self control) longitud? if(yPos < p1.getYpos() || yPos > p1.getYpos() + p1.getHeight()) { // vertically outside the left player, i.e. a miss p1.setLife(p1.getLife() - 1); // if a miss, 1 life is lost if(p1.getLife() <= 0) { // if the number of lifes left is 0 or less it's game over gA.setGameOver(); // game over sequence is played p1.setLife(0); // put life to 0 } gui.setPlayerOneLife(String.valueOf(p1.getLife())); // show in GUI the new life status if(speed < maxSpeed)// if not max speed speed += 2;// increase by 2 } // end if, i.e vertically outside the left player(one self) else { // vertically within the left player(the ball hits the left player) sender.sendAway(xPos, yPos, p2.getLife(), p2.getPoints(), p1.getLife(), p1.getPoints(), "hit"); // send info on hit Toolkit.getDefaultToolkit().beep(); // play a beep sound p1.setPoints(p1.getPoints() + 1); // increase left player score if(p1.getPoints() == Player.getBonusLimit()) {// if the score is on the bonus limit p1.setLife(p1.getLife() + 5);// a bonus of 5 extra lifes gui.setPlayerOneLife(String.valueOf(p1.getLife())); // show the bonus lifes in GUI gui.setPlayerLifeColor("p1"); // change color of life status text } gui.setPlayerOnePoints(String.valueOf(p1.getPoints())); // show in GUI the increased score if(speed < maxSpeed)// if not max speed yet speed += 1;// increase with 1 } // end else, i.e a hit(vertically within the left player) gA.sendStatus("lifeAndScore"); // send life and score status xStep = speed; // move to the right next tim, with a speed(step length) of the value of the speed variable } // end outer if, i.e. if the ball is on the left in the game area on the same longitud as the left player // if the ball instead is on the right side of the game area with the same longitud as the right player else if(xPos + radie >= gA.getXMax() - p2.getWidth()) { if(yPos < p2.getYpos() || yPos > p2.getYpos() + p2.getHeight()) { // vertically outside the right player, i.e a miss p2.setLife(p2.getLife() - 1); // if so, one life is lost if(p2.getLife() <= 0) { // if the number of lifes left is equal to or less than 0, it's game over gA.setGameOver();// play game over sequence p2.setLife(0); // put life to 0 } gui.setPlayerTwoLife(String.valueOf(p2.getLife())); // show decreased number of lifes in GUI if(speed < maxSpeed) // if not max speed yet speed += 2 ;// increase speed by 2 } // end if, i.e a miss, i.e vertically outside the right player else { // vertically against the right player(your opponent), i.e. a hit. sender.sendAway(xPos, yPos, p2.getLife(), p2.getPoints(), p1.getLife(), p1.getPoints(),"hit"); //send info on hit Toolkit.getDefaultToolkit().beep(); // play a beep sound p2.setPoints(p2.getPoints() + 1); // increase the right player's score by 1 if(p2.getPoints() == Player.getBonusLimit()) { // if it should be a bonus p2.setLife(p2.getLife() + 5); // then give one, 5 extra lifes gui.setPlayerTwoLife(String.valueOf(p2.getLife())); // make this bonus visible in the GUI gui.setPlayerLifeColor("p2"); // change color of the life text } gui.setPlayerTwoPoints(String.valueOf(p2.getPoints())); // show increased score in GUI if(speed < maxSpeed) // if not max speed yet speed += 1; // öka speed/hastigheten med 1 } gA.sendStatus("lifeAndScore"); // send life and score status xStep =- speed; //move to the left next time with the step length(speed) of the speed varible } // end else if, i.e. if the ball is on the right side with the vertically same position as the player avatar if(yPos-radie <= 0 || yPos+radie >= gA.getYmax()) yStep =- yStep; // change direction vertically if the ball is on the top or at the bottom of the game area // the balls constant movement in x and y directions xPos += xStep; yPos += yStep; // If the ball doesn't behave if(xPos < radie) // goes to far in the left wall of the game area xPos = radie; // since the x-position is in the ball center, xPos is set to the ball radie else if(xPos > gA.getXMax() - radie) // goes to far in the right game area wall xPos = gA.getXMax() - radie; // x-positionen gets the value of the game area xMax minus the ball radie. if(yPos < radie) // to deep in the upper top wall of the game area yPos = radie; // // since the y-position is in the ball center, yPos is set to the ball radie else if(yPos > gA.getYmax() - radie) // bottom wall of the game area yPos = gA.getYmax() - radie; // set yPos to the value of the game area yMax minus the ball radie else if(xPos < (radie + p1.getWidth()) && yPos > p1.getYpos() && yPos < p1.getYpos() + p1.getHeight()) //if against the left player xPos = radie + p1.getWidth(); // xPos gets the value of ball radie plus the player width else if(xPos>gA.getXMax() - radie - p2.getWidth() && yPos > p2.getYpos() && yPos < p2.getYpos() + p2.getHeight()) //if against the right player xPos = gA.getXMax() - radie - p2.getWidth(); sender.sendAway(xPos, yPos, 0, 0, 0, 0, "ball"); // send the ball position by using an instance of the Sender class. } } //End class Ball