import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferStrategy;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JScrollBar;
/**
* This is simple example of Active Rendering strategy with interoperation between Swing
* <code>JScrollBar</code> component and rendering thread.
* @author Mersenne
*
*/
public class ActiveRenderingDemo {
// Based on code from http://www.gamedev.net/page/resources/_/technical/general-programming/java-games-active-rendering-r2418
public static final int WORLD_WIDTH = 1600;
public static final int WORLD_HEIGHT = 480;
// These fields will be read from rendering thread, but updated from Event Dispatch Thread
private static volatile int viewportWidth;
private static volatile int viewportHeight;
private static volatile int scrollPosition;
private static int[][] spritesData;
public static void main(String[] args) {
viewportWidth = 640;
viewportHeight = WORLD_HEIGHT;
// Create frame with components
JFrame app = new JFrame();
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setLayout(new BorderLayout());
Canvas canvas = new Canvas();
canvas.setIgnoreRepaint(true);
canvas.setSize(viewportWidth, viewportHeight);
app.add(canvas, BorderLayout.CENTER);
final JScrollBar scrollBar = new JScrollBar(JScrollBar.HORIZONTAL);
scrollBar.setMaximum(WORLD_WIDTH - viewportWidth);
app.add(scrollBar, BorderLayout.SOUTH);
app.pack();
app.setVisible(true);
// Listen for important events and adjust rendering parameters
canvas.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
viewportWidth = ((Canvas) e.getSource()).getWidth();
viewportHeight = ((Canvas) e.getSource()).getHeight();
scrollBar.setMaximum(WORLD_WIDTH - viewportWidth);
}
});
scrollBar.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
scrollPosition = e.getValue();
}
});
// Create "sprites"
initSprites();
// Create buffer strategy and acquire buffer for rendering operations
canvas.createBufferStrategy(2);
BufferStrategy buffer = canvas.getBufferStrategy();
try {
while (true) {
// Create graphics on every rendering cycle
Graphics2D g2d = (Graphics2D) buffer.getDrawGraphics();
try {
// I like smooth shapes
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Paint background
g2d.setColor(Color.YELLOW);
g2d.fillRect(0, 0, viewportWidth, viewportHeight);
// Draw something
renderSprites(g2d);
// Always check this before show()
if (!buffer.contentsLost())
buffer.show();
// "Game mechanics"
moveSprites();
// Limit framerate to 50 fps
Thread.sleep(1000 / 50);
} finally {
g2d.dispose();
}
}
} catch (InterruptedException ie) { }
}
private static void initSprites() {
Random rand = new Random();
spritesData = new int[20][4];
for (int[] spriteData : spritesData) {
spriteData[0] = rand.nextInt(WORLD_WIDTH); // X
spriteData[1] = rand.nextInt(WORLD_HEIGHT); // Y
spriteData[2] = rand.nextInt(3) - 1; // X movement delta
spriteData[3] = rand.nextInt(3) - 1; // Y movement delta
}
}
private static void renderSprites(Graphics2D g2d) {
final int spriteSize = 20;
for (int[] spriteData : spritesData) {
int spriteX = spriteData[0];
int spriteY = spriteData[1];
// Some simple calculations to make sprite more dynamic
int colorMod = Math.abs(255 - spriteX * 2 % 512);
int sizeModX = Math.abs(5 - spriteX % 10);
int sizeModY = Math.abs(5 - spriteY % 10);
int curSpriteSizeX = spriteSize + sizeModX;
int curSpriteSizeY = spriteSize + sizeModY;
// Fill body
g2d.setColor(new Color(colorMod, colorMod, 0));
g2d.fillOval(
spriteX - curSpriteSizeX/2 - scrollPosition,
spriteY - curSpriteSizeY/2,
curSpriteSizeX,
curSpriteSizeY);
// Draw border
g2d.setColor(Color.BLACK);
g2d.drawOval(
spriteX - curSpriteSizeX/2 - scrollPosition,
spriteY - curSpriteSizeY/2,
curSpriteSizeX,
curSpriteSizeY);
}
}
private static void moveSprites() {
for (int[] spriteData : spritesData) {
int spriteX = spriteData[0];
int spriteY = spriteData[1];
int spriteXmod = spriteData[2];
int spriteYmod = spriteData[3];
int newSpriteX = spriteX + spriteXmod;
int newSpriteY = spriteY + spriteYmod;
if (newSpriteX > WORLD_WIDTH) {
newSpriteX = WORLD_WIDTH;
spriteXmod = -spriteXmod;
} else if (newSpriteX < 0) {
newSpriteX = 0;
spriteXmod = -spriteXmod;
}
if (newSpriteY > WORLD_HEIGHT) {
newSpriteY = WORLD_HEIGHT;
spriteYmod = -spriteYmod;
} else if (newSpriteY < 0) {
newSpriteY = 0;
spriteYmod = -spriteYmod;
}
spriteData[0] = newSpriteX;
spriteData[1] = newSpriteY;
spriteData[2] = spriteXmod;
spriteData[3] = spriteYmod;
}
}
}