0

first time using a forum for coding help so sorry if i post this all wrong. i have more than a few classes i don't think screenManger or core holds the problem but i included them just incase. i got most of this code working through a set of tutorials. but a certain point started trying to do more on my own.

i want to play the animation only when i'm moving my sprite.

in my KeyTest class i am using threads to run the animation it used to work (poorly) but now not at all pluss it really gunks up my computer. i think it's because of the thread. im new to threads so i'm not to sure if i should even be using one in this situation or if its dangerous for my computer.

the animation worked smoothly when i had the sprite bouce around the screen forever. the animation loop played with out stopping.

i think the main problem is between the animationThread, Sprite, and keyTest classes, but itcould be more indepth.

if someone could point me in the right direction for making the animation run smoothly when i push down a key and stop runing when i let off it would be greatly apriciated.

i already looked at this Java a moving animation (sprite) obviously we were doing the same tutorial. but i feel my problem is slightly different.

p.s. sorry for the typos.

import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.ImageIcon;

public class KeyTest extends Core implements KeyListener {

public static void main(String[] args){
    new KeyTest().run();
}

Sprite player1;
Image hobo;
Image background;
animation hoboRun;
animationThread t1;



//init also calls init form superclass
public void init(){
    super.init();
    loadImages();
    Window w = s.getFullScreenWindow();
    w.setFocusTraversalKeysEnabled(false);
    w.addKeyListener(this);
}

//load method will go here.
//load all pics need for animation and sprite
public void loadImages(){
    background = new ImageIcon("\\\\STUART-PC\\Users\\Stuart\\workspace\\Gaming\\yellow square.jpg").getImage();
    Image face1 = new ImageIcon("\\\\STUART-PC\\Users\\Stuart\\workspace\\Gaming\\circle.png").getImage();
    Image face2 = new ImageIcon("\\\\STUART-PC\\Users\\Stuart\\workspace\\Gaming\\one eye.png").getImage();
    hoboRun = new animation();
    hoboRun.addScene(face1, 250);
    hoboRun.addScene(face2, 250);
    player1 = new Sprite(hoboRun);
    t1 = new animationThread();
    t1.setAnimation(player1);
}


//key pressed
public void keyPressed(KeyEvent e){
    int keyCode = e.getKeyCode();
    if(keyCode == KeyEvent.VK_ESCAPE){
        stop();
    }
    if(keyCode == KeyEvent.VK_RIGHT){
        player1.setVelocityX(0.3f);
        try{
            t1.setRunning(true);
            Thread th1 = new Thread(t1);
            th1.start();
        }catch(Exception ex){System.out.println("noooo");}
    }
    if(keyCode == KeyEvent.VK_LEFT){
        player1.setVelocityX(-0.3f);
        try{
            t1.setRunning(true);
            Thread th1 = new Thread(t1);
            th1.start();
        }catch(Exception ex){System.out.println("noooo");}
    }
    if(keyCode == KeyEvent.VK_DOWN){
        player1.setVelocityY(0.3f);
        try{
            t1.setRunning(true);
            Thread th1 = new Thread(t1);
            th1.start();
        }catch(Exception ex){System.out.println("noooo");}
    }
    if(keyCode == KeyEvent.VK_UP){
        player1.setVelocityY(-0.3f);
        try{
            t1.setRunning(true);
            Thread th1 = new Thread(t1);;
            th1.start();
        }catch(Exception ex){System.out.println("noooo");}
    }else{
        e.consume();
    }
}

//keyReleased
@SuppressWarnings("static-access")
public void keyReleased(KeyEvent e){
    int keyCode = e.getKeyCode();
    if(keyCode == KeyEvent.VK_RIGHT || keyCode == KeyEvent.VK_LEFT){
        player1.setVelocityX(0);
        try{
            this.t1.setRunning(false);
        }catch(Exception ex){}
    }
    if(keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_DOWN){
        player1.setVelocityY(0);
        try{
            this.t1.setRunning(false);
        }catch(Exception ex){}
    }else{
        e.consume();
    }
}

//last method from interface
public void keyTyped(KeyEvent e){
    e.consume();
}

//draw
public void draw(Graphics2D g){
    Window w = s.getFullScreenWindow();
    g.setColor(w.getBackground());
    g.fillRect(0, 0, s.getWidth(), s.getHieght());
    g.setColor(w.getForeground());
    g.drawImage(player1.getImage(), Math.round(player1.getX()), Math.round(player1.getY()), null);
}

public void update(long timePassed){
    player1.update(timePassed);
}
}


abstract class Core {

