Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

What I am trying to do is create an animation that creates a 'running' motion. Whenever I draw it on the screen, the last frame in the animation is left behind (So there is a trail of animation frames left behind when the sprite moves). I've tried if statements and changing the image's draw position when the frame changes:

if(a2.sceneNum() == 0)
spectre_Draw1 = (screenWidth() / 2 - 120 / 2 + 120 - 6);
else
spectre_Draw1 = 0;

g.drawImage(pic[2], spectre_Draw1, (screenHeight() / 2 - 180 / 2), null);

if(a2.sceneNum() == 1)
spectre_Draw2 = (screenWidth() / 2 - 120 / 2 + 120 - 6);
else
spectre_Draw2 = 0;

g.drawImage(pic[3], spectre_Draw2, (screenHeight() / 2 - 180 / 2), null);

if(a2.sceneNum() == 2)
spectre_Draw3 = (screenWidth() / 2 - 120 / 2 + 120 - 6);
else
spectre_Draw3 = 0;

g.drawImage(pic[4], spectre_Draw3, (screenHeight() / 2 - 180 / 2), null);

Is there a way to do this while removing the trailing images?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
101 views
Welcome To Ask or Share your Answers For Others

1 Answer

I know it says "Avoid responding to other answers" but as a new registrant (but long-time user) I am only eligible to write "answers" or suggest edits.. I can't add comments to an answer until I am upvoted ! :-)

However, there are just too many errors in the source code in peeskillet's answer to qualify simply as "suggested edits" :-)

  1. Accidental interchange / confusion of ROWS and COLUMNS :

        SPRITE_ROWS = 5;
        SPRITE_COLUMNS = 2;
    
        DIM_W = img.getWidth() / SPRITE_ROWS;
        DIM_H = img.getHeight() / SPRITE_COLUMNS;
    

