【问题标题】:How to use/invoke KeyEvents from main class to use in sub class如何从主类使用/调用 KeyEvents 以在子类中使用
【发布时间】:2018-05-15 05:40:41
【问题描述】:

好吧,基本上我已经在主类中设置了这些关键事件:https://prnt.sc/jhbxz9

我在这里尝试完成的是使用在我的主类中设置的这些关键事件,这样我就可以在我的子类(播放器)的 peformAction 下编写一个带有 if/else 语句的方法,以使播放器在按下键时移动并且释放时停止移动。目前我所能做的就是始终向一个方向移动直到它离开屏幕而不需要按下任何键,但我希望它在按下 VK_LEFT 时改变 velX 但我不知道如何参考到我的子类中的关键事件而不会破坏代码。最后一件事是我注意到每个关键事件下都有 setKey,这让我觉得我需要使用 setKeys,但仍然没有。

如果您不能被要求阅读所有代码,请使用完整的屏幕截图。 玩家类(子类):http://prntscr.com/jhbx58 + http://prntscr.com/jhbxim

GameManager 类(主类):http://prntscr.com/jhbxz9

GameManager 类:

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.JFrame;

public class GameManager extends JFrame implements KeyListener {

    private int canvasWidth;
    private int canvasHeight;
    private int borderLeft;
    private int borderTop;
    private BufferedImage canvas;
    private Stage stage;
    private Enemy[] enemies;
    private Player player;
    private Goal goal;
    private Graphics gameGraphics;
    private Graphics canvasGraphics;
    private int numEnemies;
    private boolean continueGame;

    public static void main(String[] args) {
// During development, you can adjust the values provided in the brackets below
// as needed. However, your code must work with different/valid combinations
// of values.
        GameManager managerObj = new GameManager(1920, 1280, 30);
    }

    public GameManager(int preferredWidth, int preferredHeight, int maxEnemies) {
        this.borderLeft = getInsets().left;
        this.borderTop = getInsets().top;
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        if (screenSize.width < preferredWidth) {
            this.canvasWidth = screenSize.width - getInsets().left - getInsets().right;
        } else {
            this.canvasWidth = preferredWidth - getInsets().left - getInsets().right;
        }
        if (screenSize.height < preferredHeight) {
            this.canvasHeight = screenSize.height - getInsets().top - getInsets().bottom;
        } else {
            this.canvasHeight = preferredHeight - getInsets().top - getInsets().bottom;
        }
        setSize(this.canvasWidth, this.canvasHeight);
        setResizable(false);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
        addKeyListener(this);
        Random rng = new Random(2);
        this.canvas = new BufferedImage(this.canvasWidth, this.canvasHeight, BufferedImage.TYPE_INT_RGB);
// Create a Stage object to hold the background images
        this.stage = new Stage();
// Create a Goal object with its initial x and y coordinates
        this.goal = new Goal(this.canvasWidth / 2, Math.abs(rng.nextInt()) % this.canvasHeight);
// Create a Player object with its initial x and y coordinates
        this.player = new Player(this.canvasWidth - (Math.abs(rng.nextInt()) % (this.canvasWidth / 2)),
                (Math.abs(rng.nextInt()) % this.canvasHeight));
// Create the Enemy objects, each with a reference to this (GameManager) object
// and their initial x and y coordinates.
        this.numEnemies = maxEnemies;
        this.enemies = new Enemy[this.numEnemies];
        for (int i = 0; i < this.numEnemies; i++) {
            this.enemies[i] = new Enemy(this, Math.abs(rng.nextInt()) % (this.canvasWidth / 4),
                    Math.abs(rng.nextInt()) % this.canvasHeight);
        }
        this.gameGraphics = getGraphics();
        this.canvasGraphics = this.canvas.getGraphics();
        this.continueGame = true;
        while (this.continueGame) {
            updateCanvas();
        }
        this.stage.setGameOverBackground();
        updateCanvas();
    }