    private static DisplayMode modes[] = {
        new DisplayMode(1600, 900, 64, 0),
        new DisplayMode(800, 600, 32, 0),
        new DisplayMode(800, 600, 24, 0),
        new DisplayMode(800, 600, 16, 0),
        new DisplayMode(800, 480, 32, 0),
        new DisplayMode(800, 480, 24, 0),
        new DisplayMode(800, 480, 16, 0),};
    private boolean running;
    protected ScreenManager s;

    //stop method
    public void stop() {
        running = false;
    }

    public void run() {
        try {
            init();
            gameLoop();
        } finally {
            s.restoreScreen();
        }
    }

    //set to full screen
    //set current background here
    public void init() {
        s = new ScreenManager();
        DisplayMode dm = s.findFirstCompatibleMode(modes);
        s.setFullScreen(dm);

        Window w = s.getFullScreenWindow();
        w.setFont(new Font("Arial", Font.PLAIN, 20));
        w.setBackground(Color.GREEN);
        w.setForeground(Color.WHITE);
        running = true;
    }

    //main gameLoop
    public void gameLoop() {
        long startTime = System.currentTimeMillis();
        long cumTime = startTime;

        while (running) {
            long timePassed = System.currentTimeMillis() - cumTime;
            cumTime += timePassed;

            update(timePassed);

            Graphics2D g = s.getGraphics();
            draw(g);
            g.dispose();
            s.update();

            try {
                Thread.sleep(20);
            } catch (Exception ex) {
            }
        }
    }

    //update animation
    public void update(long timePassed) {
    }

    //draws to screen
    abstract void draw(Graphics2D g);
}


public class animationThread implements Runnable{

String name;
volatile boolean playing;
Sprite a;

//constructor takes input from keyboard
public animationThread(){
}

//The run method for animation
public void run() {
    long startTime = System.currentTimeMillis();
    long cumTime = startTime; 

    while(getRunning()){
        long timePassed = System.currentTimeMillis() - cumTime;
        cumTime += timePassed;
        a.startAnimation(timePassed);
    }
}

public String getName(){
    return name;
}

public void setAnimation(Sprite a){
    this.a=a;
}

public void setName(String name){
    this.name=name;
}

public synchronized void setRunning(boolean running){
    this.playing = running;
}

public synchronized boolean getRunning(){
    return playing;
}
}


class animation {

    private ArrayList scenes;
    private int sceneIndex;
    private long movieTime;
    private long totalTime;

    //constructor
    public animation() {
        scenes = new ArrayList();
        totalTime = 0;
        start();
    }

    //add scene to ArrayLisy and set time for each scene
    public synchronized void addScene(Image i, long t) {
        totalTime += t;
        scenes.add(new OneScene(i, totalTime));
    }

    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 animations current scene(aka image)
    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 Inner CLASS//////////////
    private class OneScene {

        Image pic;
        long endTime;

        public OneScene(Image pic, long endTime) {
            this.pic = pic;
            this.endTime = endTime;
        }
    }
}

class Sprite {

    private animation a;
    private float x;
    private float y;
    private float vx;
    private float vy;

    //Constructor
    public Sprite(animation a) {
        this.a = a;
    }

    //change position
    public void update(long timePassed) {
        x += vx * timePassed;
        y += vy * timePassed;
    }

    public void startAnimation(long timePassed) {
        a.update(timePassed);
    }

    //get x position
    public float getX() {
        return x;
    }

    //get y position
    public float getY() {
        return y;
    }

    //set x
    public void setX(float x) {
        this.x = x;
    }

    //set y
    public void setY(float y) {
        this.y = y;
    }

    //get sprite width
    public int getWidth() {
        return a.getImage().getWidth(null);
    }

    //get sprite height
    public int getHeight() {
        return a.getImage().getHeight(null);
    }

    //get horizontal velocity
    public float getVelocityX() {
        return vx;
    }

    //get vertical velocity
    public float getVelocityY() {
        return vx;
    }

    //set horizontal velocity
    public void setVelocityX(float vx) {
        this.vx = vx;
    }

    //set vertical velocity
    public void setVelocityY(float vy) {
        this.vy = vy;
    }

    //get sprite / image
    public Image getImage() {
        return a.getImage();
    }
}

class ScreenManager {

    private GraphicsDevice vc;

    public ScreenManager() {
        GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
        vc = e.getDefaultScreenDevice();
    }

    //get all compatible DM
    public DisplayMode[] getCompatibleDisplayModes() {
        return vc.getDisplayModes();
    }

