【LWJGL教程】四、输入处理

四、输入处理

  • 在LWJGL中,使用Set***Callback进行输入处理。以下是所有的输入处理(第一个参数为窗口,第二个为匿名函数),当用户进行如下操作时调用匿名函数

    GLFW.glfwSetWindowCloseCallback(window, null); // 窗口关闭
    GLFW.glfwSetWindowContentScaleCallback(window, null); // 窗口比例更改
    GLFW.glfwSetWindowFocusCallback(window, null); // 窗口获得焦点
    GLFW.glfwSetWindowIconifyCallback(window, null); // 窗口最小化
    GLFW.glfwSetWindowMaximizeCallback(window, null); // 窗口最大化
    GLFW.glfwSetWindowPosCallback(window, null); // 窗口坐标改变
    GLFW.glfwSetWindowRefreshCallback(window, null); // 窗口刷新
    GLFW.glfwSetWindowSizeCallback(window, null); // 窗口大小改变
    GLFW.glfwSetKeyCallback(window, null); // 按键按下
    GLFW.glfwSetCharCallback(window, null); // (受修饰符影响)字符输入
    GLFW.glfwSetCharModsCallback(window, null); // (不受修饰符影响)字符输入
    GLFW.glfwSetMouseButtonCallback(window, null); // 鼠标按下
    GLFW.glfwSetCursorPosCallback(window, null); // 鼠标指针位置改变
    GLFW.glfwSetCursorEnterCallback(window, null); // 鼠标指针进入窗口
    GLFW.glfwSetScrollCallback(window, null); // 窗口滚动
    GLFW.glfwSetDropCallback(window, null); // 文件拖入窗口
    
  • 在engine包下创建io包,并新建Input类和各抽象类

public GLFWWindowCloseCallback closeCallback;
public GLFWWindowContentScaleCallback contentScaleCallback;
public GLFWWindowFocusCallback focusCallback;
public GLFWWindowIconifyCallback iconifyCallback;
public GLFWWindowMaximizeCallback maximizeCallback;
public GLFWWindowPosCallback posCallback;
public GLFWWindowRefreshCallback refreshCallback;
public GLFWWindowSizeCallback sizeCallback;
public GLFWKeyCallback keyCallback;
public GLFWCharCallback charCallback;
public GLFWCharModsCallback charModsCallback;
public GLFWMouseButtonCallback mouseButtonCallback;
public GLFWCursorPosCallback cursorPosCallback;
public GLFWCursorEnterCallback cursorEnterCallback;
public GLFWScrollCallback scrollCallback;
public GLFWDropCallback dropCallback;
  • 在构造函数中实现这些类
