I've been looking through/for guides all night trying to find how to smooth out my multiple image animation. I tried a few guides, found one i liked but it's quite choppy.
atm my animation works but flashes.
my animation clas:
package graphics;
import java.awt.Image;
import java.util.ArrayList;
public class Animation {
private ArrayList<OneScene> scenes;
private int sceneIndex;
private long movieTime;
private long totalTime;
//Constructor
public Animation() {
scenes = new ArrayList<OneScene>();
totalTime = 0;
start();
}
//Add scene to ArayList & set time for each scene
public synchronized void addScene(Image i, long t) {
totalTime += t;
scenes.add(new OneScene(i, totalTime));
}
//Start animation
public synchronized void start() {
movieTime = 0;
sceneIndex = 0;
}
//Change Scenes
public synchronized void update(long timePassed) {
if (scenes.size() > 1) {
movieTime += timePassed;
if (movieTime >= totalTime) {
movieTime = 0;
sceneIndex = 0;
}
while(movieTime > getScene(sceneIndex).endTime) {
sceneIndex++;
}
}
}
//Get animation (Image) current scene
public synchronized Image getImage() {
if (scenes.size() ==0) {
return null;
}else{
return getScene(sceneIndex).pic;
}
}
//Get Scene
private OneScene getScene(int x) {
return (OneScene)scenes.get(x);
}
//Private Class
public class OneScene {
Image pic;
long endTime;
public OneScene(Image pic, long endTime) {
this.pic = pic;
this.endTime = endTime;
}
}
& a few of my methods:
Image load1 = new ImageIcon(""+cachemainDir+"1.png").getImage();
Image load2 = new ImageIcon(""+cachemainDir+"2.png").getImage();
Image load3 = new ImageIcon(""+cachemainDir+"3.png").getImage();
Image load4 = new ImageIcon(""+cachemainDir+"4.png").getImage();
Image load5 = new ImageIcon(""+cachemainDir+"5.png").getImage();
Image load6 = new ImageIcon(""+cachemainDir+"6.png").getImage();
Image load7 = new ImageIcon(""+cachemainDir+"7.png").getImage();
Image load8 = new ImageIcon(""+cachemainDir+"8.png").getImage();
Image load9 = new ImageIcon(""+cachemainDir+"9").getImage();
Image load10 = new ImageIcon(""+cachemainDir+"10.png").getImage();
Image load11 = new ImageIcon(""+cachemainDir+"11.png").getImage();
Image load12 = new ImageIcon(""+cachemainDir+"12.png").getImage();
Anim = new Animation();
Anim.addScene(load1, 100);
Anim.addScene(load2, 100);
Anim.addScene(load3, 100);
Anim.addScene(load4, 100);
Anim.addScene(load5, 100);
Anim.addScene(load6, 100);
Anim.addScene(load7, 100);
Anim.addScene(load8, 100);
Anim.addScene(load9, 100);
Anim.addScene(load10, 100);
Anim.addScene(load11, 100);
Anim.addScene(load12, 100);
and...
while (AppLoading) {
long timePassed = System.currentTimeMillis() - cumTime;
cumTime += timePassed;
Anim.update(timePassed);
Graphics g = getGraphics();
draw(g);
g.dispose();
try{
Thread.sleep(0);
}catch(Exception ex){}
}
lastly....
public void draw(Graphics g) {
new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
g.drawImage(bg, 0, 0, getWidth(), getHeight(), null);
g.drawImage(Anim.getImage(), 300, 300, null);
}
What do you mean by flashing? Is there a blank frame between the actual frames? (You can test this by just making a few stills and animating them.)It could be that you are updating to little frames, as you only have 12. This is fine if the images are animated correctly out side of run time. Make the 'cachemainDir' images closer in animation. It may help if you Thread.sleep(5); //or a number besides 0
Related
I have multiple games running on 60 frame per second rate. I need to capture each frame and clone into four different screen with specific filter.
Software will work on dual screen monitor where primary and secondary screen will be responsible for running game and displaying four filter view respectively.
Limitation on applying filter:
Filter will work on image only.
Filter is written in java which almost impossible to rewrite.
So I am applying logic something like below:
import java.awt.*;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import com.sun.jna.platform.win32.GDI32Util;
import com.sun.jna.platform.win32.WinDef.HWND;
import java.awt.image.BufferedImage;
public class MultiFrameApplet implements Runnable
{
public JFrame currentFrame = null;
public PanelPaint currentCanvas = null;
public BufferedImage screenshotImage = null;
com.sun.jna.platform.win32.User32 user32 = null;
HWND hwnd = null;
Thread th = null;
String CurrentFrameText = "";
private long lastTime;
private double fps; //could be int or long for integer values
public MultiFrameApplet(int filtertype)
{
main(null,filtertype);
}
public void main(String[] argv,int filtertype)
{
try
{
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gd = ge.getScreenDevices();
//First Screen
GraphicsConfiguration gcFirst = gd[0].getDefaultConfiguration();
Toolkit toolkit = Toolkit.getDefaultToolkit();
if (toolkit == null)
{
return;
}
Rectangle screenRectFirst = gcFirst.getBounds();
Insets screenInsetsFirst = toolkit.getScreenInsets(gcFirst);
screenRectFirst.x = screenInsetsFirst.left;
screenRectFirst.y = screenInsetsFirst.top;
Robot robot = new Robot(gcFirst.getDevice());
//Second Screen
GraphicsConfiguration gcSecond = gd[1].getDefaultConfiguration();
Rectangle screenRectSecond = gcSecond.getBounds();
Insets screenInsetsSecond = Toolkit.getDefaultToolkit().getScreenInsets(gcSecond);
Rectangle effectiveScreenArea = new Rectangle();
/*Remove start bar area*/
effectiveScreenArea.x = screenRectSecond.x + screenInsetsSecond.left;
effectiveScreenArea.y = screenRectSecond.y + screenInsetsSecond.top;
effectiveScreenArea.height = screenRectSecond.height - screenInsetsSecond.top - screenInsetsSecond.bottom;
effectiveScreenArea.width = screenRectSecond.width - screenInsetsSecond.left - screenInsetsSecond.right;
//Scaling will decide capture image needs to shrink or not.!
double xscaling = 0;
double yscaling = 0;
screenshotImage = robot.createScreenCapture(screenRectFirst);
int differenceWidth = screenRectSecond.width / screenRectFirst.width;
int differenceheight = screenRectSecond.height / screenRectFirst.height;
xscaling = differenceWidth / 2.0;
yscaling = differenceheight / 2.0;
yscaling = yscaling - 0.018;
currentFrame = new JFrame();
currentFrame.setSize((int)effectiveScreenArea.width/2, (int)effectiveScreenArea.height/2);
if(filtertype == 0)
{
currentFrame.setLocation(effectiveScreenArea.x, effectiveScreenArea.y);
currentFrame.setTitle("First");
CurrentFrameText = "First";
}
else if(filtertype == 1)
{
currentFrame.setLocation(effectiveScreenArea.x + ((int)effectiveScreenArea.width/2), effectiveScreenArea.y);
currentFrame.setTitle("Second");
CurrentFrameText = "Second";
}
else if(filtertype == 2)
{
currentFrame.setLocation(effectiveScreenArea.x + ((int)effectiveScreenArea.width/2), effectiveScreenArea.y);
currentFrame.setTitle("Third");
CurrentFrameText = "Third";
}
else if(filtertype == 3)
{
currentFrame.setLocation(effectiveScreenArea.x + ((int)effectiveScreenArea.width/2),effectiveScreenArea.y + ((int)effectiveScreenArea.height/2));
currentFrame.setTitle("Forth");
CurrentFrameText = "Forth";
}
currentCanvas = new PanelPaint((int)effectiveScreenArea.width/2,(int)effectiveScreenArea.height/2,xscaling,yscaling,CurrentFrameText);
currentCanvas.xpos = (int)effectiveScreenArea.width/2;
currentCanvas.ypos = (int)effectiveScreenArea.height/2;
currentFrame.getContentPane().add(currentCanvas);
currentFrame.setUndecorated(true);
currentFrame.setVisible(true);
user32 = com.sun.jna.platform.win32.User32.INSTANCE;
hwnd = user32.GetDesktopWindow();
th = new Thread(this);
th.start();
}
catch (AWTException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void close()
{
currentFrame.dispose();
currentFrame = null;
currentCanvas.close();
currentCanvas = null;
screenshotImage = null;
user32 = null;
hwnd = null;
th = null;
}
#Override
public void run()
{
while(true)
{
lastTime = System.nanoTime();
screenshotImage = GDI32Util.getScreenshot(hwnd);
///screenshotImage = screenshotImage.Convert(); //Place where filter applied
currentCanvas.setImg(screenshotImage,fps);
java.awt.EventQueue.invokeLater(currentCanvas::repaint);
fps = 1000000000.0 / (System.nanoTime() - lastTime); //one second(nano) divided by amount of time it takes for one frame to finish
lastTime = System.nanoTime();
}
}
}
#SuppressWarnings("serial")
class PanelPaint extends javax.swing.JPanel
{
public int xpos = 0;
public int ypos = 0;
BufferedImage img = null;
java.awt.Graphics2D gc = null;
Font currentFont = null;
double fps = 0;
String CurrentFrameText;
PanelPaint(int xpos,int ypos,double sx,double sy,String argCurrentFrameText)
{
img = new BufferedImage(xpos, ypos, BufferedImage.TYPE_INT_ARGB);
gc = img.createGraphics();
gc.scale(sx, sy);
currentFont = new Font("default", Font.BOLD, 30);
CurrentFrameText = argCurrentFrameText;
gc.setFont(currentFont);
gc.setColor(Color.RED);
}
#Override
public Dimension getPreferredSize()
{
return new Dimension(xpos, ypos);
}
public void setImg(BufferedImage img,double argfps)
{
gc.drawImage(img, 0, 0, null);
gc.drawString(CurrentFrameText + ": " + (int)fps, 25, 25);
fps = argfps;
}
#Override
public void paint(java.awt.Graphics g)
{
g.drawImage(img, 0, 0, null);
}
public void close()
{
img = null;
gc = null;
currentFont = null;
}
}
Above is slower for high contrast images and taking time for "g.drawImage(img, 0, 0, null);" code.
Can performance for draw image can be improve?
You can use an OpenGL fragment shader to filter and then blit the source image as a texture to the 4 screens as screen quads (orthonormal projections onto a quad poly).
This is by far the optimal solution to your requirement. If your game is OpenGL based, it will be even faster since you wont have to use the Robot package as an intermediate - you can simply render the game texture directly (image conversion not required).
This will also allow full control over the filter in the fragment shader. See ShaderToy.com for many excellent filter shaders.
im following a tutorial and im coming across this is the error, i cannot seem to work out what the problem is. All im trying to do is load a Sprite image. Here is the code:
Here is the error:
Exception in thread "Thread-0" java.lang.NullPointerException
at com.mainpkg.game.Handler.gg(Handler.java:27)
at com.mainpkg.game.Game.render(Game.java:107)
at com.mainpkg.game.Game.run(Game.java:83)
at java.base/java.lang.Thread.run(Thread.java:844)
Main Game Class:
public class Game extends Canvas implements Runnable {
public static final int WIDTH = 800, HEIGHT = WIDTH / 12 * 9;
private Thread thread;
private boolean running = false;
private Handler handler;
private BufferedImage grassTile;
public Game() {
new Window(WIDTH, HEIGHT, "MOON EXPOLATION", this);
handler = new Handler(getWidth(), getHeight());
testImage = loadImage("Resources/GrassTile.png");
}
private BufferedImage loadImage(String path) {
try {
BufferedImage loadedImage = ImageIO.read(new FileInputStream(path));
BufferedImage formattedImage = new BufferedImage(loadedImage.getWidth(), loadedImage.getHeight(),
BufferedImage.TYPE_INT_RGB);
formattedImage.getGraphics().drawImage(loadedImage, 0, 0, null);
return formattedImage;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public synchronized void start() {
thread = new Thread(this);
thread.start();
running = true;
}
public synchronized void stop() {
try {
thread.join();
running = false;
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
int FRAMES = 0;
int TICKS = 0;
long lastTime = System.nanoTime();
double unprocessed = 0;
double nsPerSecs = 1000000000 / 60.0;
long Timer = System.currentTimeMillis();
while (running) {
long now = System.nanoTime();
unprocessed += (now - lastTime) / nsPerSecs;
lastTime = now;
if (unprocessed >= 1) {
TICKS++;
ticks();
unprocessed -= 1;
}
try {
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
FRAMES++;
render();
if (System.currentTimeMillis() - Timer > 1000) {
System.out.println("Ticks: " + TICKS + " FPS: " + FRAMES);
TICKS = 0;
FRAMES = 0;
Timer += 1000;
}
}
stop();
}
private void ticks() {
}
void render() {
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
super.paint(getGraphics());
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
handler.renderImage(testImage, 0, 0);
handler.render(g);
// g.setColor(Color.BLACK);
// g.fillRect(0,0,WIDTH,HEIGHT);
g.dispose();
bs.show();
}
public static void main(String[] args) {
new Game();
}
Handler Class:
public class Handler {
private BufferedImage view;
private int pixels[];
public Handler(int width, int height) {
view = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
pixels = ((DataBufferInt) view.getRaster().getDataBuffer()).getData();
}
public void render(Graphics g) {
g.drawImage(view, 0, 0, view.getWidth(), view.getHeight(), null);
}
public void renderImage(BufferedImage image, int xPosition,int yPosition) {
int[] imagepixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
for(int y = 0; y < image.getHeight(); y++) {
for(int x = 0; x < image.getWidth(); x++) {
pixels[(x + xPosition) + (y + yPosition ) * view.getWidth()] = imagepixels[x + y * image.getWidth()];
}
}
}
The problem is here:
BufferedImage loadedImage = ImageIO.read(Game.class.getResource(path));
getResource(path) is returning null and that is causing the exception.
Try changing the image path to "Assets/GrassTile.png"
One tip:
You should avoid using absolute paths to locate your resources. This is a really bad idea because if you change the location of your project it will stop working, try using relative paths.
Im having a problem where my sprite isnt showing the background image but its showing the background Color from the frame.
Here is my code:
MAIN(edited so i only show the part where i load the sprite)
private JFrame principal;
private JButton bt_inicio_iniciar;
private JButton bt_menu_1;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable(){
public void run()
{
try
{
// UIManager.setLookAndFeel(new SyntheticaBlackEyeLookAndFeel());
new Thread (new ClientMain()).start();
}
catch( Exception e )
{
e.printStackTrace();
}
}
});
}
public ClientMain() throws IOException {
img = ImageIO.read(new File("Resources\\images\\background\\background.png"));
loadGUI();
}
private void loadGUI()
{
int principal_width = 1200;
int principal_heigth = 500;
principal = new JFrame();
// principal.setBackground(new Color(0,0,0,0));
JLabel contentPane = new JLabel();
contentPane.setIcon( new ImageIcon("Resources\\images\\background\\background.png") );
contentPane.setLayout( new BorderLayout() );
principal.pack();
principal.setContentPane( contentPane );
principal.setResizable(false);
principal.setLocationRelativeTo(null);
principal.setTitle("Cliente ");
principal.setSize(principal_width, principal_heigth);
//principal.setContentPane(new JLabel(new ImageIcon("Resources\\images\\background\\background.png")));
principal.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
principal.getContentPane().setLayout(null);
//inicio
bt_inicio_iniciar = new JButton();
bt_inicio_iniciar.setBounds(500,200,200,50);
bt_inicio_iniciar.setText("Iniciar");
bt_inicio_iniciar.setEnabled(false);
tx_inicio_estado = new JLabel();
tx_inicio_estado.setText("Esperando al servidor");
tx_inicio_estado.setForeground(Color.WHITE);
tx_inicio_estado.setSize(200,20);
tx_inicio_estado.setLocation(500,175);
//menu
bt_menu_1 = new JButton();
bt_menu_1.setBounds(10,350,150,50);
bt_menu_1.setText("Attack");
bt_menu_1.setBackground(Color.LIGHT_GRAY);
bt_menu_1.setEnabled(true);
bt_menu_2 = new JButton();
bt_menu_2.setBounds(170,350,150,50);
bt_menu_2.setText("Spells");
bt_menu_2.setBackground(Color.LIGHT_GRAY);
bt_menu_2.setEnabled(true);
bt_menu_3 = new JButton();
bt_menu_3.setBounds(10,410,150,50);
bt_menu_3.setText("Items");
bt_menu_3.setBackground(Color.LIGHT_GRAY);
bt_menu_3.setEnabled(true);
bt_menu_4 = new JButton();
bt_menu_4.setBounds(170,410,150,50);
bt_menu_4.setText("Defend");
bt_menu_4.setBackground(Color.LIGHT_GRAY);
bt_menu_4.setEnabled(true);
//battleLog
tx_log = new JLabel();
tx_log.setText("Battle Log");
tx_log.setBounds(330,350,150,15);
log = new TextArea();
log.setBounds(330,370,400,89);
log.setBackground(Color.lightGray);
log.setForeground(Color.white);
//Hp
tx_hp_player1 = new JLabel();
tx_hp_player1.setBounds(740,350,150,15);
tx_hp_player1.setText("Player1");
pb_hp_player1 = new JProgressBar();
pb_hp_player1.setBounds(740,365,445,15);
pb_hp_player1.setMaximum(100);
pb_hp_player1.setMinimum(0);
pb_hp_player1.setValue(100);
pb_hp_player1.setIndeterminate(false);
pb_hp_player1.setStringPainted(true);
pb_hp_player1.setForeground(Color.red);
pb_hp_player1.setString(pb_hp_player1.getValue()+"/"+pb_hp_player1.getMaximum());
tx_hp_player2 = new JLabel();
tx_hp_player2.setBounds(740,385,150,15);
tx_hp_player2.setText("Player2");
pb_hp_player2 = new JProgressBar();
pb_hp_player2.setBounds(740,400,445,15);
pb_hp_player2.setMaximum(100);
pb_hp_player2.setMinimum(0);
pb_hp_player2.setValue(100);
pb_hp_player2.setIndeterminate(false);
pb_hp_player2.setStringPainted(true);
pb_hp_player2.setForeground(Color.red);
pb_hp_player2.setString(pb_hp_player2.getValue()+"/"+pb_hp_player2.getMaximum());
tx_hp_boss = new JLabel();
tx_hp_boss.setBounds(740,420,150,15);
tx_hp_boss.setText("Boss");
pb_hp_boss = new JProgressBar();
pb_hp_boss.setBounds(740,435,445,15);
pb_hp_boss.setMaximum(200);
pb_hp_boss.setMinimum(0);
pb_hp_boss.setValue(200);
pb_hp_boss.setIndeterminate(false);
pb_hp_boss.setStringPainted(true);
pb_hp_boss.setForeground(Color.red);
pb_hp_boss.setString(pb_hp_boss.getValue()+"/"+pb_hp_boss.getMaximum());
p = new Player();
//p.setBounds(100,100,30,35);
//p.setOpaque(true);
principal.add(bt_inicio_iniciar);
principal.add(bt_menu_1);
principal.add(bt_menu_2);
principal.add(bt_menu_3);
principal.add(bt_menu_4);
principal.add(tx_log);
principal.add(log);
principal.add(tx_hp_player1);
principal.add(pb_hp_player1);
principal.add(tx_hp_player2);
principal.add(pb_hp_player2);
principal.add(tx_hp_boss);
principal.add(pb_hp_boss);
principal.add(tx_inicio_estado);
principal.add(p);
principal.setVisible(true);
}
}
Player
public class Player extends JPanel {
// Screen Dimensions
int
GWIDTH = 30,
GHEIGHT = 30;
Dimension screenSize = new Dimension(GWIDTH, GHEIGHT);
// Double Buffer Varabiles
Image dbImage;
Graphics dbg;
// buffered spritesheet
Image firstBall;
SpriteLoader ball = new SpriteLoader("Resources\\images\\sprites\\sprite1.png");
// Animator
Animation ballAnimation;
ArrayList animationArray;
public Player() {
this.setSize(screenSize);
init();
}
private void init(){
animationArray = new ArrayList<BufferedImage>();
animationArray.add(0,ball.getImage(0,64,32,32));
animationArray.add(1,ball.getImage(32,64,32,32));
animationArray.add(2,ball.getImage(64,64,32,32));
ballAnimation = new Animation(animationArray);
ballAnimation.setSpeed(100);
ballAnimation.start();
}
#Override
public void paint(Graphics g){
super.paint(g);
dbImage = createImage(getWidth(),getHeight());
dbg = dbImage.getGraphics();
draw(dbg);
g.drawImage(dbImage, 0, 0, this);
g.dispose();
}
public void draw(Graphics g){
if(ballAnimation != null){
g.drawImage(ballAnimation.sprites, 0, 0, this);
ballAnimation.update(System.currentTimeMillis());
repaint();
}
g.dispose();
}
public static void main(String[] args) {
Player m = new Player();
}
}
Animation
public class Animation {
// initalize values
private ArrayList<BufferedImage> frames;
public BufferedImage sprites;
// Animation Varabales
private volatile boolean running = false;
private long previousTime, speed;
private int frameAtPause, currentFrame;
public Animation(ArrayList<BufferedImage> frames){
this.frames = frames;
}
public void setSpeed(long speed){
this.speed = speed;
}
public void update(long time){
if(running){
if(time - previousTime >= speed){
//Update the animation
currentFrame++;
try{
sprites = frames.get(currentFrame);
} catch(IndexOutOfBoundsException e){
currentFrame = 0;
sprites = frames.get(currentFrame);
}
previousTime = time;
}
}
}// end update
public void start (){
running = true;
previousTime = 0;
frameAtPause = 0;
currentFrame = 0;
}
public void stop (){
running = false;
running = true;
previousTime = 0;
frameAtPause = 0;
currentFrame = 0;
}
public void pause (){
frameAtPause = currentFrame;
running = false;
}
public void restart (){
currentFrame = frameAtPause;
running = true;
}
}
SpriteLoader
public class SpriteLoader {
//Initialize values
private BufferedImage bImage = null,bImage2 = null;
public SpriteLoader(String location){
try{
bImage = ImageIO.read(new File(location));
}catch(IOException e){
}
}
public BufferedImage getImage (int x, int y, int w, int h){
bImage2 = bImage.getSubimage(x, y , w, h);
return bImage2;
}
}
Here is the sprite I'm using
And the background
till now i tried to do everything that i could find on stackoverflow but i couldn't find anything that helped to solve the problem :S
EDIT1: Edited the main class to have only the GUI part but i don't know if i could clean the other classes since i dont knwo where the bug can be :S
EDIT2: Cleared unused methods
I'm pretty sure that this code should draw an oval on the screen next to the word text. However, the word is all the appears, the rest of the screen is black. This seems to happen with any primitive shape. I'd like to think I know java fairly well, but graphical things have been really confusing to me. I'm at my wit's end with this and any help would be appreciated.
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.util.ArrayList;
public class Game extends JPanel implements Runnable {
int W = 4;
int H = 3;
int windowSize = 300;
boolean running;
static boolean drawHitBoxes = true;
int FPSLimit = 30;
private Thread thread;
private BufferedImage buffer;
private Graphics2D g;
public Game() {
super();
setPreferredSize(new Dimension(W * windowSize, H * windowSize));
setFocusable(true);
requestFocus();
}
public void addNotify() {
super.addNotify();
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
public void run() {
running = true;
buffer = new BufferedImage(W * windowSize, H * windowSize,
BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) buffer.getGraphics();
// citList.add(new Citizen(200, 200, "Joe"));
long startTime;
long waitTime;
long frameTime = 1000 / FPSLimit; // /How long one frame should take
long currentFrameTime;
while (running) {
startTime = System.nanoTime(); // record when loop starts
gameUpdate();
gameRender();
gameDraw();
// Calculate how long the current frame took
currentFrameTime = (System.nanoTime() - startTime) / 1000000;
waitTime = frameTime - currentFrameTime;
try {
Thread.sleep(waitTime);
} catch (Exception e) {
} // Sleep for the remaining time
}
}
private void gameUpdate() {
// for(Citizen i:citList){i.update();} //Update citizens
}
private void gameRender() {
g.setColor(Color.WHITE);
g.drawOval(100, 100, W - 100, H - 100);
g.setColor(Color.WHITE);
g.drawString("Text.", 100, 100);
System.out.println("Drawing white box.");
// for(Citizen i:citList){i.draw(g);} //Draw citizens
}
private void gameDraw() {
Graphics gMain = this.getGraphics();
gMain.drawImage(buffer, 0, 0, null);
}
}
g.drawOval(100, 100, W-100, H-100);
W is 4 and H is 3, and so since W-100 is -96 and H-100 is -97, making your 3rd and 4th parameters negative, which doesn't make sense for the Graphics#drawOval(...) method since how can an oval's width and height be negative. Solution: be sure to use only positive parameters that make sense when calling this method. Probably what you want is:
// but you'll also want to avoid magic numbers such as 100 & 200 as well
g.drawOval(100, 100, W * windowSize - 200, H * windowSize - 200);
As an aside, myself, I prefer using passive graphics, drawing in paintComponent and am fearful whenever I see Swing code that has a Graphics or Graphics2D instance field.. Also your code looks to not obey Swing threading rules as it appears to be making Swing calls off of the Swing event thread.
I think it's better to create the paintComponent method and transfer your gameRender and gameDraw there and in your while loop replace their method calls with repaint(). Here is the code that works.
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.util.ArrayList;
public class Game extends JPanel implements Runnable {
int W = 4;
int H = 3;
int windowSize = 300;
boolean running;
static boolean drawHitBoxes = true;
int FPSLimit = 30;
private Thread thread;
private BufferedImage buffer;
private Graphics2D g;
public Game() {
super();
setPreferredSize(new Dimension(W * windowSize, H * windowSize));
setFocusable(true);
requestFocus();
}
public void addNotify() {
super.addNotify();
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
public void run() {
running = true;
buffer = new BufferedImage(W * windowSize, H * windowSize,
BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) buffer.getGraphics();
// citList.add(new Citizen(200, 200, "Joe"));
long startTime;
long waitTime;
long frameTime = 1000 / FPSLimit; // /How long one frame should take
long currentFrameTime;
while (running) {
startTime = System.nanoTime(); // record when loop starts
gameUpdate();
//gameRender();
//gameDraw();
repaint();
// Calculate how long the current frame took
currentFrameTime = (System.nanoTime() - startTime) / 1000000;
waitTime = frameTime - currentFrameTime;
try {
Thread.sleep(waitTime);
} catch (Exception e) {
} // Sleep for the remaining time
}
}
private void gameUpdate() {
// for(Citizen i:citList){i.update();} //Update citizens
}
private void gameRender() {
g.setColor(Color.WHITE);
//g.drawOval(100, 100, W - 100, H - 100);
g.drawOval(100, 100, 100, 100);
g.setColor(Color.WHITE);
g.drawString("Text.", 100, 100);
//System.out.println("Drawing white box.");
// for(Citizen i:citList){i.draw(g);} //Draw citizens
}
private void gameDraw(Graphics gMain) {
//Graphics gMain = this.getGraphics();
gMain.drawImage(buffer, 0, 0, null);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
gameRender();
gameDraw(g);
}
}
As point out by #Hovercraft in his answer, the W-100 and H-100 in the code `g.drawOval(100, 100, W - 100, H - 100);' will yield negative numbers. I don't know exactly what values do you want to result in there but I just replace them with 100 just to remove the bug.
Just wrote a program that displays dynamic animation. BTW, it runs but the problem is that backround keeps on flickering black and white at a rapid speed. i have googled it but didnt get an appropriate answer. Here is the code:
For main method -
import java.awt.*;
import javax.swing.*;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class nam2 {
public static void main(String[] args){
nam2 b= new nam2();
b.run();
}
private Sprite sprite; //class to control characteristics of image
private Animation a; //class to control animation
private ScreenManager s; //class to control monitor screen
private Image bg; //an image
private static final DisplayMode modes1[] = { // List of desired DisplayModes
new DisplayMode(800,600,32,0),
new DisplayMode(800,600,25,0),
new DisplayMode(800,600,16,0),
new DisplayMode(640,480,32,0),
new DisplayMode(640,480,24,0),
new DisplayMode(1920,1080,16,0),
};
//load images and add scenes
public void loadImages(){
bg = new ImageIcon("G:\\bg2.jpg").getImage();
Image face1 = new ImageIcon("G:\\naman1.jpg").getImage();
Image face2 = new ImageIcon("G:\\3.jpg").getImage();
a = new Animation();
a.addScene(face1,500);
a.addScene(face2,500);
sprite = new Sprite(a);
sprite.setVelocityX(0.3f);
sprite.setVelocityY(0.3f);
}
//run method call from main method
public void run(){
s = new ScreenManager();
try{
DisplayMode dm = s.findFirstCompDisplayMode(modes1);
s.setFullScreen(dm);
loadImages();
movieLoop();
}finally{s.restoreScren();}
}
public void movieLoop(){
long startingTime = System.currentTimeMillis();
long cumTime = startingTime;
while(cumTime - startingTime <10000){
long timePassed = System.currentTimeMillis() - cumTime ;
cumTime += timePassed;
update(timePassed);
//draw and update screen
Graphics2D g = s.getGraphics();
draw(g);
g.dispose();
s.update();
try{
Thread.sleep(20);
}catch(Exception e){}
}
}
//draw method
public void draw(Graphics g){
g.drawImage(bg, 0, 0, null);
g.drawImage(sprite.getImage(), Math.round(sprite.getX()),Math.round(sprite.getY()),null);
}
//update method
private void update(long timePassed) {
if(sprite.getX() < 0 ){
sprite.setVelocityX(Math.abs(sprite.getVelocityX()));
}else if(sprite.getX() + sprite.getWidth() >= s.getWidth()){
sprite.setVelocityX(-Math.abs(sprite.getVelocityX()));
}
if(sprite.getY() < 0 ){
sprite.setVelocityY(Math.abs(sprite.getVelocityY()));
}else if(sprite.getY() + sprite.getHeight() >= s.getHeight()){
sprite.setVelocityY(-Math.abs(sprite.getVelocityY()));
}
sprite.update(timePassed);
}
}
I have uploaded code of only main class . If other class codes are required please tell me. Isnt it something related to threads coz when i change the sleep time of thread, the speed of flickering changes. So my major issue to write this questions is:
Why does the screen flickers black to white and again to black continuously.