    //compares DM passed into vc DM and see if they match
    public DisplayMode findFirstCompatibleMode(DisplayMode modes[]) {
        DisplayMode goodModes[] = vc.getDisplayModes();
        for (int x = 0; x < modes.length; x++) {
            for (int y = 0; y < goodModes.length; y++) {
                if (displayModesMatch(modes[x], goodModes[y])) {
                    return modes[x];
                }
            }
        }
        return null;
    }

    //get current DM
    public DisplayMode getCurrentDisplayMode() {
        return vc.getDisplayMode();
    }

    //checks if two modes match each other
    public boolean displayModesMatch(DisplayMode m1, DisplayMode m2) {
        if (m1.getWidth() != m2.getWidth() || m1.getHeight() != m2.getHeight()) {
            return false;
        }
        if (m1.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI && m2.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI && m1.getBitDepth() != m2.getBitDepth()) {
            return false;
        }
        if (m1.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN && m2.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN && m1.getRefreshRate() != m2.getRefreshRate()) {
            return false;
        }
        return true;
    }

    //make frame full screen
    public void setFullScreen(DisplayMode dm) {
        JFrame f = new JFrame();
        f.setUndecorated(true);
        f.setIgnoreRepaint(true);
        f.setResizable(false);
        vc.setFullScreenWindow(f);

        if (dm != null && vc.isDisplayChangeSupported()) {
            try {
                vc.setDisplayMode(dm);
            } catch (Exception ex) {
            }
        }
        f.createBufferStrategy(2);
    }

    //sets graphics object = this return
    public Graphics2D getGraphics() {
        Window w = vc.getFullScreenWindow();
        if (w != null) {
            BufferStrategy s = w.getBufferStrategy();
            return (Graphics2D) s.getDrawGraphics();
        } else {
            return null;
        }
    }

    //updates display
    public void update() {
        Window w = vc.getFullScreenWindow();
        if (w != null) {
            BufferStrategy s = w.getBufferStrategy();
            if (!s.contentsLost()) {
                s.show();
            }
        }
    }

    //returns full screen window
    public Window getFullScreenWindow() {
        return vc.getFullScreenWindow();
    }

    //get width of window
    public int getWidth() {
        Window w = vc.getFullScreenWindow();
        if (w != null) {
            return w.getWidth();
        } else {
            return 0;
        }
    }

    //get height of window
    public int getHieght() {
        Window w = vc.getFullScreenWindow();
        if (w != null) {
            return w.getHeight();
        } else {
            return 0;
        }
    }

    //get out of full screen
    public void restoreScreen() {
        Window w = vc.getFullScreenWindow();
        if (w != null) {
            w.dispose();
        }
        vc.setFullScreenWindow(null);
    }

