我遇到了一个问题,我暂时找不到任何解决办法,即使是在网上搜索。
我目前正在工作的2D游戏,我希望我的球员去每一个方向和对角线。由于这个原因,我需要从键盘上得到两个输入,我可以编写代码,但现在我的问题是,当我按下第二个键时,我有一个轻微的延迟,我的球员不能移动。这是非常恼人的,因为当我改变我的方向时,运动一点也不平稳。在这里,我的班级管理所有的输入。提前谢谢你的帮助。
public class Input
{
private static final Input INSTANCE = new Input();
public final static float PI = (float) 3.141592;
public final static float P2 = (float) (PI/2);
private double x = Jeu.Isaac.getDeplacement().getHit().getEntity().getX();
private double y = Jeu.Isaac.getDeplacement().getHit().getEntity().getY();
private double a = Jeu.Isaac.getDeplacement().getA();
private final int[] listeInput = {GLFW.GLFW_KEY_A, GLFW.GLFW_KEY_D, GLFW.GLFW_KEY_W, GLFW.GLFW_KEY_S,
GLFW.GLFW_KEY_UP, GLFW.GLFW_KEY_DOWN, GLFW.GLFW_KEY_RIGHT, GLFW.GLFW_KEY_LEFT};
private double speed = 5.85;
public void drawBalle()
{
Jeu.Isaac.getMunitions().drawBalle();
}
public DeplacerPersonnage getPlayerMove() {
return Jeu.Isaac.getDeplacement();
}
private GLFWKeyCallback keyboard;
private HashMap<Integer, Boolean> mappageTouches;
private Input()
{
mappageTouches = new HashMap<Integer, Boolean>();
for(int key:listeInput)
{
mappageTouches.put(key, false);
}
keyboard = new GLFWKeyCallback()
{
@Override
public void invoke(long window, int key, int scancode, int action, int mods)
{
if(action == GLFW.GLFW_RELEASE)
{
mappageTouches.replace(key, false);
}
else if(action == GLFW.GLFW_PRESS)
{
System.out.println("Pressed");
mappageTouches.replace(key, true);
getAWSDkeys();
getShotsKeys();
}
else
{
System.out.println("hold");
getAWSDkeys();
getShotsKeys();
}
}
};
}
public void getAWSDkeys()
{
for(Integer key:listeInput)
{
if(mappageTouches.get(key))
{
switch(key)
{
case GLFW.GLFW_KEY_A:
a = PI;
if(!Jeu.Isaac.getDeplacement().getHit().isQCollision()) x -= speed;
Jeu.Isaac.getDeplacement().update(x, y, a);
Jeu.Isaac.getDeplacement().drawPlayer();
break;
case GLFW.GLFW_KEY_D:
a = 0;
if(!Jeu.Isaac.getDeplacement().getHit().isDCollision()) x += speed;
Jeu.Isaac.getDeplacement().update(x, y, a);
Jeu.Isaac.getDeplacement().drawPlayer();
break;
case GLFW.GLFW_KEY_W:
a = PI/2;
if(!Jeu.Isaac.getDeplacement().getHit().isZCollision()) y += speed;
Jeu.Isaac.getDeplacement().update(x, y, a);
Jeu.Isaac.getDeplacement().drawPlayer();
break;
case GLFW.GLFW_KEY_S:
a = 3*(PI/2);
if(!Jeu.Isaac.getDeplacement().getHit().isSCollision()) y -= speed;
Jeu.Isaac.getDeplacement().update(x, y, a);
Jeu.Isaac.getDeplacement().drawPlayer();
break;
}
}
}
}
public void getShotsKeys()
{
for(Integer key:listeInput)
{
if(mappageTouches.get(key))
{
switch(key)
{
case GLFW.GLFW_KEY_UP:
Jeu.Isaac.getMunitions().addBalle(new Balle(1, 1, Jeu.Isaac.getDeplacement().getHit().getEntity().getX(), Jeu.Isaac.getDeplacement().getHit().getEntity().getY(), 3));
break;
case GLFW.GLFW_KEY_DOWN:
Jeu.Isaac.getMunitions().addBalle(new Balle(1, 1, Jeu.Isaac.getDeplacement().getHit().getEntity().getX(), Jeu.Isaac.getDeplacement().getHit().getEntity().getY(), 4));
break;
case GLFW.GLFW_KEY_RIGHT:
Jeu.Isaac.getMunitions().addBalle(new Balle(1, 1, Jeu.Isaac.getDeplacement().getHit().getEntity().getX(), Jeu.Isaac.getDeplacement().getHit().getEntity().getY(), 2));
break;
case GLFW.GLFW_KEY_LEFT:
Jeu.Isaac.getMunitions().addBalle(new Balle(1, 1, Jeu.Isaac.getDeplacement().getHit().getEntity().getX(), Jeu.Isaac.getDeplacement().getHit().getEntity().getY(), 1));
break;
}
}
}
}
public static Input getInstance()
{
return INSTANCE;
}
public void init(long window)
{
glfwSetKeyCallback(window, keyboard);
}
}发布于 2021-12-11 17:21:37
问题是,您的输入处理逻辑,比如通过x (在getAWSDkeys()中)递增您的x += speed;变量,只有在操作系统为您的键盘发送窗口事件消息时才执行。这种情况只发生在KEY_DOWN、KEY_UP和KEY_REPEAT事件中。而且,是的,当您按下并按住相同的键时,KEY_DOWN和KEY_REPEAT事件之间会有延迟。
为了解决这个问题,您只需将游戏逻辑(如前面提到的x或y变量的增量/减少)移出键事件处理程序。
通常,您有一个游戏循环,它也调用glfwPollEvents() (如果您将输入/窗口事件处理与呈现解耦,则调用glfwWaitEvents() )。
因此,您的键盘事件处理程序函数应该只为每个可能的键设置一些布尔标志,指示该键现在已按下/按下或向上/释放。在游戏/输入循环中,您只需查询布尔标志的状态并相应地在其中执行x/y增量/递减操作。
您也可以使用glfwGetKey()函数,而不是为所有键(无论是down/up )存储自己的布尔标志。但是,请注意,这个函数并不查询当前的键状态,而是返回缓存的密钥状态( GLFW的缓存侧),在调用glfwPollEvents()/glfwWaitEvents()时,GLFW会在内部设置/记住该状态。请参阅:钥匙
此函数只返回缓存的键事件状态。它不对系统轮询密钥的当前物理状态。
简而言之:问题在于您的游戏逻辑在窗口事件消息回调(当操作系统向进程/游戏发送键盘事件时由glfwPollEvents/glfwWaitEvents调用)。您必须将输入事件的处理与实际的游戏逻辑解耦。
发布于 2022-01-03 15:10:41
很抱歉我迟到了,我很忙。
我最终解决了我的问题,那就是回调逻辑。我删除了所有内容,并且直接使用glfwGetKey(),并且它成功了。
这是我做的代码,如果它能帮助一些人。
public class Input
{
private static final Input INSTANCE = new Input();
public final static float PI = (float) 3.141592;
public final static float P2 = (float) (PI/2);
private double x = Jeu.Isaac.getPosition().getY();
private double y = Jeu.Isaac.getPosition().getX();
private double a = Jeu.Isaac.getA();
private final int[] listeInput = {GLFW.GLFW_KEY_A, GLFW.GLFW_KEY_D, GLFW.GLFW_KEY_W, GLFW.GLFW_KEY_S, GLFW.GLFW_KEY_I, GLFW.GLFW_KEY_L, GLFW.GLFW_KEY_K, GLFW.GLFW_KEY_P,GLFW.GLFW_KEY_O,
GLFW.GLFW_KEY_SPACE, GLFW.GLFW_KEY_UP, GLFW.GLFW_KEY_DOWN, GLFW.GLFW_KEY_RIGHT, GLFW.GLFW_KEY_LEFT};
private double speed = 5.85;
public void drawBalle()
{
Jeu.Isaac.getMunitions().drawBalle();
}
public Personnage getPlayerMove() {
return Jeu.Isaac;
}
private GLFWKeyCallback keyboard;
//private HashMap<Integer, Boolean> mappageTouches;
private Input()
{
/*mappageTouches = new HashMap<Integer, Boolean>();
for(int key:listeInput)
{
mappageTouches.put(key, false);
}*/
/*keyboard = new GLFWKeyCallback()
{
@Override
public void invoke(long window, int key, int scancode, int action, int mods)
{
if(glfwGetKey(window, key) == GLFW_PRESS)
{
System.out.println("Pressed");
getAWSDkeys(window);
getShotsKeys(window);
}
if(glfwGetKey(window, key) == GLFW_RELEASE)
{
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_FALSE);
System.out.println("Released");
}
}
};*/
}
public void deplacement()
{
for(Integer key:listeInput)
{
checkDeplacement(Fenetre.getInstance().getWindow(), key);
}
Jeu.Isaac.updateGameObject();
}
public void tire()
{
for(Integer key:listeInput)
{
checkTire(Fenetre.getInstance().getWindow(), key);
}
}
/**
* Méthode qui vérifie si une touche a été pressée.
* Si oui renvoie vers la méthode getAWSDkeys(window).
* Si non, définie l'entrée rémanente à faux.
* @param window
* La fenêtre active.
* @param key
* La touche détectée à vérifier.
*/
public void checkDeplacement(long window, int key)
{
if(glfwGetKey(window, key) == GLFW_PRESS)
{
// System.out.println("Pressed");
getAWSDkeys(window);
}
if(glfwGetKey(window, key) == GLFW_RELEASE)
{
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_FALSE);
// System.out.println("Released");
}
}
public void checkTire(long window, int key)
{
if(glfwGetKey(window, key) == GLFW_PRESS)
{
// System.out.println("Pressed");
getShotsKeys(window);
}
if(glfwGetKey(window, key) == GLFW_RELEASE)
{
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_FALSE);
// System.out.println("Released");
}
}
public void moveUp()
{
if(!Jeu.Isaac.getHitbox().isZCollision()) {
Jeu.Isaac.goUpNext();
}
Jeu.Isaac.setA(PI/2);
Jeu.Isaac.drawPlayer();
}
public void moveDown()
{
if(!Jeu.Isaac.getHitbox().isSCollision()) {
Jeu.Isaac.goDownNext();
}
Jeu.Isaac.setA(3*PI/2);
Jeu.Isaac.drawPlayer();
}
public void moveRight()
{
a = 0;
if(!Jeu.Isaac.getHitbox().isDCollision()) {
Jeu.Isaac.goRightNext();
}
Jeu.Isaac.setA(0);
Jeu.Isaac.drawPlayer();
}
public void moveLeft()
{
a = PI;
if(!Jeu.Isaac.getHitbox().isQCollision()) {
Jeu.Isaac.goLeftNext();
}
Jeu.Isaac.setA(PI);
Jeu.Isaac.drawPlayer();
}
public void poseBomb() {
ObjetsInventaire bomb = new ObjetsInventaire(-1, 100, 100, Jeu.gameWorld.getPlayer().getPosition(), "");
}
public void shootUp()
{
Jeu.Isaac.getMunitions().addBalle(new Balle(25, 25, Jeu.Isaac.getPosition().getX(), Jeu.Isaac.getPosition().getY(), new Vector2(0, 1), "", 10));
Jeu.gameWorld.getPlayer().setFace(1);
}
public void shootDown()
{
Jeu.Isaac.getMunitions().addBalle(new Balle(25, 25, Jeu.Isaac.getPosition().getX(), Jeu.Isaac.getPosition().getY(), new Vector2(0, -1), "", 10));
Jeu.gameWorld.getPlayer().setFace(2);
}
public void shootRight()
{
Jeu.Isaac.getMunitions().addBalle(new Balle(25, 25, Jeu.Isaac.getPosition().getX(), Jeu.Isaac.getPosition().getY(), new Vector2(1, 0), "", 10));
Jeu.gameWorld.getPlayer().setFace(3);
}
public void shootLeft()
{
Jeu.Isaac.getMunitions().addBalle(new Balle(25, 25, Jeu.Isaac.getPosition().getX(), Jeu.Isaac.getPosition().getY(), new Vector2(-1, 0), "", 10));
Jeu.gameWorld.getPlayer().setFace(4);
}
public void getAWSDkeys(long window)
{
if(glfwGetKey(window, GLFW_KEY_W) == GLFW.GLFW_PRESS)
{
moveUp();
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
}
if(glfwGetKey(window, GLFW_KEY_S) == GLFW.GLFW_PRESS)
{
moveDown();
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
}
if(glfwGetKey(window, GLFW_KEY_D) == GLFW.GLFW_PRESS)
{
moveRight();
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
}
if(glfwGetKey(window, GLFW_KEY_A) == GLFW.GLFW_PRESS)
{
moveLeft();
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
}
if(glfwGetKey(window, GLFW_KEY_L) == GLFW.GLFW_PRESS)
{
Jeu.gameWorld.getPlayer().setSpeed(20);
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
}
if(glfwGetKey(window, GLFW_KEY_I) == GLFW.GLFW_PRESS)
{
Jeu.gameWorld.getPlayer().setInvincible(true);
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
}
if(glfwGetKey(window, GLFW_KEY_K) == GLFW.GLFW_PRESS)
{
Jeu.gameWorld.getMapEnCours().setListeEnnemi(new listeEnnemi());
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
}
if(glfwGetKey(window, GLFW_KEY_P) == GLFW.GLFW_PRESS)
{
Jeu.gameWorld.getPlayer().setDegat(Integer.MAX_VALUE);
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
}
if(glfwGetKey(window, GLFW_KEY_O) == GLFW.GLFW_PRESS)
{
Jeu.gameWorld.getPlayer().setCoin(Jeu.gameWorld.getPlayer().getCoin() + 10); //TODO pas fini
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
}
if(glfwGetKey(window, GLFW_KEY_SPACE) == GLFW.GLFW_PRESS)
{
poseBomb();
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
}
}
public void getShotsKeys(long window)
{
if(glfwGetKey(window, GLFW_KEY_UP) == GLFW.GLFW_PRESS)
{
shootUp();
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
}
if(glfwGetKey(window, GLFW_KEY_DOWN) == GLFW.GLFW_PRESS)
{
shootDown();
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
}
if(glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW.GLFW_PRESS)
{
shootRight();
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
}
if(glfwGetKey(window, GLFW_KEY_LEFT) == GLFW.GLFW_PRESS)
{
shootLeft();
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
}
}
public void init(long window)
{
}
public static Input getInstance() {
return INSTANCE;
}
}```https://stackoverflow.com/questions/70314753
复制相似问题