Sprite animation dosen't work properly.

But I have a new problem. I’m trying to make a new game, and when I press left, my character won’t face left. He just faces right(His default is facing right).

Is their a way to fix it so that when I press the right key, he faces right and when I press the left key, he faces left?

Here are the source codes

Animation


import java.awt.*;
import java.util.ArrayList;

public class Animation {

    public ArrayList<Frame> frames;
    public int f = 0;
    public long currentTime;
    public long totalTime;

    public Animation() {
        frames = new ArrayList();
        totalTime = 0;
        start();
    }

    public synchronized void addFrame(Image i, long t) {
        totalTime += t;
        frames.add(new Frame(i, totalTime));
    }

    public synchronized void start() {
        currentTime = 0;
        f = 0;
    }

    public synchronized void update(long time) {
        if (frames.size() > 1) {
            currentTime += time;
            if (currentTime >= totalTime) {
                currentTime = 0;
                f = 0;
            }
            while (currentTime > frames.get(f).time) {
                f++;
                System.out.println("next frame");
            }
        }
        //System.out.println(time);
    }

    public synchronized Image getImage() {
        if (frames.isEmpty()) {
            return null;
        } else {
            return frames.get(f).img;
        }
    }

    public class Frame {

        public Image img;
        public long time;

        public Frame(Image i, long t) {
            img = i;
            time = t;
        }
    }
}

ExtremeMario


import javax.swing.JFrame;

public class ExtremeMario {

    public ExtremeMario() {
        JFrame f = new JFrame();
        f.setTitle("ExtremeMario");
        f.add(new MainConfig());
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(500, 500);
        f.setVisible(true);

    }

    public static void main(String[] args) {
        new ExtremeMario();
    }
}


MainConfig


import extrememario.mario.*;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class MainConfig extends JPanel implements Runnable {

    public Mario mario;
    public Thread mainLoop;

    public MainConfig() {
        mario = new Mario();
        this.addKeyListener(new KL());

    }

    @Override
    public void addNotify() {
        super.addNotify();
        mainLoop = new Thread(this);
        mainLoop.start();
    }

    @Override
    public void run() {
        long lastTime = System.currentTimeMillis();
        while (true) {
            long nowTime = System.currentTimeMillis();
            long timePassed = nowTime - lastTime;
            lastTime = nowTime;
            mario.sprite().update(timePassed);
            repaint();
            try {
                Thread.sleep(10);
            } catch (Exception e) {
            }
        }

    }
    public Image bg = new ImageIcon(this.getClass().getResource("/extrememario/BackgroundDemoStage.png")).getImage();

    @Override
    public void paint(Graphics g) {
        g.drawImage(bg, 0, 0, null);
        g.drawImage(mario.getFrame(), 250, 250, null);
        g.dispose();
    }

    public class KL implements KeyListener {

        @Override
        public void keyPressed(KeyEvent e) {
            mario.keyPressed(e);
        }

        @Override
        public void keyReleased(KeyEvent e) {
            mario.keyReleased(e);
        }

        @Override
        public void keyTyped(KeyEvent e) {
        }
    }
}


Sprite


import java.awt.Image;

public class Sprite {

    public int x, y;
    public Animation a;

    public Sprite(Animation anim) {
        a = anim;
    }

    public void update(long time) {
        a.update(time);
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getWidth() {
        return a.getImage().getWidth(null);
    }

    public int getHieght() {
        return a.getImage().getHeight(null);
    }

    public Image getImage() {
        return a.getImage();
    }
}

Mario


import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;

/**
 *
 * @author ben
 */
public class Mario extends MarioSprites implements KeyListener {

    public Mario() {
        idleRight();
    }
    public boolean ap;//stands for already pressed

    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_RIGHT) {
            idleRight();

        } else if (keyCode == KeyEvent.VK_LEFT) {
            idleLeft();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_RIGHT) {
            idleRight();

        } else if (keyCode == KeyEvent.VK_LEFT) {
            idleLeft();
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }
}

MarioSprites


import extrememario.Animation;
import extrememario.Sprite;
import java.awt.Image;
import javax.swing.ImageIcon;

public class MarioSprites {

    public Animation idleAnimRight;
    public Sprite currentSprite;