    //create image compatible with monitor
    public BufferedImage createCopatibleImage(int w, int h, int t) {
        Window win = vc.getFullScreenWindow();
        if (win != null) {
            GraphicsConfiguration gc = win.getGraphicsConfiguration();
            return gc.createCompatibleImage(w, h, t);
        }
        return null;
    }
}
Community
  • 1
  • 1
  • I reformatted your 500+ line example; it's complete, but you'll get better results with a more focused [sscce](http://sscce.org/), for [example](http://stackoverflow.com/a/3256941/230513). – trashgod Jul 01 '12 at 20:37
  • Thank you i just edited the post before reading this so i hope i didn't mess up what you reformated. btw what did you do to reformat also what is sscce? thanks. – heysuse renard Jul 02 '12 at 03:50
  • It looks like sscce.org is down right now; try [sscce](http://mindprod.com/jgloss/sscce.html). For better formatting, use spaces, not tabs, to indent. – trashgod Jul 02 '12 at 07:50

3 Answers3

0

In your animationThread class you are accessing the field "playing". This should be done using synchronized blocks. As one option put the "synchronized" keyword before "playing". As one option put the "volatile" keyword before "playing".

Without "synchronized" one thread may not see a change of "playing" done in another thread. So the threads may run forever. (short answer only, because I am on one of those fancy mobile devices now)

EDIT:

With the "volatile" keyword the "playing" field, the field is accessed each time its value is read or written. Without it, a Thread may use a copy of it and doesn't see when the original field has changed.

You can make blocks "synchronized":

boolean setRunning(boolean running) {
    synchronized (this) {
        this.playing = running;
    }
}

You can make methods "synchronized":

synchronized boolean setRunning(boolean running) {
    this.playing = running;
}

"synchronized" ensures, that no two threads execute this code at the same time and it makes sure that a thread sees an "up to date" object. For instance if one thread changes the "playing" field and when another thread enters a synchronized block, then that other thread will see the changed value of the field.

Rainer Schwarze
  • 4,725
  • 1
  • 27
  • 49
  • java will not let me put "synchronized" before the boolean "playing" but i understand what you saying. am i missunderstanding where the key word should go? i ithought it can only go in when writing a method. Should i put the "synchronized" in the run method? or for the get and set methods for playing? i'll fool around with it. i'm only reluctant because when i mess up these threads my cpu goes to 100% and i need to restart. but i'll fool around with synchronized. and i'm still wondering if i even need the thread. like i said i'm new to threads so is this a time i need it? – heysuse renard Jul 02 '12 at 03:41
  • Sorry for my mistake. I changed the answer. (I will reduce answering when not sitting before a real computer in the future :-) ) Later today I probably have some more time to take a detailed look at the source code. – Rainer Schwarze Jul 02 '12 at 04:36
  • wow thanks alot i really apriciate it. i'll work with what you said now and see what happens. i'll be looking for what u say after a better look. – heysuse renard Jul 02 '12 at 04:50
  • ok i have changes some things (i also relized i never called startAnimation)lol but now this is the closet ive gotten to this being correct. it's acctually how i had it before i started messing around with it. any way the animation plays when i want it and stops too but it is super flickery. almost like its changing images at a super fast pace. i think i may be accedently calling the animation update twice somehow. i'll look but let me know if you see anything like that also the synchronized definetlly helpped no more com. lag from thread. – heysuse renard Jul 02 '12 at 05:04
0

i just figured out something new that may be important to note: when holding down the the right key to move the sprite and update the animation the code is being re executed i found out by doing this

public void keyPressed(KeyEvent e){
    int keyCode = e.getKeyCode();
    if(keyCode == KeyEvent.VK_ESCAPE){
        stop();
    }
    if(keyCode == KeyEvent.VK_RIGHT){
        player1.setVelocityX(0.3f);
        try{
            t1.setRunning(true);
            Thread th1 = new Thread(t1);
            th1.start();
        }catch(Exception ex){System.out.println("noooo");}
        player1.setVelocityX(0);
    }

at first the spite doesn't move because the velocity is set to zero at the end but if i hold the butten long enough the sprite jumps across the screen.

this has to be the problem but idk how to fix it

  • found this "When you press a key and keep the key pressed, Java generates repeated key pressed events. I refer to this scenario as key repeat."(not my words) – heysuse renard Jul 02 '12 at 05:34
  • This is not an answer; please edit you question to reflect your current situation. – trashgod Jul 02 '12 at 07:52
0

hey thanks for all the help i just solved it though.

public void keyPressed(KeyEvent e){
    if(godDamn){
        godDamn=false;
        int keyCode = e.getKeyCode();
        if(keyCode == KeyEvent.VK_ESCAPE){
            stop();
        }
        if(keyCode == KeyEvent.VK_RIGHT){
            player1.setVelocityX(0.3f);
            try{
                t1.setRunning(true);
                Thread th1 = new Thread(t1);
                th1.start();
            }catch(Exception ex){System.out.println("noooo");}
        }
        if(keyCode == KeyEvent.VK_LEFT){
            player1.setVelocityX(-0.3f);
            try{
                t1.setRunning(true);
                Thread th1 = new Thread(t1);
                th1.start();
            }catch(Exception ex){System.out.println("noooo");}
        }
        if(keyCode == KeyEvent.VK_DOWN){
            player1.setVelocityY(0.3f);
            try{
                t1.setRunning(true);
                Thread th1 = new Thread(t1);
                th1.start();
            }catch(Exception ex){System.out.println("noooo");}
        }
        if(keyCode == KeyEvent.VK_UP){
            player1.setVelocityY(-0.3f);
            try{
                t1.setRunning(true);
                Thread th1 = new Thread(t1);;
                th1.start();
            }catch(Exception ex){System.out.println("noooo");}
        }else{
            e.consume();
        }

    }
}

//keyReleased
@SuppressWarnings("static-access")
public void keyReleased(KeyEvent e){
    int keyCode = e.getKeyCode();
    if(keyCode == KeyEvent.VK_RIGHT || keyCode == KeyEvent.VK_LEFT){
        player1.setVelocityX(0);
        try{
            this.t1.setRunning(false);
        }catch(Exception ex){}
        godDamn=true;
    }
    if(keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_DOWN){
        player1.setVelocityY(0);
        try{
            this.t1.setRunning(false);
        }catch(Exception ex){}
    }else{
        e.consume();
    }
}

the new boolean stops the multiple key events from executing. i have to fine tune it but other wise i'm good.