public Input() {
    closeCallback = new GLFWWindowCloseCallback() {
        @Override
        public void invoke(long window) {
            // window 窗口
        }
    };
    contentScaleCallback = new GLFWWindowContentScaleCallback() {
        @Override
        public void invoke(long window, float xscale, float yscale) {
            // window 窗口 
            // xscale x方向的缩放
            // yscale y方向的缩放
        }
    };
    focusCallback = new GLFWWindowFocusCallback() {
        @Override
        public void invoke(long window, boolean focused) {
            // window 窗口 
            // focused 是否获得焦点
        }
    };
    iconifyCallback = new GLFWWindowIconifyCallback() {
        @Override
        public void invoke(long window, boolean iconified) {
            // window 窗口 
            // iconified 是否最小化
        }
    };
    maximizeCallback = new GLFWWindowMaximizeCallback() {
        @Override
        public void invoke(long window, boolean maximized) {
            // window 窗口 
            // maximized 是否最大化
        }
    };
    posCallback = new GLFWWindowPosCallback() {
        @Override
        public void invoke(long window, int xpos, int ypos) {
            // window 窗口 
            // xpos x坐标
            // ypos y坐标
        }
    };
    refreshCallback = new GLFWWindowRefreshCallback() {
        @Override
        public void invoke(long window) {
            // window 窗口 
        }
    };
    sizeCallback = new GLFWWindowSizeCallback() {
        @Override
        public void invoke(long window, int width, int height) {
            // window 窗口 
            // width 新宽度
            // height 新高度
        }
    };
    keyCallback = new GLFWKeyCallback() {
        @Override
        public void invoke(long window, int key, int scancode, int action, int mods) {
            // window 窗口 
            // key 按键类型
            // scancode 按键的系统专用扫描码
            // action 按下的模式(释放、按下、反复)
            // mods 修饰符
        }
    };
    charCallback = new GLFWCharCallback() {
        @Override
        public void invoke(long window, int codepoint) {
            // window 窗口
            // codepoint 字符unicode编码
        }
    };
    charModsCallback = new GLFWCharModsCallback() {
        @Override
        public void invoke(long window, int codepoint, int mods) {
            // window 窗口
            // codepoint 字符unicode编码
            // mods 修饰符
        }
    };
    mouseButtonCallback = new GLFWMouseButtonCallback() {
        @Override
        public void invoke(long window, int button, int action, int mods) {
            // window 窗口
            // button 鼠标按键类型
            // action 按下类型(释放、按下、反复)
            // mods 修饰符
        }
    };
    cursorPosCallback = new GLFWCursorPosCallback() {
        @Override
        public void invoke(long window, double xpos, double ypos) {

        }
    };
    cursorEnterCallback = new GLFWCursorEnterCallback() {
        @Override
        public void invoke(long window, boolean entered) {
            // window 窗口
            // entered 是否进入
        }
    };
    scrollCallback = new GLFWScrollCallback() {
        @Override
        public void invoke(long window, double xoffset, double yoffset) {
            // window 窗口
            // xoffset x偏移量
            // yoffset y偏移量
        }
    };
    dropCallback = new GLFWDropCallback() {
        @Override
        public void invoke(long window, int count, long names) {
            // window 窗口
            // count 文件数
            // names 名称
        }
    };
}
  • 在Window类中实例化Input,并创建createCallback方法以设置窗口回调
public Input Input = new Input();
public void createCallback() {
    GLFW.glfwSetWindowCloseCallback(window, input.closeCallback); // 窗口关闭
    GLFW.glfwSetWindowContentScaleCallback(window, input.contentScaleCallback); // 窗口比例更改
    GLFW.glfwSetWindowFocusCallback(window, input.focusCallback); // 窗口获得焦点
    GLFW.glfwSetWindowIconifyCallback(window, input.iconifyCallback); // 窗口最小化
    GLFW.glfwSetWindowMaximizeCallback(window, input.maximizeCallback); // 窗口最大化
    GLFW.glfwSetWindowPosCallback(window, input.posCallback); // 窗口坐标改变
    GLFW.glfwSetWindowRefreshCallback(window, input.refreshCallback); // 窗口刷新
    GLFW.glfwSetWindowSizeCallback(window, input.sizeCallback); // 窗口大小改变
    GLFW.glfwSetKeyCallback(window, input.keyCallback); // 按键按下
    GLFW.glfwSetCharCallback(window, input.charCallback); // (受修饰符影响)字符输入
    GLFW.glfwSetCharModsCallback(window, input.charModsCallback); // (不受修饰符影响)字符输入
    GLFW.glfwSetMouseButtonCallback(window, input.mouseButtonCallback); // 鼠标按下
    GLFW.glfwSetCursorPosCallback(window, input.cursorPosCallback); // 鼠标指针位置改变
    GLFW.glfwSetCursorEnterCallback(window, input.cursorEnterCallback); // 鼠标指针进入窗口
    GLFW.glfwSetScrollCallback(window, input.scrollCallback); // 窗口滚动
    GLFW.glfwSetDropCallback(window, input.dropCallback); // 文件拖入窗口
}
  • 在Input中创建数组保存按下的按键,并在keyCallback和mouseButtonCallback中记录
// 键盘按下按键
public boolean[] pressed_keys = new boolean[GLFW.GLFW_KEY_LAST];
// 鼠标按下按键
public boolean[] pressed_buttons = new boolean[GLFW.GLFW_MOUSE_BUTTON_LAST];