    public void updateCanvas() {
        long start = System.nanoTime();
// If the player is alive, this should move the player in the direction of the
// key that has been pressed
// Note: See keyPressed and keyReleased methods in the GameManager class.
        this.player.performAction();
// If the enemy is alive, the enemy must move towards the goal. The goal object
// is obtained
// via the GameManager object that is given at the time of creating an Enemy
// object.
// Note: The amount that the enemy moves by must be much smaller than that of
// the player above
// or else the game becomes too hard to play.
        for (int i = 0; i < this.numEnemies; i++) {
            this.enemies[i].performAction();
        }
        if ((Math.abs(this.goal.getX() - this.player.getX()) < (this.goal.getCurrentImage().getWidth() / 2))
                && (Math.abs(this.goal.getY() - this.player.getY()) < (this.goal.getCurrentImage().getWidth()
                / 2))) {
            for (int i = 0; i < this.numEnemies; i++) {
// Sets the image of the enemy to the "dead" image and sets its status to
// indicate dead
                this.enemies[i].die();
            }
// Sets the image of the enemy to the "dead" image and sets its status to
// indicate dead
            this.goal.die();
// Sets the background of the stage to the finished game background.
            this.stage.setGameOverBackground();
            this.continueGame = false;
        }
// If an enemy is close to the goal, the player and goal die
        int j = 0;
        while (j < this.numEnemies) {
            if ((Math.abs(this.goal.getX() - this.enemies[j].getX()) < (this.goal.getCurrentImage().getWidth() / 2))
                    && (Math.abs(this.goal.getY() - this.enemies[j].getY())
                    < (this.goal.getCurrentImage().getWidth() / 2))) {
                this.player.die();
                this.goal.die();
                this.stage.setGameOverBackground();
                j = this.numEnemies;
                this.continueGame = false;
            }
            j++;
        }
        try {
// Draw stage
            this.canvasGraphics.drawImage(stage.getCurrentImage(), 0, 0, null);
// Draw player
            this.canvasGraphics.drawImage(player.getCurrentImage(),
                    this.player.getX() - (this.player.getCurrentImage().getWidth() / 2),
                    this.player.getY() - (this.player.getCurrentImage().getHeight() / 2), null);
// Draw enemies
            for (int i = 0; i < this.numEnemies; i++) {
                this.canvasGraphics.drawImage(this.enemies[i].getCurrentImage(),
                        this.enemies[i].getX() - (this.enemies[i].getCurrentImage().getWidth() / 2),
                        this.enemies[i].getY() - (this.enemies[i].getCurrentImage().getHeight()
                        / 2), null);
            }
// Draw goal
            this.canvasGraphics.drawImage(this.goal.getCurrentImage(),
                    this.goal.getX() - (this.goal.getCurrentImage().getWidth() / 2),
                    this.goal.getY() - (this.goal.getCurrentImage().getHeight() / 2), null);
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
// Draw everything.
        this.gameGraphics.drawImage(this.canvas, this.borderLeft, this.borderTop, this);
        long end = System.nanoTime();
        this.gameGraphics.drawString("FPS: " + String.format("%2d", (int) (1000000000.0 / (end - start))),
                this.borderLeft + 50, this.borderTop + 50);
    }

    public Goal getGoal() {
        return this.goal;
    }

    public void keyPressed(KeyEvent ke) {
// Below, the setKey method is used to tell the Player object which key is
// currently pressed.
// The Player object must keep track of the pressed key and use it for
// determining the direction
// to move.
        if (ke.getKeyCode() == KeyEvent.VK_LEFT) {
            this.player.setKey('L', true);
        }
        if (ke.getKeyCode() == KeyEvent.VK_RIGHT) {
            this.player.setKey('R', true);
        }
        if (ke.getKeyCode() == KeyEvent.VK_UP) {
            this.player.setKey('U', true);
        }
        if (ke.getKeyCode() == KeyEvent.VK_DOWN) {
            this.player.setKey('D', true);
        }
        if (ke.getKeyCode() == KeyEvent.VK_ESCAPE) {
            this.continueGame = false;
        }
    }

    @Override
    public void keyReleased(KeyEvent ke) {
// Below, the setKey method is used to tell the Player object which key is
// currently released.
// The Player object must keep track of the pressed key and use it for
// determining the direction
// to move.
        if (ke.getKeyCode() == KeyEvent.VK_LEFT) {
            this.player.setKey('L', false);
        }
        if (ke.getKeyCode() == KeyEvent.VK_RIGHT) {
            this.player.setKey('R', false);
        }
        if (ke.getKeyCode() == KeyEvent.VK_UP) {
            this.player.setKey('U', false);
        }
        if (ke.getKeyCode() == KeyEvent.VK_DOWN) {
            this.player.setKey('D', false);
        }
    }

    @Override
    public void keyTyped(KeyEvent ke) {
    }
}

我的玩家类(子类):

import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class Player {

private BufferedImage imageRunning;
private BufferedImage imageOver;
private BufferedImage imageCurrent;
int valx = 500;
int valy = 100;


public Player(int valx, int valy) {

    try {
        this.imageRunning = ImageIO.read(new File("C:/Users/HUS/Desktop/Assigment222/images/player-alive.png"));
        this.imageOver = ImageIO.read(new File("C:/Users/HUS/Desktop/Assigment222/images/player-dead.png"));
    } catch (IOException e) {
        e.printStackTrace();
    }
    this.imageCurrent = this.imageRunning;
}

public BufferedImage getCurrentImage() {
    return this.imageCurrent;
}

public void setGameOverBackground() {
    this.imageCurrent = this.imageOver;
}

public void performAction() {
    if(Player.setKey('D', true) == true) {
        this.valx += 2;
    }
    else if(Player.setKey('D', false) == false) {
        this.valx = 0;
    }
    return;
}

public int getX() {
    return valx;
}

public int getY() {
    return valy;
}

public void die() {
    return;

}

public static boolean setKey(char c, boolean b) {
    return b;


}

}

【问题讨论】:

