/**
*
*/
package de.tutorials;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import java.util.LinkedList;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import javax.swing.JFrame;
/**
* @author Tom
*
*/
public class Java2DGamingExample extends JFrame {
boolean shouldExitGame;
final Dimension currentWindowSize;
BufferStrategy bufferStrategy;
final ExecutorService executorService = Executors.newFixedThreadPool(1);
final static Random RANDOM = new Random();
boolean keyUpPressed;
boolean keyDownPressed;
boolean keyLeftPressed;
boolean keyRigthPressed;
Ball[] balls;
Player player;
AlphaComposite[] alphaComposites;
abstract class Figure {
Color color;
int x;
int y;
public Figure(int x, int y, Color color) {
this.color = color;
this.x = x;
this.y = y;
}
public void drawOn(Graphics2D g) {
Color oldColor = g.getColor();
g.setColor(color);
drawInternal(g);
g.setColor(oldColor);
}
abstract void drawInternal(Graphics2D g);
}
class Player extends Figure {
int width;
int widthHalf;
int height;
int heightHalf;
public int velocity;
public Player(int x, int y, int width, int height, int velocity,
Color color) {
super(x, y, color);
this.width = width;
this.widthHalf = width / 2;
this.height = height;
this.heightHalf = height / 2;
this.velocity = velocity;
}
@Override
void drawInternal(Graphics2D g) {
g.fillRect(x - widthHalf, y - heightHalf, width, height);
}
}
class Ball extends Figure {
LinkedList<Point> historyPoints;
int historySize;
int radius;
int radiusHalf;
int velocityY;
int velocityX;
int radiusShrinkStep;
public Ball(int x, int y, int radius, int velocityX, int velocityY,
Color color, int historySize) {
super(x, y, color);
this.radius = radius;
this.radiusHalf = radius / 2;
this.velocityX = velocityX;
this.velocityY = velocityY;
this.historyPoints = new LinkedList<Point>();
this.historySize = historySize;
this.radiusShrinkStep = (radius - (int) (.1 * radius))
/ historySize;
}
public void move() {
if ((x <= 0) || (x >= currentWindowSize.width - radiusHalf)) {
velocityX *= -1;
}
if ((y <= 0) || (y >= currentWindowSize.height - radiusHalf)) {
velocityY *= -1;
}
addToHistory(new Point(x, y));
x += velocityX;
y += velocityY;
}
private void addToHistory(Point point) {
if (historyPoints.size() >= historySize) {
historyPoints.removeLast();
}
historyPoints.addFirst(point);
}
@Override
void drawInternal(Graphics2D g) {
int currentRadius = radius;
Composite oldComposite = g.getComposite();
int currentHistoryPointIndex = 0;
for (Point historyPoint : historyPoints) {
g.setComposite(alphaComposites[currentHistoryPointIndex++]);
currentRadius -= radiusShrinkStep;
g.fillOval(historyPoint.x - radiusHalf, historyPoint.y
- radiusHalf, currentRadius, currentRadius);
}
g.setComposite(oldComposite);
g.fillOval(x - radiusHalf, y - radiusHalf, radius, radius);
}
}
Runnable gameLoop = new Runnable() {
public void run() {
while (!shouldExitGame) {
processKeys();
updateGameState();
drawScene();
}
shutdown();
}
};
public Java2DGamingExample() {
setUndecorated(true);
setIgnoreRepaint(true);
GraphicsDevice graphicsDevice = getGraphicsConfiguration().getDevice();
graphicsDevice.setFullScreenWindow(this);
graphicsDevice.setDisplayMode(new DisplayMode(640, 480, 16, 60));
setVisible(true);
currentWindowSize = getSize();
createBufferStrategy(2);
bufferStrategy = getBufferStrategy();
init();
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
keyUpPressed = true;
break;
case KeyEvent.VK_DOWN:
keyDownPressed = true;
break;
case KeyEvent.VK_LEFT:
keyLeftPressed = true;
break;
case KeyEvent.VK_RIGHT:
keyRigthPressed = true;
break;
case KeyEvent.VK_ESCAPE:
shouldExitGame = true;
break;
}
}
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
keyUpPressed = false;
break;
case KeyEvent.VK_DOWN:
keyDownPressed = false;
break;
case KeyEvent.VK_LEFT:
keyLeftPressed = false;
break;
case KeyEvent.VK_RIGHT:
keyRigthPressed = false;
break;
}
}
});
}
private void init() {
balls = createBalls(50, 30, 5);
player = new Player(100, 100, 20, 20, 5, Color.RED);
}
protected void processKeys() {
if (keyUpPressed) {
player.y -= player.velocity;
}
if (keyDownPressed) {
player.y += player.velocity;
}
if (keyRigthPressed) {
player.x += player.velocity;
}
if (keyLeftPressed) {
player.x -= player.velocity;
}
}
private Ball[] createBalls(int ballCount, int ballRadius, int historySize) {
Ball[] balls = new Ball[ballCount];
alphaComposites = new AlphaComposite[historySize];
int currentRadius = ballRadius;
int minRadius = (int) (currentRadius * .1);
int radiusShringStep = (ballRadius - minRadius) / historySize;
for (int i = 0; i < alphaComposites.length; i++) {
alphaComposites[i] = AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, 0.8F * currentRadius / ballRadius);
currentRadius -= radiusShringStep;
}
int DEFAULT_SPEED_X = 16;
int DEFAULT_SPEED_Y = 16;
for (int j = 0; j < balls.length; j++) {
Color ballColor = null;
switch (RANDOM.nextInt(5)) {
case 0:
ballColor = Color.RED;
break;
case 1:
ballColor = Color.BLUE;
break;
case 2:
ballColor = Color.GREEN;
break;
case 3:
ballColor = Color.YELLOW;
break;
case 4:
ballColor = Color.MAGENTA;
break;
}
balls[j] = new Ball(20 + RANDOM.nextInt(400), 20 + RANDOM
.nextInt(300), ballRadius,
RANDOM.nextBoolean() ? -RANDOM.nextInt(DEFAULT_SPEED_X)
: RANDOM.nextInt(DEFAULT_SPEED_X), RANDOM
.nextBoolean() ? -RANDOM.nextInt(DEFAULT_SPEED_Y)
: RANDOM.nextInt(DEFAULT_SPEED_Y), ballColor,
historySize);
}
return balls;
}
private void drawScene() {
Graphics2D g = (Graphics2D) bufferStrategy.getDrawGraphics();
drawBackground(g);
drawBalls(g);
drawPlayer(g);
g.dispose();
bufferStrategy.show();
}
private void drawPlayer(Graphics2D g) {
player.drawOn(g);
}
private void drawBalls(Graphics2D g) {
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// g.setRenderingHint(RenderingHints.KEY_RENDERING,
// RenderingHints.VALUE_COLOR_RENDER_SPEED);
// g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
// RenderingHints.VALUE_COLOR_RENDER_SPEED);
for (int i = 0; i < balls.length; i++) {
Ball ball = balls[i];
ball.drawOn(g);
}
}
private void drawBackground(Graphics2D g) {
g.fillRect(0, 0, currentWindowSize.width, currentWindowSize.height);
}
private void updateGameState() {
for (int i = 0; i < balls.length; i++) {
Ball ball = balls[i];
checkForCollision(ball);
ball.move();
}
}
private void checkForCollision(Ball ballToCheck) {
for (int i = 0; i < balls.length; i++) {
Ball ball = balls[i];
if (ball == ballToCheck) {
continue;
} else {
if ((abs(ball.x - ballToCheck.x) <= ballToCheck.radiusHalf)
&& (abs(ball.y - ballToCheck.y) <= ballToCheck.radiusHalf)) {
ball.velocityX *= -1;
ballToCheck.velocityX *= -1;
ball.velocityY *= -1;
ballToCheck.velocityY *= -1;
}
}
}
}
public static int abs(int a) {
return (a ^ (a >> 31)) - (a >> 31);
}
private void shutdown() {
executorService.shutdown();
System.exit(0);
}
public static void main(String[] args) {
new Java2DGamingExample().start();
}
private void start() {
executorService.execute(gameLoop);
}
}