我正走在使用 LWJGL 开发自己的小型 MMORPG 游戏的漫长道路上。到目前为止,我已经将一只兔子导入到我的游戏中,并将其放置在草地上方。像这样:
我想做的是让游戏中的对象能够交互。例如,单击它们会弹出一个小选项菜单,或者当您遇到它们时会发生一些事情。为此我需要碰撞检测。我以前曾在 2D 游戏中使用过它,这要简单得多。
这是我的 Bunny.java 类:
public class Bunny {
public static Model m = null;
public static int displayList;
public static void init() {
displayList = glGenLists(1);
glNewList(displayList, GL_COMPILE);
{
try {
m = OBJLoader.loadModel(new File("res/models/bunny.obj"));
} catch (FileNotFoundException e) {
e.printStackTrace();
Display.destroy();
System.exit(1);
} catch (IOException e) {
e.printStackTrace();
Display.destroy();
System.exit(1);
}
glBegin(GL_TRIANGLES);
for (Face face : m.faces) {
Vector3f n1 = m.normals.get((int) face.normal.x - 1);
glNormal3f(n1.x, n1.y, n1.z);
Vector3f v1 = m.vertices.get((int) face.vertex.x - 1);
glVertex3f(v1.x, v1.y, v1.z);
Vector3f n2 = m.normals.get((int) face.normal.y - 1);
glNormal3f(n2.x, n2.y, n2.z);
Vector3f v2 = m.vertices.get((int) face.vertex.y - 1);
glVertex3f(v2.x, v2.y, v2.z);
Vector3f n3 = m.normals.get((int) face.normal.z - 1);
glNormal3f(n3.x, n3.y, n3.z);
Vector3f v3 = m.vertices.get((int) face.vertex.z - 1);
glVertex3f(v3.x, v3.y, v3.z);
}
glEnd();
}
glEndList();
}
public static void draw(float x, float y, float z) {
glPushMatrix();
glTranslatef(x, y, z);
glCallList(displayList);
glPopMatrix();
}
}
还有我的主课:
public class Main {
public static float PlayerX = 0;
public static float PlayerY = 0;
public static float PlayerZ = 0;
public static float walkSpeed = 0.016f;
public static float PlayerRot = 0;
private static float[] lightPosition = {-2.19f, 1.36f, 11.45f, 1f};
public float pCenterX = 0;
public float pCenterY = 0;
public float pCenterZ = 0;
public static Model m = null;
public static void main(String[] args) {
initDisplay();
Bunny.init();
gameLoop();
cleanUp();
}
public static void gameLoop() {
Texture tex = loadTexture("tex", "png");
Texture wood = loadTexture("wood", "png");
loadLight();
Camera camera = new Camera(70, (float) Display.getWidth() / (float) Display.getHeight(), 0.3f, 1000);
while (!Display.isCloseRequested()) {
if(Keyboard.isKeyDown(Keyboard.KEY_W)) camera.move(walkSpeed, 1);
if(Keyboard.isKeyDown(Keyboard.KEY_S)) camera.move(-walkSpeed, 1);
if(Keyboard.isKeyDown(Keyboard.KEY_A)) camera.rotateY(-0.1f);
if(Keyboard.isKeyDown(Keyboard.KEY_D)) camera.rotateY(0.1f);
if(Keyboard.isKeyDown(Keyboard.KEY_SPACE)) camera.moveY(0.05f, 1);
if(Keyboard.isKeyDown(Keyboard.KEY_Z)) camera.moveY(0.05f, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glTranslatef(0, 2.5f, 0);
glLoadIdentity();
//camera.setX(-PlayerX); camera.setY(-PlayerY - 3); camera.setZ(-PlayerZ - 10);
glLight(GL_LIGHT0, GL_POSITION, asFloatBuffer(new float[] {-2.19f, 1.36f, 11.45f, 1f}));
camera.useView();
//Draw.rect(PlayerX, PlayerY, PlayerZ, 0.5f, 0.5f, 0.5f, tex);
Draw.rect(1, 0, 1, 100, 0.5f, 100, wood);
Bunny.draw(10, 2.5f, 10);
Bunny.draw(50, 2.5f, 50);
Display.update();
}
}
public static void cleanUp() {
Display.destroy();
}
public static void initDisplay() {
try {
Display.setDisplayMode(new DisplayMode(800, 600));
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
}
}
public static Texture loadTexture(String key, String fileType) {
try {
return TextureLoader.getTexture(fileType, new FileInputStream(new File("res/img/" + key + "." + fileType)));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private static FloatBuffer asFloatBuffer(float[] values) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(values.length);
buffer.put(values);
buffer.flip();
return buffer;
}
public static void loadLight() {
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightModel(GL_LIGHT_MODEL_AMBIENT, asFloatBuffer(new float[] {0.05f, 0.05f, 0.05f, 1f}));
glLight(GL_LIGHT0, GL_DIFFUSE, asFloatBuffer(new float[] {1.5f, 1.5f, 1.5f, 1f}));
//glEnable(GL_CULL_FACE);
//glCullFace(GL_BACK);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_DIFFUSE);
}
}
如何获取兔子的点,并在算法中使用这些点来检测我们何时发生碰撞?
最佳答案
您已经在第一个片段中显示了顶点的代码。所以你拥有它们。
至于问题的第二部分:您正在寻找的是碰撞检测和拾取。在答案中涵盖它们实在太多了,因此您必须查找它们。
做到这一点的一种方法是场景图。
- 每个对象都有一个包围其所有点的边界框
- 通过将对象连接到节点来链接到场景图中
- 每个节点都有一个包围其子节点所有框的边界框
这给你一个树状结构。现在,您只需通过针对碰撞伙伴测试节点的边界框来检查是否发生了碰撞。如果它击中了您,请检查其子节点和对象是否发生碰撞。如果您命中某个对象,您可以根据实际模型数据进行另一次检查。
对于普通对象,您可以使用它们的边界框和数据进行检查。为了进行拾取,您可以使用从鼠标单击的世界坐标中发射的光线。
这只是实现这一目标的方法,但该主题还有更多内容。例如,OpenGL 提供了自己的拾取支持。
关于Java LWJGL - 3D 模型上的碰撞检测?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25142812/