Java Animation Memory Overload [on hold]
- by user2425429
I need a way to reduce the memory usage of these programs while keeping the functionality. Every time I add 50 milliseconds or so to the set&display loop in AnimationTest1, it throws an out of memory error. Here is the code I have now:
import java.awt.DisplayMode;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Polygon;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import javax.swing.ImageIcon;
public class AnimationTest1 {
public static void main(String args[]) {
AnimationTest1 test = new AnimationTest1();
test.run();
}
private static final DisplayMode POSSIBLE_MODES[] = {
new DisplayMode(800, 600, 32, 0),
new DisplayMode(800, 600, 24, 0),
new DisplayMode(800, 600, 16, 0),
new DisplayMode(640, 480, 32, 0),
new DisplayMode(640, 480, 24, 0),
new DisplayMode(640, 480, 16, 0)
};
private static final long DEMO_TIME = 4000;
private ScreenManager screen;
private Image bgImage;
private Animation anim;
public void loadImages() {
// create animation
List<Polygon> polygons=new ArrayList();
int[] x=new int[]{20,4,4,20,40,56,56,40};
int[] y=new int[]{20,32,40,44,44,40,32,20};
polygons.add(new Polygon(x,y,8));
anim = new Animation();
//# of frames
long startTime = System.currentTimeMillis();
long currTimer = startTime;
long elapsedTime = 0;
boolean animated = false;
Graphics2D g = screen.getGraphics();
int width=200;
int height=200;
//set&display loop
while (currTimer - startTime < DEMO_TIME*2) {
//draw the polygons
if(!animated){
for(int j=0; j<polygons.size();j++){
for(int pos=0; pos<polygons.get(j).npoints; pos++){
polygons.get(j).xpoints[pos]+=1;
}
}
anim.setNewPolyFrame(polygons , width , height , 64);
}
else{
// update animation
anim.update(elapsedTime);
draw(g);
g.dispose();
screen.update();
try{
Thread.sleep(20);
}
catch(InterruptedException ie){}
}
if(currTimer - startTime == DEMO_TIME)
animated=true;
elapsedTime = System.currentTimeMillis() - currTimer;
currTimer += elapsedTime;
}
}
public void run() {
screen = new ScreenManager();
try {
DisplayMode displayMode =
screen.findFirstCompatibleMode(POSSIBLE_MODES);
screen.setFullScreen(displayMode);
loadImages();
}
finally {
screen.restoreScreen();
}
}
public void draw(Graphics g) {
// draw background
g.drawImage(bgImage, 0, 0, null);
// draw image
g.drawImage(anim.getImage(), 0, 0, null);
}
}
ScreenManager:
import java.awt.Color;
import java.awt.DisplayMode;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ScreenManager extends JPanel {
private GraphicsDevice device;
/**
Creates a new ScreenManager object.
*/
public ScreenManager() {
GraphicsEnvironment environment=GraphicsEnvironment.getLocalGraphicsEnvironment();
device = environment.getDefaultScreenDevice();
setBackground(Color.white);
}
/**
Returns a list of compatible display modes for the
default device on the system.
*/
public DisplayMode[] getCompatibleDisplayModes() {
return device.getDisplayModes();
}
/**
Returns the first compatible mode in a list of modes.
Returns null if no modes are compatible.
*/
public DisplayMode findFirstCompatibleMode(
DisplayMode modes[])
{
DisplayMode goodModes[] = device.getDisplayModes();
for (int i = 0; i < modes.length; i++) {
for (int j = 0; j < goodModes.length; j++) {
if (displayModesMatch(modes[i], goodModes[j])) {
return modes[i];
}
}
}
return null;
}
/**
Returns the current display mode.
*/
public DisplayMode getCurrentDisplayMode() {
return device.getDisplayMode();
}
/**
Determines if two display modes "match". Two display
modes match if they have the same resolution, bit depth,
and refresh rate. The bit depth is ignored if one of the
modes has a bit depth of DisplayMode.BIT_DEPTH_MULTI.
Likewise, the refresh rate is ignored if one of the
modes has a refresh rate of
DisplayMode.REFRESH_RATE_UNKNOWN.
*/
public boolean displayModesMatch(DisplayMode mode1,
DisplayMode mode2)
{
if (mode1.getWidth() != mode2.getWidth() ||
mode1.getHeight() != mode2.getHeight())
{
return false;
}
if (mode1.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI &&
mode2.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI &&
mode1.getBitDepth() != mode2.getBitDepth())
{
return false;
}
if (mode1.getRefreshRate() !=
DisplayMode.REFRESH_RATE_UNKNOWN &&
mode2.getRefreshRate() !=
DisplayMode.REFRESH_RATE_UNKNOWN &&
mode1.getRefreshRate() != mode2.getRefreshRate())
{
return false;
}
return true;
}
/**
Enters full screen mode and changes the display mode.
If the specified display mode is null or not compatible
with this device, or if the display mode cannot be
changed on this system, the current display mode is used.
<p>
The display uses a BufferStrategy with 2 buffers.
*/
public void setFullScreen(DisplayMode displayMode) {
JFrame frame = new JFrame();
frame.setUndecorated(true);
frame.setIgnoreRepaint(true);
frame.setResizable(true);
device.setFullScreenWindow(frame);
if (displayMode != null &&
device.isDisplayChangeSupported())
{
try {
device.setDisplayMode(displayMode);
}
catch (IllegalArgumentException ex) { }
}
frame.createBufferStrategy(2);
Graphics g=frame.getGraphics();
g.setColor(Color.white);
g.drawRect(0, 0, frame.WIDTH, frame.HEIGHT);
frame.paintAll(g);
g.setColor(Color.black);
g.dispose();
}
/**
Gets the graphics context for the display. The
ScreenManager uses double buffering, so applications must
call update() to show any graphics drawn.
<p>
The application must dispose of the graphics object.
*/
public Graphics2D getGraphics() {
Window window = device.getFullScreenWindow();
if (window != null) {
BufferStrategy strategy = window.getBufferStrategy();
return (Graphics2D)strategy.getDrawGraphics();
}
else {
return null;
}
}
/**
Updates the display.
*/
public void update() {
Window window = device.getFullScreenWindow();
if (window != null) {
BufferStrategy strategy = window.getBufferStrategy();
if (!strategy.contentsLost()) {
strategy.show();
}
}
// Sync the display on some systems.
// (on Linux, this fixes event queue problems)
Toolkit.getDefaultToolkit().sync();
}
/**
Returns the window currently used in full screen mode.
Returns null if the device is not in full screen mode.
*/
public Window getFullScreenWindow() {
return device.getFullScreenWindow();
}
/**
Returns the width of the window currently used in full
screen mode. Returns 0 if the device is not in full
screen mode.
*/
public int getWidth() {
Window window = device.getFullScreenWindow();
if (window != null) {
return window.getWidth();
}
else {
return 0;
}
}
/**
Returns the height of the window currently used in full
screen mode. Returns 0 if the device is not in full
screen mode.
*/
public int getHeight() {
Window window = device.getFullScreenWindow();
if (window != null) {
return window.getHeight();
}
else {
return 0;
}
}
/**
Restores the screen's display mode.
*/
public void restoreScreen() {
Window window = device.getFullScreenWindow();
if (window != null) {
window.dispose();
}
device.setFullScreenWindow(null);
}
/**
Creates an image compatible with the current display.
*/
public BufferedImage createCompatibleImage(int w, int h,
int transparency)
{
Window window = device.getFullScreenWindow();
if (window != null) {
GraphicsConfiguration gc =
window.getGraphicsConfiguration();
return gc.createCompatibleImage(w, h, transparency);
}
return null;
}
}
Animation:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Polygon;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
/**
The Animation class manages a series of images (frames) and
the amount of time to display each frame.
*/
public class Animation {
private ArrayList frames;
private int currFrameIndex;
private long animTime;
private long totalDuration;
/**
Creates a new, empty Animation.
*/
public Animation() {
frames = new ArrayList();
totalDuration = 0;
start();
}
/**
Adds an image to the animation with the specified
duration (time to display the image).
*/
public synchronized void addFrame(BufferedImage image, long duration){
ScreenManager s = new ScreenManager();
totalDuration += duration;
frames.add(new AnimFrame(image, totalDuration));
}
/**
Starts the animation over from the beginning.
*/
public synchronized void start() {
animTime = 0;
currFrameIndex = 0;
}
/**
Updates the animation's current image (frame), if
necessary.
*/
public synchronized void update(long elapsedTime) {
if (frames.size() >= 1) {
animTime += elapsedTime;
/*if (animTime >= totalDuration) {
animTime = animTime % totalDuration;
currFrameIndex = 0;
}*/
while (animTime > getFrame(0).endTime) {
frames.remove(0);
}
}
}
/**
Gets the Animation's current image. Returns null if this
animation has no images.
*/
public synchronized Image getImage() {
if (frames.size() > 0&&!(currFrameIndex>=frames.size())) {
return getFrame(currFrameIndex).image;
}
else{
System.out.println("There are no frames!");
System.exit(0);
}
return null;
}
private AnimFrame getFrame(int i) {
return (AnimFrame)frames.get(i);
}
private class AnimFrame {
Image image;
long endTime;
public AnimFrame(Image image, long endTime) {
this.image = image;
this.endTime = endTime;
}
}
public void setNewPolyFrame(List<Polygon> polys,int imagewidth,int imageheight,int
time){
BufferedImage image=new BufferedImage(imagewidth, imageheight, 1);
Graphics g=image.getGraphics();
for(int i=0;i<polys.size();i++){
g.drawPolygon(polys.get(i));
}
addFrame(image,time);
g.dispose();
}
}