Java游戏:尽管控制被压低,如何让动画只循环一次?

时间:2014-09-21 20:04:02

标签: java

我一直在做一个2D游戏,我觉得我过度复杂化了如何让动画只循环一次。例如,如果用户按下' a'关键,角色的攻击'变量设置为true,然后游戏将不断地将动画精灵图像渲染到屏幕上,直到释放该键。问题是,我希望攻击动画只发生一次,无论是' a'按键保持0.001秒或1分钟。

我觉得解决方案就像在渲染动画的最后一个精灵帧时将变量设置为false一样简单。并且只有在该变量为true且控制被按下时才会呈现动画。这是一个非常广泛的问题(可能有很多解决方案),所以如果我遗漏任何细节,请告诉我。下面是一个代码示例,删除了所有内容,除了与1个玩家操作有关的内容(此示例中为攻击):

游戏类(w / main()):

public class Game extends Canvas implements Runnable{
    private static final long serialVersionUID = 1L;
    public static final int WIDTH = 1200, HEIGHT = 600, SCALE = 1;
    public static boolean running = false;
    public Thread gameThread;

private BufferedImage p1AttackSpriteSheet;
private ImageManager im;

private static Player1 player1;

public void init(){
    ImageLoader loader = new ImageLoader();

    //Prepare sprite sheets (the loading takes some time...)
    p1AttackSpriteSheet = loader.load("/player1/attackSpriteSheet.png");
    SpriteSheet SS1 = new SpriteSheet(p1AttackSpriteSheet);

    im = new ImageManager(SS1);

    player1 = new Player1(-50, 200, im);
}

public synchronized void start() {
    if(running)return;
    running = true;
    gameThread = new Thread(this);
    gameThread.start();
}

public synchronized void stop() {
    if(!running)return;
    running = false;
    try {
        gameThread.join();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public void run() {

    // Credit for this run loop goes to MadProgrammer @ StackOverflow
    init();
    final long amountOfTicks = 60;
    long ns = Math.round(1_000_000_000 / (double)amountOfTicks);

    int frames = 0;
    long frameStart = System.currentTimeMillis();

    while (running) {
        long startedAt = System.nanoTime();
        tick();
        render();
        long completedAt = System.nanoTime();
        long duration = completedAt - startedAt;

        long frameEnd = System.currentTimeMillis();
        if (frameEnd - frameStart >= 1000) {
            System.out.println(frames);    //Take this out for final version
            frames = 0;
            frameStart = System.currentTimeMillis();
        } else {
            frames++;
        }

        long rest = ns - duration;
        if (rest > 0) {
            rest = TimeUnit.MILLISECONDS.convert(rest, TimeUnit.NANOSECONDS);
            try {
                Thread.sleep(rest);
            } catch (InterruptedException ex) {
            }
        }
    }
    stop();
}

public void tick() {
    player1.tick();
}

public void render() {

    BufferStrategy bs = this.getBufferStrategy();
    if(bs == null)
    {
        createBufferStrategy(3); //Use 5 at most
        return;
    }
    Graphics g = bs.getDrawGraphics();

    //RENDER HERE
    player1.render(g);
    //END RENDER

    g.dispose();
    bs.show();
}

public static void main(String[] args)
{
    JLabel controlKeyPanel;

    Game game = new Game();
    game.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));

    JFrame frame = new JFrame("-");
    frame.setResizable(false);
    frame.setSize(WIDTH * SCALE, HEIGHT * SCALE);
    frame.setLayout(new BorderLayout());

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(game);

    frame.setVisible(true);

    game.start();
}

public static Player1 getPlayer1() {
    return player1;
}

public static Player2 getPlayer2() {
    return player2;
}

KeyManager类:

public class KeyManager implements KeyListener{

    public void keyPressed(KeyEvent e) {

        int keyCode = e.getKeyCode();

        if(keyCode == KeyEvent.VK_A) //P1 Attack
        {
            Game.getPlayer1().attack1 = true;
        }
    }

    public void keyReleased(KeyEvent e) {

        int keyCode = e.getKeyCode();

        if(keyCode == KeyEvent.VK_C) //P1 Attack
        {
            Game.getPlayer1().attack1 = false;
        }
    }
}

Player1类:

public class Player1 {

private ImageManager im;
public boolean attack1 = false;
private int x1, y1;

private Animation P1AttackLeftAnimation;

public Player1(int x, int y, ImageManager im) {
    this.x1 = x;
    this.y1 = y;
    this.im = im;

    P1AttackLeftAnimation = new Animation(im.player1AttackLeft, 20);
}

public void tick() {

    P1AttackLeftAnimation.tick();
}

public void render(Graphics g) {

    if(attack1)
    {
        P1AttackLeftAnimation.render(g, x1, y1, 400 * Game.SCALE, 400 * Game.SCALE);
    }
}
}

动画类:

public class Animation {

    private BufferedImage[] images;
    private int interval, index;
    private long timer, now, lastTime;

    public Animation(BufferedImage[] images, int interval) {
        this.images = images;
        this.interval = interval;
        index = 0;
        timer = 0;
        now = 0;
        lastTime = System.currentTimeMillis();
    }

    public void tick() {
        now = System.currentTimeMillis();
        timer += now - lastTime;
        lastTime = now;

        if(timer >= interval)
        {
            index++;
            timer = 0;

            if(index >= images.length)
            {
                index = 0;
            }
        }
    }

    public void render(Graphics g, int x, int y, int width, int height) {

        g.drawImage(images[index], x, y, width, height, null);
    }
}

ImageManager类:

public class ImageManager {

public BufferedImage [] player1AttackLeft;


public ImageManager(SpriteSheet ss1) {

    //Player 1 Attack images
    player1AttackLeft = new BufferedImage[12];
        player1AttackLeft[0] = ss1.crop(0, 0, 400, 400);
        player1AttackLeft[1] = ss1.crop(1, 0, 400, 400);
        player1AttackLeft[2] = ss1.crop(2, 0, 400, 400);
        player1AttackLeft[3] = ss1.crop(3, 0, 400, 400);
        player1AttackLeft[4] = ss1.crop(4, 0, 400, 400);
        player1AttackLeft[5] = ss1.crop(5, 0, 400, 400);
        player1AttackLeft[6] = ss1.crop(6, 0, 400, 400);
        player1AttackLeft[7] = ss1.crop(7, 0, 400, 400);
        player1AttackLeft[8] = ss1.crop(8, 0, 400, 400);
        player1AttackLeft[9] = ss1.crop(9, 0, 400, 400);
        player1AttackLeft[10] = ss1.crop(10, 0, 400, 400);
        player1AttackLeft[11] = ss1.crop(11, 0, 400, 400);
}
}

SpriteSheet类:

public class SpriteSheet {

    private BufferedImage sheet;

    public SpriteSheet(BufferedImage sheet) {
        this.sheet = sheet;
    }

    public BufferedImage crop(int col, int row, int w, int h) {
        return sheet.getSubimage(col * 400, row * 400, w, h);
    }
}

0 个答案:

没有答案