keyCallback = new GLFWKeyCallback() {
    @Override
    public void invoke(long window, int key, int scancode, int action, int mods) {
        // window 窗口 
        // key 按键类型
        // scancode 按键的系统专用扫描码
        // action 按下的模式(释放、按下、反复)
        // mods 修饰符
        if(action == GLFW.GLFW_PRESS) pressed_keys[key] = true;
        if(action == GLFW.GLFW_RELEASE) pressed_buttons[key] = false;
    }
};

mouseButtonCallback = new GLFWMouseButtonCallback() {
    @Override
    public void invoke(long window, int button, int action, int mods) {
        // window 窗口
        // button 鼠标按键类型
        // action 按下类型(释放、按下、反复)
        // mods 修饰符
        if(action == GLFW.GLFW_PRESS) pressed_buttons[button] = true;
        if(action == GLFW.GLFW_RELEASE) pressed_buttons[button] = false;
    }
};
  • 在Window.update中检测ESC是否被按下,若是则关闭窗口
if(input.pressed_keys[GLFW.GLFW_KEY_ESCAPE])
    GLFW.glfwSetWindowShouldClose(window, true);
  • 在Window.create中调用createCallback以设置回调(放在创建窗口代码之后)
createCallback();
  • 运行代码,可以发现按下ESC进程便会结束。以下是完整代码
// Main.java
package main;

import org.lwjgl.glfw.GLFW;

import engine.Window;

public class Main implements Runnable{
	
	public Thread game;
	public Window window;
	public static final int WIDTH = 1280, HEIGHT = 720;
	
	// 初始化
	public void init() {
		window = new Window(WIDTH, HEIGHT, "Game");
		if(!window.create()) System.exit(1); // 窗口创建失败,结束进程
	}
	// 开始
	public void start() {
		game = new Thread(this, "game");
		game.start();
	}
	// 运行
	public void run() {
		init();
		// 窗口不应关闭时保持循环
		while(!GLFW.glfwWindowShouldClose(window.window)) {
			update();
			render();
		}
	}
	// 渲染
	public void render() {
		System.out.println("Game rendered");
	}
	// 更新
	public void update() {
		System.out.println("Game updated");
		// 更新窗口
		window.update();
	}
	// 主方法
	public static void main(String[] argv) {
		new Main().start();
	}
}
// Window.java
package engine;

import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL;

import engine.io.Input;

public class Window {
	public static int width, height; // 窗口宽度, 长度
	public static String title;
	public long window;
	public Input input = new Input();
	
	@SuppressWarnings("static-access")
	public Window(int width, int height, String title) {
		this.width = width;
		this.height = height;
		this.title = title;
	}
	
	// 创建窗口,并返回是否创建成功
	public boolean create() {
		// 初始化GLFW,并处理错误
		if(!GLFW.glfwInit()) {
			System.err.println("Unable to Init GLFW");
			return false;
		}
		
		// 创建窗口
		window = GLFW.glfwCreateWindow(width, height, title, 0, 0);
		/*
		 * 	创建一个窗口及其相关的OpenGL或OpenGL ES上下文
		 * 	public static long glfwCreateWindow(int width, 
		 * 		int height, 
		 * 		@NativeType("char const *") CharSequence title, 
		 * 		@NativeType("GLFWmonitor *") long monitor, 
		 * 		@NativeType("GLFWwindow *") long share)
		 * 
		 * 	width 窗口宽度
		 * 	height 窗口高度
		 * 	title 窗口标题
		 * 	monitor 用于全屏模式的显示器,或者用于窗口模式的显示器为NULL
		 * 	share 要与之共享资源的窗口,或者不共享资源的窗口为NULL
		 * */
		
		
		// 创建窗口失败
		if(window == 0) {
			System.err.println("Unable to Create Window");
			return false;
		}
		
		
		GLFW.glfwMakeContextCurrent(window);  // 垂直同步
		createCallback();
		GLFW.glfwShowWindow(window); // 显示窗口
		GLFW.glfwSwapInterval(GLFW.GLFW_TRUE); // 垂直同步
		
		// 创建成功
		return true;
	}
	