    public void idleRight() {
        idleAnimRight = new Animation();
        Image f1 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame0.png")).getImage();
        Image f2 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame1.png")).getImage();
        Image f3 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame2.png")).getImage();
        Image f4 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame3.png")).getImage();
        Image f5 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame4.png")).getImage();
        idleAnimRight.addFrame(f1, 110);
        idleAnimRight.addFrame(f2, 110);
        idleAnimRight.addFrame(f3, 110);
        idleAnimRight.addFrame(f4, 110);
        idleAnimRight.addFrame(f5, 110);
        currentSprite = new Sprite(idleAnimRight);
    }
    public Animation idleAnimLeft;

    public void idleLeft() {
        idleAnimRight = new Animation();
        Image f1 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft1.png")).getImage();
        Image f2 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft2.png")).getImage();
        Image f3 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft3.png")).getImage();
        Image f4 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft4.png")).getImage();
        Image f5 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft5.png")).getImage();
        idleAnimLeft.addFrame(f1, 110);
        idleAnimLeft.addFrame(f2, 110);
        idleAnimLeft.addFrame(f3, 110);
        idleAnimLeft.addFrame(f4, 110);
        idleAnimLeft.addFrame(f5, 110);
        currentSprite = new Sprite(idleAnimLeft);
    }

    public Sprite sprite() {
        return currentSprite;
    }

    public Image getFrame() {
        return currentSprite.getImage();
    }
}


Check to see if the idleLeft() method is actually called. Also it is not good to reload all the images in the idleLeft() and idleRight(). You should only load your resources in memory once or else it will slow down your entire game.

Thanks for the reply.

Yea, I checked, idleLeft() is called.

It starts from MarioSprites


    public Animation idleAnimLeft;
    public Image l1 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft1.png")).getImage();
    public Image l2 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft2.png")).getImage();
    public Image l3 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft3.png")).getImage();
    public Image l4 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft4.png")).getImage();
    public Image l5 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft5.png")).getImage();

    public void idleLeft() {
        idleAnimLeft = new Animation();
        idleAnimLeft.addFrame(l1, 110);
        idleAnimLeft.addFrame(l2, 110);
        idleAnimLeft.addFrame(l3, 110);
        idleAnimLeft.addFrame(l4, 110);
        idleAnimLeft.addFrame(l5, 110);
    }

to Mario


@Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_RIGHT) {
            idleRight();
            currentSprite = new Sprite(idleAnimRight);

        } else if (keyCode == KeyEvent.VK_LEFT) {
            idleLeft();
            currentSprite = new Sprite(idleAnimLeft);
        }
    }


to
MainConfig


    public MainConfig() {
        mario = new Mario();
        addKeyListener(new KL());

    }


    public class KL implements KeyListener {

        @Override
        public void keyPressed(KeyEvent e) {
            mario.keyPressed(e);
        }

        @Override
        public void keyReleased(KeyEvent e) {
            mario.keyReleased(e);
        }

        @Override
        public void keyTyped(KeyEvent e) {
        }
    }

Here are all the changed source codes(whole classes)

MainConfig


import extrememario.mario.*;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class MainConfig extends JPanel implements Runnable {

    public Mario mario;
    public Thread mainLoop;

    public MainConfig() {
        mario = new Mario();
        addKeyListener(new KL());

    }

    @Override
    public void addNotify() {
        super.addNotify();
        mainLoop = new Thread(this);
        mainLoop.start();
    }

    @Override
    public void run() {
        long lastTime = System.currentTimeMillis();
        while (true) {
            long nowTime = System.currentTimeMillis();
            long timePassed = nowTime - lastTime;
            lastTime = nowTime;
            mario.sprite().update(timePassed);
            repaint();
            try {
                Thread.sleep(10);
            } catch (Exception e) {
            }
        }

    }
    public Image bg = new ImageIcon(this.getClass().getResource("/extrememario/BackgroundDemoStage.png")).getImage();

    @Override
    public void paint(Graphics g) {
        g.drawImage(bg, 0, 0, null);
        g.drawImage(mario.getFrame(), 250, 250, null);
        g.dispose();
    }

    public class KL implements KeyListener {

        @Override
        public void keyPressed(KeyEvent e) {
            mario.keyPressed(e);
        }

        @Override
        public void keyReleased(KeyEvent e) {
            mario.keyReleased(e);
        }

        @Override
        public void keyTyped(KeyEvent e) {
        }
    }
}