  • 作为建议,处理运动可能不是玩家的责任,而更多的是“主循环”。但是,如果您想让玩家这样做,那么您应该传入当前的“输入状态”(可能还有玩家可以进入的边界),但我再说一遍,我不相信这是域播放器
  • 作为扩展,不要将“输入状态”存储在 Player 中,将其存储在“输入模型”中 - 这确实应该独立于 Player(因为您可能想稍后添加鼠标输入,例如)
  • @MadProgrammer 嘿,感谢您抽出宝贵时间回复,我还应该在上面提到这是交给我的工作,我被告知不要更改主类中的任何内容,这也是这个游戏的目标是让玩家在敌人类追逐目标的当前位置时使用关键事件向目标移动(我现在正在研究的部分)。我也不是那么了解java,我真的不明白你传递当前“输入状态”或存储输入模型的意思,尽管我会确保现在阅读这些内容并希望有好消息回复你
  • @MadProgrammer 我也只需要这个游戏的箭头键,不支持鼠标或控制器。如果您很忙但介意将我链接到输入模型或输入状态的示例或教程,也可以忽略最后一部分?似乎找不到太多与 java 相关的东西,或者只是我想找什么,哈哈。再次感谢您抽出宝贵时间回复
  • ????把它还给我……好吧,说真的。 performAction 没有足够的信息或执行边界检查(你怎么知道你什么时候移动到很远的地方?)。但是,setKey 应该存储指定char 的状态,可能在MapSet 中。然后performAction 应该检查MapSet 是否包含特定字符(在Map 的情况下,它是活动的/true)并执行所需的操作

标签: java call invoke keyevent


【解决方案1】:

所以当keyPressedkeyReleased 被调用时,它们会依次调用Player.setKey。当它被调用时,你存储状态。

例如...

public class Player {

    //...

    // I really, really, really don't static been used this way, it
    // has a bad code smell about it...
    public static Set<Character> inputState = new TreeSet<Character>();

    //...

    public static void setKey(char c, boolean b) {
        if (b) {
            inputState.add(c);
        } else {
            inputState.remove(c);
        }
    }

}

所以,这实际上就是将char 添加到Set 或删除它。因为Set保证了唯一性,所以我们不需要关心这个键是否已经被按下了。

然后当调用performAction 时,您检查输入是否在Set 中并采取适当的措施...

public void performAction() {
    if (inputState.contains('U')) {
        // Going up
    } else if (inputState.contains('D')) {
        // Going down
    }
    //... other inputs
}

【讨论】:

  • 嘿,谢谢,我刚刚试了一下,但我似乎遇到了“inputState.add(c);”的语法错误“.add”似乎是错误。关于为什么会发生这种情况的任何想法?或者你可以推荐我阅读/谷歌以了解更多关于 set 的信息?顺便说一句,这是错误消息:prntscr.com/ji0pbp
  • 你事先定义了 inputState 吗?你在用 java.util.Set
  • 是的,我相信我做得对,这是一个屏幕截图,以防万一:prntscr.com/ji0sw9
  • 您使用的是什么版本的 Java? (Ps 我在发布代码之前对其进行了测试,以使其按我认为应该的方式工作)
  • 嗯,我有 Java 8 Update 151(64 位)和 Java SE Development Kit 8 Update 151(64 位)。我也在使用 Eclipse Java Oxygen(4 个月前重新下载了它,所以它相当新)顺便说一句,感谢您对代码进行测试,这意味着很多知道这是正确的代码,我只需要让它在我的最终工作:P
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-19
相关资源
最近更新 更多