Screen flickers black & white repeatedly - java

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.

Related

Why does this attempt to animate my moving sprite work?

I'm trying to animate the sprite in my game when a button is pressed, but when I press the button, it skips the animation. Its supposed to go one pixel, change sprites, and then go one more pixel and change back. Here is the code
//for all
import java.nio.file.*;
import javax.imageio.ImageIO;
import java.io.IOException;
import java.awt.image.*;
import java.net.*;
import java.awt.*;
import javax.swing.*;
import static java.lang.invoke.MethodHandles.*;
import java.awt.event.*;
//my Mario class (cut down a lot)
class Mario {
// all numbers multiplied by 2 from OG game
protected Direction dir;
protected int x, y;
protected BufferedImage sprite;
protected String currentSpriteName;
public Mario() {
this.x = 54;
this.y = 808;
dir = Direction.RIGHT;
setSprite(MVCE.SMALLSTANDFACERIGHT);
currentSpriteName = MVCE.SMALLSTANDFACERIGHT;
}
public void moveRight(){
if(this.dir == Direction.LEFT){
this.dir = Direction.RIGHT;
}
else if(this.dir == Direction.RIGHT){
this.x+=1;
}
}
public void animateMoveRight(){
if (currentSpriteName.equals(MVCE.SMALLSTANDFACERIGHT)){
setSprite(MVCE.SMALLWALKFACERIGHT);
}
else if (currentSpriteName.equals(MVCE.SMALLWALKFACERIGHT)){
setSprite(MVCE.SMALLSTANDFACERIGHT);
}
}
public void jump() {
this.y -= 46;
}
public void setSprite(String spriteName) {
URL spriteAtLoc = MVCE.urlGenerator(spriteName);
this.sprite = MVCE.generateAndFilter(sprite, spriteAtLoc);
}
public void getSprite(){
System.out.println(this.currentSpriteName);
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(sprite, 0, 0, null); // DO NOT SET x and y TO ANYTHING,
// this sets 0,0 to top left!!
}
}
// my MarioRender class:
class MarioRender extends JLabel {
protected Mario marioSprite;
public MarioRender() {
marioSprite = new Mario();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
marioSprite.paint(g2);
setBounds(marioSprite.x, marioSprite.y, marioSprite.sprite.getWidth(), marioSprite.sprite.getHeight());
}
public void moveMarioRight(){
marioSprite.moveRight();
marioSprite.animateMoveRight();
setLocation(this.marioSprite.getX(), this.marioSprite.getY());
repaint();
//this is my attempt to make it animate
marioSprite.moveRight();
marioSprite.animateMoveRight();
setLocation(this.marioSprite.getX(), this.marioSprite.getY());
repaint();
}
public void jumpMario() {
marioSprite.jump();
setLocation(this.marioSprite.x, this.marioSprite.y);
repaint();
}
}
// direction class, solely for moving
enum Direction {
LEFT, RIGHT
}
// my calling class, which I called MVCE where I make the frame
public class MVCE extends JFrame {
MarioRender m = new MarioRender();
JLabel bg;
public MVCE() {
bg = new JLabel();
this.setSize(868, 915);
this.setVisible(true);
this.add(bg, BorderLayout.CENTER);
bg.setLayout(null);
bg.add(m);
m.setBounds(m.marioSprite.x, m.marioSprite.y, m.marioSprite.sprite.getWidth(),
m.marioSprite.sprite.getHeight());
KeyListener kl = new MoveListener();
this.addKeyListener(kl);
this.setFocusable(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static final String SMALLSTANDFACERIGHT = "SmallStandFaceRight.bmp"; // 30
// x
// 32
public static final String SMALLJUMPFACERIGHT = "SmallJumpFaceRight.bmp"; // 32
// x
// 32
// generate URL
public static URL urlGenerator(String name) {
URL u = lookup().lookupClass().getResource(name);
return u;
}
// return image with filtered color
public static BufferedImage generateAndFilter(BufferedImage b, URL u) {
try {
b = ImageIO.read(u);
int width = b.getWidth();
int height = b.getHeight();
int[] pixels = new int[width * height];
b.getRGB(0, 0, width, height, pixels, 0, width);
for (int i = 0; i < pixels.length; i++) {
// System.out.println(pixels[i]);
if (pixels[i] == 0xFFff00fe) {
pixels[i] = 0x00ff00fe;
}
}
BufferedImage newSprite = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
newSprite.setRGB(0, 0, width, height, pixels, 0, width);
b = newSprite;
} catch (IOException e) {
System.out.println("sprite not found");
e.printStackTrace();
}
return b;
}
// key listener
class MoveListener implements KeyListener {
public void keyPressed(KeyEvent k) {
if ((k.getKeyCode() == 39)) {
m.moveMarioRight();
///THIS IS SUPPOSED TO MOVE HIM 1, change sprite, and automatically move him back, it moves 2 pixels but no animation
}
if (k.getKeyCode() == 83) { // S key
m.marioSprite.setSprite(SMALLJUMPFACERIGHT);
m.jumpMario();
}
}
public void keyReleased(KeyEvent k) {
}
public void keyTyped(KeyEvent k) {
}
}
public static void main(String[] args) {
MVCE m = new MVCE();
}
}
I tried putting this between the calls to marioMoveRight():
try {
Thread.sleep(200);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
but it just delays the whole thing. I had also tried using an ActionListener, but I don't know how to make it react only when the key is pushed. as I had it,
I had this class inside of MVCE:
class TickListener implements ActionListener{
public void actionPerformed(ActionEvent a){
m.marioSprite.setSprite(Constants.SMALLWALKFACERIGHT);
repaint();
}
}
and this at the end of the MVCE constructor:
ActionListener ac = new TickListener();
final int DELAY = 1000;
Timer t = new Timer(DELAY, ac);
t.start();
but then, the Mario just moves automatically. I do not want to use a sprite sheet for this project, I am trying to do it as this guy did for SMB1.
Many problems, don't know which one or if any will fix the problem:
Don't use a KeyListener. If a component doesn't have focus the component won't receive the event. Instead use Key Bindings.
Don't use "==" to compare Objects. Instead you should be using the equals(...) method.
Don't override paintComponent. A painting method is for painting only. You should not be changing the bounds of the component in the painting method.
Do basic debugging (problem solving) before asking a question. A simple System.out.println(...) added to various methods will determine if the code is executing as you expect. Then when you ask a question you can ask a specific question telling us which block of code does not execute as you expect.
You never actually call the method animateMoveRight(), and if I understand correcly, that's what's changing the sprite. Also, I doubt that you see the sprite change when calling the same method twice in a row without any delay.
Try putting the animateMoveRight() method into the moveRight() or the moveMarioRight() method and, if neccessary because the animation is too fast, add your delay code back where you had it. Be careful not to let the main thread sleep, as this causes everything to freeze, so start another one or use a timer etc.
EDIT: Good timers
I'm not too familiar with the Timer class, so I end up using the Thread variant. There are many tutorials for that out there, just search for "java threads" or "java multithreading". This is IMO a solid tutorial you can check out.

Finished project, how to add a background in NetBeans

I am using NetBeans IDE 8.2 and I created a simple clone game from tutorials.
I am looking to add a background to the app and my research keeps pointing to using JFrame Forms and a JLabel.
None of the tutorials touched on backgrounds or JFrame Forms/JLabels. So I am uncertain how to take my completed project and add a background. I have attempted to reproduce JFrame Forms and JLabel code only to be unable to put my classes/interfaces "inside?" or "on top?" of the JFrame Form/JLabel.
I apologize if this really isn't an ideal first question, I just signed up and this is my first dip into the Java pool. Game class with JFrame (not Form) settings
EDIT: Adding full paste of my Game.java class.
package game;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import java.util.ArrayList;
import javax.swing.*;
public class Game {
public final static int WIDTH = 1920, HEIGHT = 1080;
private String gameName = "Tutorial Game";
private Canvas game = new Canvas();
private Input input;
private ArrayList<Updatable> updatables = new ArrayList<>();
private ArrayList<Renderable> renderables = new ArrayList<>();
// Helper methods for update/render Arrays
public void addUpdatable(Updatable u) {
updatables.add(u);
}
public void removeUpdatable(Updatable u) {
updatables.remove(u);
}
public void addRenderable(Renderable r) {
renderables.add(r);
}
public void removeRenderable(Renderable r) {
renderables.remove(r);
}
public void start() {
// Initialize windows
Dimension gameSize = new Dimension(Game.WIDTH, Game.HEIGHT);
JFrame gameWindow = new JFrame(gameName);
gameWindow.setDefaultCloseOperation(3);
gameWindow.setSize(gameSize);
gameWindow.setResizable(false);
gameWindow.setLocationRelativeTo(null);
gameWindow.add(game);
game.setSize(gameSize);
game.setMinimumSize(gameSize);
game.setMaximumSize(gameSize);
game.setPreferredSize(gameSize);
gameWindow.setVisible(true);
// Initialize Input
input = new Input();
game.addKeyListener(input);
// Game loop
final int TICKS_PER_SECOND = 60;
final int TIME_PER_TICK = 1000 / TICKS_PER_SECOND;
final int MAX_FRAMESKIPS = 5;
long nextGameTick = System.currentTimeMillis();
int loops;
float interpolation;
long timeAtLastFPSCheck = 0;
int ticks = 0;
boolean running = true;
while(running) {
// Updating
loops = 0;
while(System.currentTimeMillis() > nextGameTick && loops < MAX_FRAMESKIPS) {
update();
ticks++;
nextGameTick += TIME_PER_TICK;
loops++;
}
// Rendering
interpolation = (float) (System.currentTimeMillis() + TIME_PER_TICK - nextGameTick)
/ (float) TIME_PER_TICK;
render(interpolation);
// FPS Check
if(System.currentTimeMillis() - timeAtLastFPSCheck >= 1000) {
System.out.println("FPS: " + ticks);
gameWindow.setTitle(gameName + " - FPS: " + ticks);
ticks = 0;
timeAtLastFPSCheck = System.currentTimeMillis();
}
}
}
private void update() {
for(Updatable u : updatables) {
u.update(input);
}
}
private void render(float interpolation) {
BufferStrategy b = game.getBufferStrategy();
if(b == null) {
game.createBufferStrategy(2);
return;
}
Graphics2D g = (Graphics2D) b.getDrawGraphics();
g.clearRect(0, 0, game.getWidth(), game.getHeight());
for(Renderable r : renderables) {
r.render(g, interpolation);
}
g.dispose();
b.show();
}
}

Strange behavior of drawing image in java

I am making an animation by drawing different images dozens of milliseconds after the former one. something like this:
drawimage(image1,0,0,null);
try {
Thread.sleep(100);
}catch(Exception e){//To do something
}
drawimage(image2,0,0,null);
But the first image doesn't show until the second one appear. That means they appear at the same time.
My question is why does this happen?
Me: Where exactly is this code? Is it in a paint/paintComponent method?
OP: it is in paintComponent. I use it to make animation, but I am not sure it is a good way.
You're right it isn't a good way. Don't ever call Thread.sleep in the paintComponent method. I would avoid the Thread.sleep all together and use a javax.swing.Timer. See more How to Use Swing Timers
See examples here and here and here and here.
You could...
Use a list of Images and every iteration firing of the Timer event, add another Image to the List<Image> and call repaint()
You could...
Have an MyImage object class that has an Image field and a boolean draw field. In the Timer, loop through the MyImage objects and do something like
for (MyImage image: images) {
if (!image.isDraw()) {
image.setDraw(true);
break;
}
}
repaint();
For the MyImage List just loop through them in the paintComponent method and call it drawImage method, that you create.
Run this exmaple, showing the first option
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class AnimateImages extends JPanel {
private static final int IMAGE_ROWS = 10;
private static final int IMAGE_COLS = 10;
private static final int IMAGE_SIZE = 50;
private static final int DIM_WIDTH = IMAGE_COLS * IMAGE_SIZE;
private final List<MyImage> images;
private Image image;
private int currX = -IMAGE_SIZE;
private int currY;
public AnimateImages() {
try {
image = ImageIO.read(new URL("http://swoo.co.uk/content/images/icons/stackoverflow.png"));
} catch (IOException ex) {
Logger.getLogger(AnimateImages.class.getName()).log(Level.SEVERE, null, ex);
}
images = createImages();
Timer timer = new Timer(100, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (MyImage image : images) {
if (!image.isDraw()) {
image.setDraw(true);
break;
}
repaint();
}
}
});
timer.start();
}
private List<MyImage> createImages() {
List<MyImage> list = new ArrayList<>();
for (int i = 0; i < IMAGE_ROWS * IMAGE_COLS; i++) {
if (currX >= DIM_WIDTH) {
currX = 0;
currY += IMAGE_SIZE;
} else {
currX += IMAGE_SIZE;
}
list.add(new MyImage(image, currX, currY));
}
return list;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (MyImage img : images) {
img.draw(g);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(IMAGE_SIZE * IMAGE_COLS, IMAGE_SIZE * IMAGE_ROWS);
}
public class MyImage {
Image image;
int x, y;
boolean draw = false;
public MyImage(Image image, int x, int y) {
this.image = image;
this.x = x;
this.y = y;
}
public void setDraw(boolean draw) {
this.draw = draw;
}
public boolean isDraw() {
return draw;
}
public void draw(Graphics g) {
if (draw) {
g.drawImage(image, x, y, IMAGE_SIZE, IMAGE_SIZE, AnimateImages.this);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.add(new AnimateImages());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
The program, in its current state, draws two images at the same time because there are two draw methods in the loop (if you are indeed using a loop).
In order to solve this issue, you should use only a single draw method and leave the delay in the same place. However, in order to cycle through all of the different image variables (if you have them named as numbers 1,2,3,4...etc in an array) you can use a for loop to draw them:
for (int i = 0; i< *however many images you have*; i++){
drawimage(image[i],0,0,null);
try {
Thread.sleep(100);
}catch(Exception e){//To do something
}
}
Edit
You do not use delays inside the paintComponent. Since you are, that is what is likely causing the issues. Move the delay into the main method of your program.
Your answer
You're getting this result because it is printing image1, waiting .1 seconds and then printing image2. Then it doesn't wait at all, the game is immediately updated and then prints image1. Your display time for image2 is microscopic and you're likely only seeing image1 as a result.
Furthermore, the images are never deleted or replaced and so you are constantly drawing images on top of each other which is causing a memory leak, and is likely the cause of you seeing both images.
Considerations
This is a handy little animation class that I got, and still use, from this tutorial. This class is pretty handy and you can add the animated sprites necessary for each animation.
With this class, when you do a drawImage() you can use object.getImage() to extract the current frame of the animation.
Just make sure that you're calling the animation's update() method in your game's main loop so that the animations are constantly being updated.
import java.awt.Image;
import java.util.ArrayList;
public class Animation {
private ArrayList frames;
private int currentFrame;
private long animTime;
private long totalDuration;
public Animation() {
frames = new ArrayList();
totalDuration = 0;
synchronized (this) {
animTime = 0;
currentFrame = 0;
}
}
public synchronized void addFrame(Image image, long duration) {
totalDuration += duration;
frames.add(new AnimFrame(image, totalDuration));
}
public synchronized void update(long elapsedTime) {
if (frames.size() > 1) {
animTime += elapsedTime;
if (animTime >= totalDuration) {
animTime = animTime % totalDuration;
currentFrame = 0;
}
while (animTime > getFrame(currentFrame).endTime) {
currentFrame++;
}
}
}
public synchronized Image getImage() {
if (frames.size() == 0) {
return null;
} else {
return getFrame(currentFrame).image;
}
}
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;
}
}
}

java creating smooth multi image animation

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

Thread won't start

I am attempting to move an star image diagonally across. I am using a Thread to try and achieve this. The program compiles and the image is displayed, however the star won't move at all. I dont think the thread started properly.
Help would be greatly appreciated
drawing class (Board):
//define host package
package star;
//import awt and swing drawing packages
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
//jpanel and other javax classes
import javax.swing.JPanel;
import javax.swing.ImageIcon;
//main board class
public class Board extends JPanel implements Runnable
{
//constructor
Image star; //star image to hold image returned from directory
int x, y; //co ordinates for translation of star image
//delay constant
private final int DELAY = 50;
private Thread animator;
public Board()
{
//set the background colour to black
setBackground(Color.black);
//image directory
ImageIcon ii = new ImageIcon(this.getClass().getResource("star.png"));
//retrieve image from directory
star = ii.getImage();
//paint in memory then screen to improve
setDoubleBuffered(true);
//set star co ords variables
x = y = 10;
}
//initialize thread
void AddNotify()
{
super.addNotify();
//run method in this class
animator = new Thread(this);
animator.start();
}
//jpanel paintComponent() with abstract graphics object
#Override public void paintComponent(Graphics comp)
{
//repaint screen due to animation
super.paintComponent(comp);
Graphics2D comp2d = (Graphics2D) comp;
//draw the star
//class should be notified of drawing
comp2d.drawImage(star, x, y, this);
//sync for linux systems
Toolkit.getDefaultToolkit().sync();
comp.dispose();
}
//set the coordinates for the star image
public void cycle()
{
//move star
x += 1;
y += 1;
//if top corner goes out of range
if (y > 240)
{
x = -45;
y = -45;
}
System.out.println("x: " + x + "y: " + y);
}
//action performed method. Event parameter from the timer
public void run()
{
//beforeTime, timeDiff and sleep variables
//long = 2 x integer
long beforeTime, timeDiff, sleep;
beforeTime = System.currentTimeMillis();
//infinite loop
while (true)
{
//cycle and add notify methods
cycle();
//call the paintComponent method
repaint();
//compute system time
timeDiff = System.currentTimeMillis() - beforeTime;
/*subtracting from delay keeps lag from cycle() & AddNotify()
methods unoticable.
timeDiff will change with each loop cycle
*/
sleep = DELAY - timeDiff;
//compensate for a timeDiff > 50
if (sleep < 0)
{
sleep = 2;
}
//sleep thread in exception
try
{
Thread.sleep(sleep);
}
catch (InterruptedException ie)
{
System.out.println("Thread could not sleep: " + ie.getMessage());
}
//reset beforeTime time
beforeTime = System.currentTimeMillis();
}
}
}
main java frame class:
//import jframe
import javax.swing.JFrame;
//main class
public class Star extends JFrame
{
//constructor
public Star()
{
//title, resize, size, location etc.
add(new Board2());
setTitle("Star animation");
setSize(240, 280);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setResizable(false);
setVisible(true);
}
//class instance
public static void main(String[] arguements)
{
new Star();
}
}
Happy to clarify on request.
You're never calling AddNotify method, which is where you start your thread. I'm guessing you have a typo, and you meant addNotify instead (notice the lower case).
When overriding methods, it's useful to add #Override tag, as compiler will complain if the method you're overriding does not exists.
#Override
void addNotify() {
super.addNotify();
//run method in this class
animator = new Thread(this);
animator.start();
}
It seems your Thread start call is not invoked anywhere in your code execution. You are starting the thread in AddNotify method but that method is not called.
Also your code has a compilation problem on this line:
add(new Board2());
there is no class Board2, rather your class name is Board. I expect it is just an error while pasting the code here.

Categories

Resources