Mario


import extrememario.Sprite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;

/**
 *
 * @author ben
 */
public class Mario extends MarioSprites implements KeyListener {

    public Mario() {
        idleRight();
        currentSprite = new Sprite(idleAnimRight);
    }

    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_RIGHT) {
            idleRight();
            currentSprite = new Sprite(idleAnimRight);

        } else if (keyCode == KeyEvent.VK_LEFT) {
            idleLeft();
            currentSprite = new Sprite(idleAnimLeft);
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_RIGHT) {
        } else if (keyCode == KeyEvent.VK_LEFT) {
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }
}

MarioSprites


import extrememario.Animation;
import extrememario.Sprite;
import java.awt.Image;
import javax.swing.ImageIcon;

public class MarioSprites {

    public Animation idleAnimRight;
    public Sprite currentSprite;
    
    public Image r1 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame0.png")).getImage();
    public Image r2 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame1.png")).getImage();
    public Image r3 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame2.png")).getImage();
    public Image r4 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame3.png")).getImage();
    public Image r5 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame4.png")).getImage();

    public void idleRight() {
        idleAnimRight = new Animation();
        idleAnimRight.addFrame(r1, 110);
        idleAnimRight.addFrame(r2, 110);
        idleAnimRight.addFrame(r3, 110);
        idleAnimRight.addFrame(r4, 110);
        idleAnimRight.addFrame(r5, 110);
    }
    public Animation idleAnimLeft;
    public Image l1 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft1.png")).getImage();
    public Image l2 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft2.png")).getImage();
    public Image l3 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft3.png")).getImage();
    public Image l4 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft4.png")).getImage();
    public Image l5 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft5.png")).getImage();

    public void idleLeft() {
        idleAnimLeft = new Animation();
        idleAnimLeft.addFrame(l1, 110);
        idleAnimLeft.addFrame(l2, 110);
        idleAnimLeft.addFrame(l3, 110);
        idleAnimLeft.addFrame(l4, 110);
        idleAnimLeft.addFrame(l5, 110);
    }

    public Sprite sprite() {
        return currentSprite;
    }

    public Image getFrame() {
        return currentSprite.getImage();
    }
}

I took a good look at everything and all seems fine to me :S
Try using a debugger :slight_smile:

see what happens when you set the default to left? cuase then that’ll telly ou whether your whole method of doing it is wrong, or just the implementation

When I make,


    public Mario() {
        idleLeft();
        currentSprite = new Sprite(idleAnimLeft);
        currentSprite.x = 250;
        currentSprite.y = 250;
    }

he faces left, but when I press right, he won’t face right.
So far, I’ve figured out that the keyPressed in Mario isn’t actually getting called, but I can’t seem to figure out why. Any idea’s or thoughts to fix this?

Here are all the changed soruce codes

Mario


public class Mario extends MarioSprites{

    public Mario() {
        idleLeft();
        currentSprite = new Sprite(idleAnimLeft);
        currentSprite.x = 250;
        currentSprite.y = 250;
    }

    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_RIGHT) {
            System.out.println("Right key");
            idleRight();
            currentSprite = new Sprite(idleAnimRight);         

        } else if (keyCode == KeyEvent.VK_LEFT) {
            idleLeft();
            currentSprite = new Sprite(idleAnimLeft);
        }
    }

    public void keyReleased(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_RIGHT) {
        } else if (keyCode == KeyEvent.VK_LEFT) {
        }
    }

    public void keyTyped(KeyEvent e) {
    }
}


MainConfig


