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 * JScrollBar 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; } } }