Further down the code, the program is clearly trying to treat rows and columns of the animation pictures in the grid correctly, but it is only because both of these are backwards that the program works. (ie there are 5 Columns and 2 Rows in the grid of images for the sample nerdgirl).

  1. Accidental interchange of DIM_H and DIM_W (1 occurrence) :

                if (x1Src >= img.getWidth() - DIM_H - 5) {  // 5 to take care of precisi
    

    "DIM_H" should be "DIM_W"

As listed, this code would cause a premature jumping to the next row of animation images in the grid (not showing the last image in each row) in the case where the individual images are either significantly taller than they are wide, or else there are many images in each row of the original grid. With the nerdgirl sample (833 x 639), the last image in each row would not have been shown if the overall grid had been just 10 pixels taller. (DIM_H = 319, img.getWidth()-DIM_H-5 = 503 and the last frame shows when x1Src = 498 ..only just made it !)

  1. Current code as shown only processes 2 rows of animation frames (even thought it correctly calculates the SIZE of each frame by changing eg SPRITE_COLUMNS (sic) to 4 for the running Man example).

This is because the following if-test :

                    if (y1Src >= DIM_H - 5) { // 5 to take care of lack of prec
                        y1Src = 0;

... should be :

                    if (y1Src >= imag.getHeight() - DIM_H - 5) { // 5 to take car
                        y1Src = 0;

..as the current code only ever displays 2 rows of sprite images even if there were more. (This explains why the flapping bird sample works "ok" without showing the final all-white frame... look carefully and it only shows the first 2 rows of images).

  1. Use of hard-coded 5 for "loss of precision" (meaning when the source images have not been composed evenly into the combined grid and they are not an exact multiple of the frame size) should actually refer to the number of frames present :

                if (x1Src >= img.getWidth() - DIM_W - SPRITE_COLUMNS) {  // - SPRITE_COLUMNS to take care of non-aligned source images (see samples)
    
                if (y1Src >= img.getHeight() - DIM_H - SPRITE_ROWS) {  // - SPRITE_ROWS to take care of non-aligned source images (see samples)
    

This is because the possible "loss of precision" is no more than 1 per frame in each row and column - resulting from the integer rounding that occurs when the animation image width and height are calculated. eg The nerdgirl sample at 833 x 639 calculates an animation frame size of 166 x 319, so after 5 images we have shown up to 830,638 of the original image.

However, I'd suggest the following would make both those if-statements much clearer and simpler :

                if (x2Src > img.getWidth()) {     // Beyond end of Row

                if (y2Src > img.getHeight()) {    // Beyond Last Row

... and there are a few other little tweaks as shown below.

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
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 NerdGirl extends JPanel {
    private static int SPRITE_COLUMNS = 5;         // Number of columns of sprite images in source file
    private static int SPRITE_ROWS    = 2;         // Number of rows    of sprite images in source file
    private static final int DELAY    = 100;       // inter-frame pause in milliseconds

    private int dim_W;                             // Width of an individual animation frame
    private int dim_H;                             // Height of an individual animation frame

    private int x1Src;                             // top-left coordinates of current frame
    private int y1Src;
    private int x2Src;                             //bottom-right coordinates of current frame
    private int y2Src;

    private BufferedImage img;

    public NerdGirl() {
        try {
            img = ImageIO.read(getClass().getResource("images/nerdgirl.jpg"));
            SPRITE_ROWS = 2;
            // Other sample files
            //img = ImageIO.read(getClass().getResource("images/explosion.png"));
            //SPRITE_ROWS = 3;
            //img = ImageIO.read(getClass().getResource("images/birdflight.png"));
            //SPRITE_ROWS = 3;
            //img = ImageIO.read(getClass().getResource("images/running_man.png"));
            //SPRITE_ROWS    = 4;
            //SPRITE_COLUMNS = 6;

        } catch (IOException ex) {
            Logger.getLogger(NerdGirl.class.getName()).log(Level.SEVERE, null, ex);
        }
        dim_W = img.getWidth()  / SPRITE_ROWS;
        dim_H = img.getHeight() / SPRITE_COLUMNS;
        x1Src = 0;
        y1Src = 0;
        x2Src = x1Src + dim_W;
        y2Src = y1Src + dim_H;

        Timer timer = new Timer(DELAY, new ActionListener() {
            public void actionPerformed(ActionEvent e) {

                // Move right to next frame (next column)
                x1Src += dim_W;
                x2Src += dim_W;

                if (x2Src > img.getWidth()) {  // Past end of current row.
                    x1Src = 0;                  // Back to start of row
                    x2Src = dim_W;

                    y1Src += dim_H;             // Move down to next Row
                    y2Src += dim_H;
                    if (y2Src > img.getHeight()) { // Below bottom of source grid of images
                        y1Src = 0;              // Back to Top.
                        y2Src = dim_H;
                    }
                }

                repaint();
            }
        });
        timer.start();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(img, 0, 0, getWidth(), getHeight(), x1Src, y1Src, x2Src, y2Src, this);
    }

    @Override
    public Dimension getPreferredSize() {
        return (img == null) ? new Dimension(300, 300) : new Dimension(dim_W, dim_H);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new NerdGirl());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}
  1. Finally, please note that independent of these issues, the sample animation source grids are poorly put together (the sprite-frame alignment is not always consistent) so that in the samples on this page you will sometimes see pieces of the neighbouring frames showing. Watch the bird-frame animation above carefully and see explanatory images here and here.)

If the grids were all compiled as a whole number multiple of the individual frame-size (as is the case with the running man png image @ 900x600 - even though the sample provided has picture "overlap" - see image link above), then the program code for the coordinate-checking could be even easier :

        Timer timer = new Timer(DELAY, new ActionListener() {
            public void actionPerformed(ActionEvent e) {

                // Move right to next frame (next column)
                x1Src += dim_W;

                if (x1Src == img.getWidth()) {  // At end of current row.
                    x1Src = 0;                  // Go Back to start of row
                    y1Src += dim_H;             // Move down to next Row

                    if (y1Src == img.getHeight()) { // Past all images
                        y1Src = 0;              // Back to Top.
                    }
                }

                x2Src += dim_W;
                y2Src += dim_H;

                repaint();
            }
        });
        timer.start();
    }

However, as input samples grids are unreliable in overall size and composition, the earlier code is recommended as it will cope with these inconsistencies.

I hope my answer saves some others valuable time in the long run !

Cheers,


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...