	// 更新窗口
	public void update() {
		
		if(input.pressed_keys[GLFW.GLFW_KEY_ESCAPE])
			GLFW.glfwSetWindowShouldClose(window, true);
		
		GLFW.glfwPollEvents(); // 处理事件
		GLFW.glfwSwapBuffers(window); // 交换窗口缓冲区
	}
	
	public void createCallback() {
        GLFW.glfwSetWindowCloseCallback(window, input.closeCallback); // 窗口关闭
        GLFW.glfwSetWindowContentScaleCallback(window, input.contentScaleCallback); // 窗口比例更改
        GLFW.glfwSetWindowFocusCallback(window, input.focusCallback); // 窗口获得焦点
        GLFW.glfwSetWindowIconifyCallback(window, input.iconifyCallback); // 窗口最小化
        GLFW.glfwSetWindowMaximizeCallback(window, input.maximizeCallback); // 窗口最大化
        GLFW.glfwSetWindowPosCallback(window, input.posCallback); // 窗口坐标改变
        GLFW.glfwSetWindowRefreshCallback(window, input.refreshCallback); // 窗口刷新
        GLFW.glfwSetWindowSizeCallback(window, input.sizeCallback); // 窗口大小改变
        GLFW.glfwSetKeyCallback(window, input.keyCallback); // 按键按下
        GLFW.glfwSetCharCallback(window, input.charCallback); // (受修饰符影响)字符输入
        GLFW.glfwSetCharModsCallback(window, input.charModsCallback); // (不受修饰符影响)字符输入
        GLFW.glfwSetMouseButtonCallback(window, input.mouseButtonCallback); // 鼠标按下
        GLFW.glfwSetCursorPosCallback(window, input.cursorPosCallback); // 鼠标指针位置改变
        GLFW.glfwSetCursorEnterCallback(window, input.cursorEnterCallback); // 鼠标指针进入窗口
        GLFW.glfwSetScrollCallback(window, input.scrollCallback); // 窗口滚动
        GLFW.glfwSetDropCallback(window, input.dropCallback); // 文件拖入窗口
	}
	
}
// Input.java
package engine.io;

import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWCharCallback;
import org.lwjgl.glfw.GLFWCharModsCallback;
import org.lwjgl.glfw.GLFWCursorEnterCallback;
import org.lwjgl.glfw.GLFWCursorPosCallback;
import org.lwjgl.glfw.GLFWDropCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.glfw.GLFWMouseButtonCallback;
import org.lwjgl.glfw.GLFWScrollCallback;
import org.lwjgl.glfw.GLFWWindowCloseCallback;
import org.lwjgl.glfw.GLFWWindowContentScaleCallback;
import org.lwjgl.glfw.GLFWWindowFocusCallback;
import org.lwjgl.glfw.GLFWWindowIconifyCallback;
import org.lwjgl.glfw.GLFWWindowMaximizeCallback;
import org.lwjgl.glfw.GLFWWindowPosCallback;
import org.lwjgl.glfw.GLFWWindowRefreshCallback;
import org.lwjgl.glfw.GLFWWindowSizeCallback;

public class Input {
	public GLFWWindowCloseCallback closeCallback;
	public GLFWWindowContentScaleCallback contentScaleCallback;
	public GLFWWindowFocusCallback focusCallback;
	public GLFWWindowIconifyCallback iconifyCallback;
	public GLFWWindowMaximizeCallback maximizeCallback;
	public GLFWWindowPosCallback posCallback;
	public GLFWWindowRefreshCallback refreshCallback;
	public GLFWWindowSizeCallback sizeCallback;
	public GLFWKeyCallback keyCallback;
	public GLFWCharCallback charCallback;
	public GLFWCharModsCallback charModsCallback;
	public GLFWMouseButtonCallback mouseButtonCallback;
	public GLFWCursorPosCallback cursorPosCallback;
	public GLFWCursorEnterCallback cursorEnterCallback;
	public GLFWScrollCallback scrollCallback;
	public GLFWDropCallback dropCallback;
	
