Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java游戏:如何使动画只循环一次,而不受控制?_Java - Fatal编程技术网

Java游戏:如何使动画只循环一次,而不受控制?

Java游戏:如何使动画只循环一次,而不受控制?,java,Java,我一直在做一个2d游戏,我想我已经把如何制作一个只循环一次的动画复杂化了。例如,如果用户按下“a”键,角色的“攻击”变量设置为true,则游戏将持续循环地将动画精灵图像渲染到屏幕上,直到释放该键。问题是,我希望攻击动画只发生一次,无论是按住“a”键0.001秒还是1分钟 我觉得解决方案就像在渲染动画的最后一个精灵帧时将变量设置为false一样简单。并且仅当该变量为真且控制被按下时,才会渲染动画。这是一个相当广泛的问题,可能有很多解决方案,所以如果我遗漏了任何细节,请告诉我。下面是一个代码示例,删

我一直在做一个2d游戏,我想我已经把如何制作一个只循环一次的动画复杂化了。例如,如果用户按下“a”键,角色的“攻击”变量设置为true,则游戏将持续循环地将动画精灵图像渲染到屏幕上,直到释放该键。问题是,我希望攻击动画只发生一次,无论是按住“a”键0.001秒还是1分钟

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

游戏类w/主:

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;
}
密钥管理器类:

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;
        }
    }
}
玩家1级:

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);
    }
}

你有没有看到这个问题在哪里可以从一群对游戏控制更有经验的人那里得到答案?我建议在你的动画类的勾选方法中,当你到达动画的末尾时,即索引超过了帧数,您需要重置索引并升起一个标志,以便根据需要不继续更改帧或绘制帧,然后需要动画类知道何时应该重新开始,尽管我没有Arkanon,但我将在那里发布此内容。我有一种感觉,这不是一个最好问的地方。