玩家移动问题(Java Graphics 2D)

问题描述 投票:0回答:1

我无法让角色在跳跃前和跳跃后做他正在做的事情。 有一个 keyReleased 方法来接收最后按下的释放键,这个方法的意思是,例如我按下 D 和 SPACE 向右跳转,然后我释放 SPACE 和 D 被程序忘记。因此,在释放按键以恢复该动作之前,我无法知道角色在做什么。

我是巴西人,所以一些变量将是葡萄牙语

普拉:跳跃

pulou:跳起来

图像:图像

botaoPressionado:按下按键

moveParaADireita:向右移动

moveParaAEsquerda:向左移动

agacha:蹲下

comeceEsseMovimento:initThisMove

这是代码:

    private boolean blocked = false;

    private Player player;
    private int x, y, dx, dy;
    Image imagem;
    private int altura, largura;
    private boolean direita = false;
    private boolean esquerda = false;
    private final int GRAVITY = 1;
    private final int JUMP_FORCE = -20;
    private final int GROUND_Y = 750;
    private int yVel;

    boolean moving = false;

    public Player2() {
        x = 100;
        y = GROUND_Y;
        yVel = 0;

    }

    public void update() {
        x += dx;
        yVel += GRAVITY;
        y += yVel;

        if (y >= GROUND_Y) {
            y = GROUND_Y;
            yVel = 0;
        }
    }

    public void jump() {
        if (y == GROUND_Y) {
            yVel = JUMP_FORCE;
        }
    }

    public String listaDeMoves = null;
    private boolean movendo;
    private boolean block;
    private ArrayList<Movimento> listMoves = new ArrayList<>();


    void keyPressed(KeyEvent botaoPressionado) {

        switch (botaoPressionado.getKeyCode()) {
            case KeyEvent.VK_D:
                moveParaADireita();
                listMoves.add(new Movimento("andouParaADireita"));
                break;
            case KeyEvent.VK_A:
                moveParaAEsquerda();
                listMoves.add(new Movimento("andouParaAEsquerda"));
                break;
            case KeyEvent.VK_S:
                listMoves.add(new Movimento("agachou"));
                agacha();
                break;
            case KeyEvent.VK_W:
                nadaAinda();
                break;
            case KeyEvent.VK_SPACE:
                listMoves.add(new Movimento("pulou"));
                pula();
                break;
            case KeyEvent.VK_ESCAPE:
                Menu menu = new Menu();
                menu.setVisible(true);
                break;
        }

    }

    private void menu() {
        Menu menu = new Menu();
        menu.setVisible(true);
    }

    private void pula() {
        jump();
        moving = true;
        ImageIcon referencia = new ImageIcon("res\\Colour2//player//120x80_gifs//__Jump.gif");
        imagem = referencia.getImage();
    }

    private void agacha() {
        if (!moving) {
            ImageIcon referencia = new ImageIcon("res\\Colour2//player//120x80_gifs//__Crouch.gif");
            imagem = referencia.getImage();
            blocked = true;
        }
    }

    private void moveParaAEsquerda() {
        dx = -5;
        moving = true;
        ImageIcon referencia = new ImageIcon("res\\Colour2//player//120x80_gifs//__RunBehind.gif");
        imagem = referencia.getImage();
        direita = false;
        esquerda = true;
    }

    private void moveParaADireita() {
        dx = 5;
        moving = true;
        ImageIcon referencia = new ImageIcon("res\\Colour2//player//120x80_gifs//__RunNormal.gif");
        imagem = referencia.getImage();
        direita = true;
        esquerda = false;
    }


    public void keyReleased(KeyEvent botaoSoltado) {
        int tecla = botaoSoltado.getKeyCode();
//        ImageIcon referencia = new //ImageIcon("res\\Colour2//player//120x80_gifs//__Idle.gif");
//        imagem = referencia.getImage();
        blocked = false;
        moving = false;
        if(tecla == KeyEvent.VK_SPACE) {

        }else{
            dx = 0;
        }
    }

    private void comeceEsseMovimento(String movimentoAtual) {
        switch (movimentoAtual){
            case "andouParaADireita":
                moveParaADireita();
                break;
            case "andouParaAEsquerda":
                moveParaAEsquerda();
                break;
            case "pulou":
                pula();
                break;
            case "agachou":
                agacha();
                break;
        }
    }


    void load() {
        ImageIcon referencia = new ImageIcon("res\\Colour2//player//120x80_gifs//__Idle.gif");
        imagem = referencia.getImage();
        altura = imagem.getHeight(null);
        largura = imagem.getWidth(null);
    }

我尝试了几次验证,但没有成功。我尝试创建一个 arrayList 来接收所有所做的动作,当 KeyReleased 方法运行时,它会看到最后一个动作是什么而不是跳跃并运行该动作,但它不起作用,因为每次该方法运行时它都会运行这个动作而且它没有得到很好的验证,因此释放任何键时都会重复之前的任何动作。示例:我正在跳跃,所以我停止跳跃并开始行走。因此,当我释放行走按钮时,角色会跳跃,因为这就是他在行走之前所做的事情。

java 2d game-development
1个回答
0
投票

我喜欢你有一个行动列表的想法,但我们需要明智地维护它。

我推荐这种方法:

    Stack<KeyEvent> pressedKeyEvents = new Stack<>();

    @Override
    public void keyPressed(KeyEvent keyEvent) {
        pressedKeyEvents.add(keyEvent);

        // this is your preexisting logic. For this approach
        // to work it needs to be in a separate method:
        doKeyPressed(keyPressed);
    }

    @Override
    public void keyReleased(KeyEvent keyEvent) {
        pressedKeyEvents.removeIf(existingKeyEvent -> keyEvent.getKeyChar() == existingKeyEvent.getKeyChar());
        
        // insert your preexisting keyReleased logic here, it doesn't
        // matter if it's in a separate method or not
        
        if (!pressedKeyEvents.isEmpty()) {
            for (int i = pressedKeyEvents.size() - 1; i >= 0; i--) {
                KeyEvent activeEvent = pressedKeyEvents.get(i);
                if (activeEvent.getKeyChar() == ' ') {
                    // you probably don't want to reissue a jump event even
                    // if the user is still holding down the SPACE key?
                    continue;
                } else {
                    doKeyPressed(activeEvent);
                    break;
                }
            }
        }
    }

当您释放每个键时:我们将其从堆栈中删除。

但是当您释放某个键时:我们将重播最近按下的另一个键(如果存在)。我们可能需要忽略某些不应重复的击键(例如跳跃);您可以根据需要进行自定义。

您列举了两个需要关注的场景。您可以将它们编写为单独的单元测试。 (场景A:按下D,按下SPACE,松开SPACE,角色是否继续向右移动?场景B:按下SPACE,松开SPACE,按下D,松开D,角色是否停止移动?)

您也可以测试这个场景C:

  1. 按D(角色向右移动)
  2. 按A(角色向左移动)
  3. 释放A(角色向右移动)
  4. 释放D(角色停止)

(预期的行为是主观的;您也可以认为同时按下 D 和 A 应该会相互抵消。无论您期望什么行为:您都可以将其表达为单元测试,以便您的应用程序保持一致。)

© www.soinside.com 2019 - 2024. All rights reserved.