	// 键盘按下按键
	public boolean[] pressed_keys = new boolean[GLFW.GLFW_KEY_LAST];
	// 鼠标按下按键
	public boolean[] pressed_buttons = new boolean[GLFW.GLFW_MOUSE_BUTTON_LAST];

	public Input() {
        closeCallback = new GLFWWindowCloseCallback() {
            @Override
            public void invoke(long window) {
                // window 窗口
            }
        };
        contentScaleCallback = new GLFWWindowContentScaleCallback() {
            @Override
            public void invoke(long window, float xscale, float yscale) {
                // window 窗口 
            	// xscale x方向的缩放
            	// yscale y方向的缩放
            }
        };
        focusCallback = new GLFWWindowFocusCallback() {
            @Override
            public void invoke(long window, boolean focused) {
            	// window 窗口 
            	// focused 是否获得焦点
            }
        };
        iconifyCallback = new GLFWWindowIconifyCallback() {
            @Override
            public void invoke(long window, boolean iconified) {
            	// window 窗口 
            	// iconified 是否最小化
            }
        };
        maximizeCallback = new GLFWWindowMaximizeCallback() {
            @Override
            public void invoke(long window, boolean maximized) {
            	// window 窗口 
            	// maximized 是否最大化
            }
        };
        posCallback = new GLFWWindowPosCallback() {
            @Override
            public void invoke(long window, int xpos, int ypos) {
            	// window 窗口 
            	// xpos x坐标
            	// ypos y坐标
            }
        };
        refreshCallback = new GLFWWindowRefreshCallback() {
            @Override
            public void invoke(long window) {
            	// window 窗口 
            }
        };
        sizeCallback = new GLFWWindowSizeCallback() {
            @Override
            public void invoke(long window, int width, int height) {
            	// window 窗口 
            	// width 新宽度
            	// height 新高度
            }
        };
        keyCallback = new GLFWKeyCallback() {
            @Override
            public void invoke(long window, int key, int scancode, int action, int mods) {
            	// window 窗口 
            	// key 按键类型
            	// scancode 按键的系统专用扫描码
            	// action 按下的模式(释放、按下、反复)
            	// mods 修饰符
            	if(action == GLFW.GLFW_PRESS) pressed_keys[key] = true;
            	if(action == GLFW.GLFW_RELEASE) pressed_buttons[key] = false;
            }
        };
        charCallback = new GLFWCharCallback() {
            @Override
            public void invoke(long window, int codepoint) {
            	// window 窗口
            	// codepoint 字符unicode编码
            }
        };
        charModsCallback = new GLFWCharModsCallback() {
            @Override
            public void invoke(long window, int codepoint, int mods) {
            	// window 窗口
            	// codepoint 字符unicode编码
            	// mods 修饰符
            }
        };
        mouseButtonCallback = new GLFWMouseButtonCallback() {
            @Override
            public void invoke(long window, int button, int action, int mods) {
            	// window 窗口
            	// button 鼠标按键类型
            	// action 按下类型(释放、按下、反复)
            	// mods 修饰符
            	if(action == GLFW.GLFW_PRESS) pressed_buttons[button] = true;
            	if(action == GLFW.GLFW_RELEASE) pressed_buttons[button] = false;
            }
        };
        cursorPosCallback = new GLFWCursorPosCallback() {
            @Override
            public void invoke(long window, double xpos, double ypos) {
                
            }
        };
        cursorEnterCallback = new GLFWCursorEnterCallback() {
            @Override
            public void invoke(long window, boolean entered) {
            	// window 窗口
            	// entered 是否进入
            }
        };
        scrollCallback = new GLFWScrollCallback() {
            @Override
            public void invoke(long window, double xoffset, double yoffset) {
            	// window 窗口
            	// xoffset x偏移量
            	// yoffset y偏移量
            }
        };
        dropCallback = new GLFWDropCallback() {
            @Override
            public void invoke(long window, int count, long names) {
                // window 窗口
            	// count 文件数
            	// names 名称
            }
        };
	}
}

版权声明:本文为TianX_Bili原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。