Как создать анимационную систему на основе спрайтов? [закрыто]

Я хочу сделать анимацию на основе листа спрайтов, но я застрял в ее реализации.

Ключевыми вещами, которые мне нужны, является мой код:

  • Воспроизведение через один набор изображений (например, анимация перехода)
  • Прокручивайте непрерывный набор изображений (например, ходячую анимацию)
  • Изменение скорости анимации

Как я могу реализовать такую ​​систему?

5 голосов | спросил guester 12 AMpFri, 12 Apr 2013 07:15:43 +040015Friday 2013, 07:15:43

1 ответ


15

Способ 2D-анимации выглядит следующим образом:

Класс поиска Sprite

Этот класс может либо загружать файл изображения, либо загружать спрайт из листа спрайтов. Это очень объяснительно.

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class Sprite {

    private static BufferedImage spriteSheet;
    private static final int TILE_SIZE = 32;

    public static BufferedImage loadSprite(String file) {

        BufferedImage sprite = null;

        try {
            sprite = ImageIO.read(new File("res/" + file + ".png"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        return sprite;
    }

    public static BufferedImage getSprite(int xGrid, int yGrid) {

        if (spriteSheet == null) {
            spriteSheet = loadSprite("AnimationSpriteSheet");
        }

        return spriteSheet.getSubimage(xGrid * TILE_SIZE, yGrid * TILE_SIZE, TILE_SIZE, TILE_SIZE);
    }

}

Класс анимации

import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;


public class Animation {

    private int frameCount;                 // Counts ticks for change
    private int frameDelay;                 // frame delay 1-12 (You will have to play around with this)
    private int currentFrame;               // animations current frame
    private int animationDirection;         // animation direction (i.e counting forward or backward)
    private int totalFrames;                // total amount of frames for your animation

    private boolean stopped;                // has animations stopped

    private List<Frame> frames = new ArrayList<Frame>();    // Arraylist of frames 

    public Animation(BufferedImage[] frames, int frameDelay) {
        this.frameDelay = frameDelay;
        this.stopped = true;

        for (int i = 0; i < frames.length; i++) {
            addFrame(frames[i], frameDelay);
        }

        this.frameCount = 0;
        this.frameDelay = frameDelay;
        this.currentFrame = 0;
        this.animationDirection = 1;
        this.totalFrames = this.frames.size();

    }

    public void start() {
        if (!stopped) {
            return;
        }

        if (frames.size() == 0) {
            return;
        }

        stopped = false;
    }

    public void stop() {
        if (frames.size() == 0) {
            return;
        }

        stopped = true;
    }

    public void restart() {
        if (frames.size() == 0) {
            return;
        }

        stopped = false;
        currentFrame = 0;
    }

    public void reset() {
        this.stopped = true;
        this.frameCount = 0;
        this.currentFrame = 0;
    }

    private void addFrame(BufferedImage frame, int duration) {
        if (duration <= 0) {
            System.err.println("Invalid duration: " + duration);
            throw new RuntimeException("Invalid duration: " + duration);
        }

        frames.add(new Frame(frame, duration));
        currentFrame = 0;
    }

    public BufferedImage getSprite() {
        return frames.get(currentFrame).getFrame();
    }

    public void update() {
        if (!stopped) {
            frameCount++;

            if (frameCount > frameDelay) {
                frameCount = 0;
                currentFrame += animationDirection;

                if (currentFrame > totalFrames - 1) {
                    currentFrame = 0;
                }
                else if (currentFrame < 0) {
                    currentFrame = totalFrames - 1;
                }
            }
        }

    }

}

Класс анимации запускается, останавливается, перезапускается и сбрасывается для управления анимацией. Вы можете легко добавить логическое значение, чтобы проверить, должно ли оно зацикливаться или нет. Я не буду добавлять это для вас.

Класс кадра

import java.awt.image.BufferedImage;

public class Frame {

    private BufferedImage frame;
    private int duration;

    public Frame(BufferedImage frame, int duration) {
        this.frame = frame;
        this.duration = duration;
    }

    public BufferedImage getFrame() {
        return frame;
    }

    public void setFrame(BufferedImage frame) {
        this.frame = frame;
    }

    public int getDuration() {
        return duration;
    }

    public void setDuration(int duration) {
        this.duration = duration;
    }

}

Класс Frame содержит изображение и продолжительность, связанные с этим изображением.

Реализация

Способ, которым я реализую анимацию, выглядит следующим образом:

Player.java

// Images for each animation
private BufferedImage[] walkingLeft = {Sprite.getSprite(0, 1), Sprite.getSprite(2, 1}; // Gets the upper left images of my sprite sheet
private BufferedImage[] walkingRight = {Sprite.getSprite(0, 2), Sprite.getSprite(2, 2};
private BufferedImage[] standing = {Sprite.getSprite(1, 0)};

// These are animation states
private Animation walkLeft = new Animation(walkingLeft, 10);
private Animation walkRight = new Animation(walkingRight, 10);
private Animation standing = new Animation(standing, 10);

// This is the actual animation
private Animation animation = standing;

В вашем методе обновления или тика у вас будет:

animation.update();

В способе рендеринга или рисования вы будете иметь:

g.drawImage(animation.getSprite(), x, y, null);

Допустим, вы внедрили MouseListener

public void mousePressed(MouseEvent e) {
    animation = walkLeft;
    animation.start();
}

public void mouseReleased(MouseEvent e) {
    animation.stop();
    animation.reset();
    animation = standing;
}

Примечания к закрытию

Вот скриншот макета листа спрайтов.

введите описание изображения здесь>> </p>

<p> Каждая плитка имеет 32 x 32 пикселя. </p>

<p> Обычно я бы не писал этот код. Тем не менее, я помню, когда я изо всех сил пытался понять это, и это раздражало меня от дерьма ... Итак, вот и вы! </p>

<p> Удачи, и я надеюсь, что вы сможете реорганизовать его в соответствии со своими потребностями:) </p></body></html>

ответил Savlon 12 AMpFri, 12 Apr 2013 10:57:11 +040057Friday 2013, 10:57:11

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132