import extrememario.mario.*;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class MainConfig extends JPanel implements Runnable {

    public Mario mario;
    public Thread mainLoop;

    public MainConfig() {
        mario = new Mario();
        addKeyListener(new KL());
        System.out.println();
    }

    @Override
    public void addNotify() {
        super.addNotify();
        mainLoop = new Thread(this);
        mainLoop.start();
    }

    public Image bg = new ImageIcon(this.getClass().getResource("/extrememario/BackgroundDemoStage.png")).getImage();

    @Override
    public void paint(Graphics g) {
        g.drawImage(bg, 0, 0, null);
        g.drawImage(mario.getFrame(), mario.currentSprite.getX(), mario.currentSprite.getY(), null);
        g.dispose();
    }

    public class KL extends KeyAdapter {
        @Override
        public void keyPressed(KeyEvent e) {
            mario.keyPressed(e);
        }

        @Override
        public void keyReleased(KeyEvent e) {
            mario.keyReleased(e);
        }
    }
        @Override
    public void run() {
        long lastTime = System.currentTimeMillis();
        while (true) {
            long nowTime = System.currentTimeMillis();
            long timePassed = nowTime - lastTime;
            lastTime = nowTime;
            mario.sprite().update(timePassed);            
            repaint();
            try {
                Thread.sleep(10);
            } catch (Exception e) {
            }
        }

    }
}


MarioSprites


import extrememario.Animation;
import extrememario.Sprite;
import java.awt.Image;
import javax.swing.ImageIcon;

public class MarioSprites {

    public Animation idleAnimRight;
    public Sprite currentSprite;
    public int sx,sy;
    
    public Image r1 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame0.png")).getImage();
    public Image r2 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame1.png")).getImage();
    public Image r3 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame2.png")).getImage();
    public Image r4 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame3.png")).getImage();
    public Image r5 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame4.png")).getImage();

    public void idleRight() {
        idleAnimRight = new Animation();
        idleAnimRight.addFrame(r1, 110);
        idleAnimRight.addFrame(r2, 110);
        idleAnimRight.addFrame(r3, 110);
        idleAnimRight.addFrame(r4, 110);
        idleAnimRight.addFrame(r5, 110);
    }
    public Animation idleAnimLeft;
    public Image l1 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft1.png")).getImage();
    public Image l2 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft2.png")).getImage();
    public Image l3 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft3.png")).getImage();
    public Image l4 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft4.png")).getImage();
    public Image l5 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft5.png")).getImage();

    public void idleLeft() {
        idleAnimLeft = new Animation();
        idleAnimLeft.addFrame(l1, 110);
        idleAnimLeft.addFrame(l2, 110);
        idleAnimLeft.addFrame(l3, 110);
        idleAnimLeft.addFrame(l4, 110);
        idleAnimLeft.addFrame(l5, 110);
    }

    public Sprite sprite() {
        return currentSprite;
    }

    public Image getFrame() {
        return currentSprite.getImage();
    }
}


Check to see if the methods under KL are being called when you press the keys.

Handling KeyStrokes has always confused me. :clue:

It looks like you are adding the keyListener to “this”, i.e., MainConfig, but I don’t see where MainConfig implements a KeyListener. Does a JPanel implement KeyListener by default or does it have to be specified?

@philfrei
The line “addKeyListener(new KL());” is what adds the listener to the JPanel.

or “this.addKeyListener(new KeyListenerClass());”

it’s not confusing, share the listened event among all class (like lwjgl) is.

I’ve tried, and the keyPressed() under KL dosen’t seem to be able to call the stuff inside of it.


    public class KL extends KeyAdapter {

        @Override
        public void keyPressed(KeyEvent e) {            
            mario.keyPressed(e);
            int keyCode = e.getKeyCode();
            if(keyCode == KeyEvent.VK_RIGHT){
                System.out.println("VK_Right pressed");
            }
        }

        @Override
        public void keyReleased(KeyEvent e) {
            mario.keyReleased(e);
        }
    }

Do you add mario to KL? If not you will get a null pointer.

yeah, aazimon is probably right. although I would imagine that it would be crashing on him.

is the KL class code u should us, the ENTIRE code?

I’ve figured out the problem. I need setFocusable() in my MainConfig constructor after addKeyListener().


    public MainConfig() {
        mario = new Mario();
        this.addKeyListener(new KL());
        this.setFocusable(true);
        System.out.println();
    }

@aazimon
Since the inner class KL isn’t static, it “inherits” the members from the parent class.

@SubzeroX5
Yeah I suspected you weren’t even getting any events. I didn’t know JPanel’s were by default non-focusable. I recommend using JComponent instead since those are automatically focusable.