//Pong - John Salis
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferStrategy;
import java.util.Random;
import java.util.Vector;
public class PongBoard extends Canvas implements Runnable, KeyListener
{
public static final int WIDTH = 720;
public static final int HEIGHT = 600;
private Random random;
private final int BALL_SIZE = 16;
private BallSpawner ballSpawner;
private Vector<Ball> activeBalls = new Vector<Ball>();
private Bound leftBound, rightBound, topBound, bottomBound;
private int padHeight;
private Player leftPlayer, rightPlayer;
private PowerUp leftPowerUp, rightPowerUp;
public final static int GAME_SPEED = 1000 / 40; // milliseconds / FPS
private Thread thread;
private volatile boolean isRunning = false;
private int tickCount = 0;
private int leftPowerUpRespawn = 0;
private boolean QPressed = false;
private boolean APressed = false;
private boolean PPressed = false;
private boolean LPressed = false;
public PongBoard()
{
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
addKeyListener(this);
topBound = new Bound(20, 20, WIDTH - 40, 20);
bottomBound = new Bound(20, HEIGHT - 80, WIDTH - 40, 20);
leftBound = new Bound(20, 20, 20, HEIGHT - 80);
rightBound = new Bound(WIDTH - 40, 20, 20, HEIGHT - 80);
padHeight = 100;
leftPlayer = new Player(60, (HEIGHT - 40 - padHeight) / 2, padHeight);
leftPlayer.addCollision(topBound);
leftPlayer.addCollision(bottomBound);
leftPlayer.setBallCollision(activeBalls);
rightPlayer = new Player(WIDTH - 72, (HEIGHT - 40 - padHeight) / 2, padHeight);
rightPlayer.addCollision(topBound);
rightPlayer.addCollision(bottomBound);
rightPlayer.setBallCollision(activeBalls);
ballSpawner = new BallSpawner(WIDTH / 2, HEIGHT / 2 - 20);
leftPowerUp = new PowerUp(WIDTH / 2 - 80, HEIGHT / 2 - 20);
leftPowerUp.setBallCollision(activeBalls);
}
private void tick()
{
////////////////// CALCULATE NEXT TICK ///////////////////
leftPlayer.movePaddle();
rightPlayer.movePaddle();
ballSpawner.move();
if (leftPowerUp != null) leftPowerUp.move();
if (activeBalls.isEmpty()) // (gameTime % 200 == 0)
{
for (int i = 0; i < 1; i++)
{
createBall();
}
}
for (int i = 0; i < activeBalls.size(); i++)
{
Ball ball = activeBalls.get(i);
ball.move();
if (ball.intersects(leftBound))
{
activeBalls.remove(i);
rightPlayer.addScore(1);
}
if (ball.intersects(rightBound))
{
activeBalls.remove(i);
leftPlayer.addScore(1);
}
}
if (leftPowerUp.isAquired() && leftPowerUpRespawn < tickCount)
{
leftPowerUpRespawn = tickCount + 1000;
}
else if (leftPowerUp.isAquired() && leftPowerUpRespawn == tickCount)
{
leftPowerUp = new PowerUp(WIDTH / 2 - 80, HEIGHT / 2 - 20);
leftPowerUp.setBallCollision(activeBalls);
}
//////////////////////////////////////////////////////////
tickCount ++;
}
public void render()
{
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
createBufferStrategy(2);
return;
}
Graphics2D g = (Graphics2D) bs.getDrawGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, WIDTH, HEIGHT);
//////////////////// DRAW GAME SCREEN ////////////////////
leftPowerUp.draw(g);
topBound.draw(g);
bottomBound.draw(g);
leftBound.draw(g);
rightBound.draw(g);
leftPlayer.draw(g);
rightPlayer.draw(g);
ballSpawner.draw(g);
for (int i = 0; i < activeBalls.size(); i++)
{
activeBalls.get(i).draw(g);
}
drawText(g);
//////////////////////////////////////////////////////////
Toolkit.getDefaultToolkit().sync();
g.dispose();
bs.show();
}
private void drawText(Graphics2D g)
{
g.setColor(Color.BLACK);
g.setFont(new Font("Consolas", Font.BOLD, 56));
g.drawString(Integer.toString(leftPlayer.getScore()), 40, HEIGHT - 10);
String str = Integer.toString(rightPlayer.getScore());
int adjust = str.length() * 30;
g.drawString(str, WIDTH - (40 + adjust), HEIGHT - 10);
}
public void createBall()
{
Ball ball = new Ball(ballSpawner.x, ballSpawner.y, BALL_SIZE);
ball.addCollision(topBound);
ball.addCollision(bottomBound);
//ball.addCollision(leftBound);
//ball.addCollision(rightBound);
//ball.setBallCollision(activeBalls);
activeBalls.add(ball);
}
public synchronized void start()
{
if (isRunning) {
return;
} else {
isRunning = true;
thread = new Thread(this);
thread.start();
}
}
public synchronized void stop()
{
if (!isRunning) {
return;
} else {
isRunning = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.exit(0);
}
}
public void run()
{
long last, diff, sleep;
last = System.currentTimeMillis();
while (isRunning) {
tick();
render();
diff = System.currentTimeMillis() - last;
sleep = GAME_SPEED - diff;
if (sleep < 0) sleep = 2;
try {
Thread.sleep(sleep);
}
catch (InterruptedException e) {
e.printStackTrace();
}
last = System.currentTimeMillis();
}
stop();
}
private void setLeftPlayerDirection()
{
if (QPressed && !APressed) {
leftPlayer.setDirection(Direction.UP);
} else if (!QPressed && APressed) {
leftPlayer.setDirection(Direction.DOWN);
} else {
leftPlayer.setDirection(Direction.IDLE);
}
}
private void setRightPlayerDirection()
{
if (PPressed && !LPressed) {
rightPlayer.setDirection(Direction.UP);
} else if (!PPressed && LPressed) {
rightPlayer.setDirection(Direction.DOWN);
} else {
rightPlayer.setDirection(Direction.IDLE);
}
}
public void keyPressed(KeyEvent e)
{
int keyCode = e.getKeyCode();
switch (keyCode)
{
case KeyEvent.VK_Q:
QPressed = true;
setLeftPlayerDirection();
break;
case KeyEvent.VK_A:
APressed = true;
setLeftPlayerDirection();
break;
case KeyEvent.VK_P:
PPressed = true;
setRightPlayerDirection();
break;
case KeyEvent.VK_L:
LPressed = true;
setRightPlayerDirection();
break;
}
}
public void keyReleased(KeyEvent e)
{
int keyCode = e.getKeyCode();
switch (keyCode)
{
case KeyEvent.VK_Q:
QPressed = false;
setLeftPlayerDirection();
break;
case KeyEvent.VK_A:
APressed = false;
setLeftPlayerDirection();
break;
case KeyEvent.VK_P:
PPressed = false;
setRightPlayerDirection();
break;
case KeyEvent.VK_L:
LPressed = false;
setRightPlayerDirection();
break;
}
}
public void keyTyped(KeyEvent e)
{
}
}