Java - 如何创建一个屏幕图层来加载我的游戏UI?

时间:2014-12-31 22:26:50

标签: java opengl user-interface screen

我正在使用Java LWJGL和OpenGL创建一个3D游戏。我希望能够在屏幕上显示玩家健康栏。我正在考虑在渲染游戏后可以呈现的某种屏幕,它将处理所有类似于2D的用户界面。需要渲染到屏幕的元素。这样做的最佳做法是什么?我尝试使用Graphics类创建一个Screen类和绘画,但我遇到了这个问题。我想要一个简单的方法来渲染这些元素。怎么做的?

编辑:

以下是我认为有用的一些文件

MasterRenderer:

package renderEngine;

import java.awt.Graphics;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import models.TexturedModel;

import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Matrix4f;

import shaders.StaticShader;
import shaders.TerrainShader;
import terrains.Terrain;
import entities.Camera;
import entities.Entity;
import entities.Light;

public class MasterRenderer {

private static final float FOV = 70;
private static final float NEAR_PLANE = 0.1f;
private static final float FAR_PLANE = 1000;

private static final float RED = 0.5f;
private static final float GREEN = 0.90f;
private static final float BLUE = 0.90f;

private GUI gui = new GUI();


private Matrix4f projectionMatrix;

private StaticShader shader = new StaticShader();
private EntityRenderer renderer;

private Map<TexturedModel, List<Entity>> entities = new HashMap<TexturedModel, List<Entity>>();
private List<Terrain> terrains = new ArrayList<Terrain>();

private TerrainRenderer terrainRenderer;
private TerrainShader terrainShader = new TerrainShader();

public MasterRenderer() {
    enableCulling();

    createProjectionMatrix();
    renderer = new EntityRenderer(shader, projectionMatrix);
    terrainRenderer = new TerrainRenderer(terrainShader, projectionMatrix);

}

public static void enableCulling() {
    GL11.glEnable(GL11.GL_CULL_FACE);
    GL11.glCullFace(GL11.GL_BACK);
}

public static void disableCulling() {
    GL11.glDisable(GL11.GL_CULL_FACE);
}

public void prepare() {
    GL11.glEnable(GL11.GL_DEPTH_TEST);
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT|GL11.GL_DEPTH_BUFFER_BIT);
    GL11.glClearColor(RED, GREEN, BLUE, 1);

}

public void render(Light sun, Camera camera) {
    prepare();
    shader.start();
    shader.loadSkyColour(RED,GREEN,BLUE);
    shader.loadLight(sun);
    shader.loadViewMatrix(camera);
    renderer.render(entities);
    shader.stop();
    terrainShader.start();
    terrainShader.loadLight(sun);
    terrainShader.loadViewMatrix(camera);
    terrainShader.loadSkyColour(RED,GREEN,BLUE);
    terrainRenderer.render(terrains);
    terrainShader.stop();
    gui.drawRect(100, 100, 300, 300, 0x00000000);
    terrains.clear();
    entities.clear();
}

public void processTerrain(Terrain terrain) {
    terrains.add(terrain);
}

public void processEntity(Entity entity) {
    TexturedModel entityModel = entity.getModel();
    List<Entity> batch = entities.get(entityModel);
    if(batch != null) {
        batch.add(entity);
    } else {
        List<Entity> newBatch = new ArrayList<Entity>();
        newBatch.add(entity);
        entities.put(entityModel, newBatch);
    }
}

private void createProjectionMatrix() {
    float aspectRatio = (float) Display.getWidth() / (float) Display.getHeight();
    float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV / 2f))) * aspectRatio);
    float x_scale = y_scale / aspectRatio;
    float frustum_length = FAR_PLANE - NEAR_PLANE;

    projectionMatrix = new Matrix4f();
    projectionMatrix.m00 = x_scale;
    projectionMatrix.m11 = y_scale;
    projectionMatrix.m22 = -((FAR_PLANE + NEAR_PLANE) / frustum_length);
    projectionMatrix.m23 = -1;
    projectionMatrix.m32 = -((2 * NEAR_PLANE * FAR_PLANE) / frustum_length);
    projectionMatrix.m33 = 0;
}



public void cleanUp() {
    shader.cleanUp();
    terrainShader.cleanUp();
}

}

Camera.java:

package entities;

import org.lwjgl.input.Mouse;
import org.lwjgl.util.vector.Vector3f;

public class Camera {

private float distanceFromPlayer = 50;
private float angleAroundPlayer = 0;


private Vector3f position = new Vector3f(0,0,0);
private float pitch = 20; //rotation
private float yaw = 0; //left or right
private float roll; //Tilted

private Player player;

public Camera(Player player) {
    this.player = player;
}

public void move() {
    calculateZoom();
    calculatePitch();
    calculateAngleAroundPlayer();

    float horizontalDistance = calculateHorizontalDistance();
    float verticalDistance = calculateVerticalDistance();
    calculateCameraPosition(horizontalDistance, verticalDistance);
    this.yaw = 180 - (player.getRotY() + angleAroundPlayer);
}

public float getAngleAroundPlayer() {
    return angleAroundPlayer;
}

public Vector3f getPosition() {
    return position;
}

public float getPitch() {
    return pitch;
}

public float getYaw() {
    return yaw;
}

public float getRoll() {
    return roll;
}

public void setAngleAroundPlayer(float angleAroundPlayer) {
    this.angleAroundPlayer = angleAroundPlayer;
}

private void calculateCameraPosition(float horizDistance, float verticDistance) {
    float theta = player.getRotY() + angleAroundPlayer;
    float offsetX = (float) (horizDistance * Math.sin(Math.toRadians(theta)));
    float offsetZ = (float) (horizDistance * Math.cos(Math.toRadians(theta)));

    position.x = player.getPosition().x - offsetX;
    position.z = player.getPosition().z - offsetZ;
    position.y = player.getPosition().y + verticDistance + 10;
}

private float calculateHorizontalDistance() {
    return (float) (distanceFromPlayer * Math.cos(Math.toRadians(pitch)));  
}

private float calculateVerticalDistance() {
    return (float) (distanceFromPlayer * Math.sin(Math.toRadians(pitch)));  
}

private void calculateZoom() {
    float zoomLevel = Mouse.getDWheel() * 0.1f;
    distanceFromPlayer -= zoomLevel;
}

private void calculatePitch() {
    if(Mouse.isButtonDown(1)) {
        float pitchChange = Mouse.getDY() * 0.1f;
        pitch -= pitchChange;

        if(pitch < 10) pitch = 10;
        if(pitch > 90) pitch = 90;      
    }
}

private void calculateAngleAroundPlayer() {
    if(Mouse.isButtonDown(0)) {
        float angleChange = Mouse.getDX() * 0.3f;

        if(angleAroundPlayer >= 360) angleAroundPlayer = 0;

        angleAroundPlayer -= angleChange;
    }
}

}

MainGameLoop:

package engineTester;

import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import models.TexturedModel;

import org.lwjgl.opengl.Display;
import org.lwjgl.util.vector.Vector3f;

import renderEngine.DisplayManager;
import renderEngine.Loader;
import renderEngine.MasterRenderer;
import renderEngine.OBJLoader;
import terrains.Terrain;
import textures.ModelTexture;
import textures.TerrainTexture;
import textures.TerrainTexturePack;
import toolbox.KeyBindings;
import entities.Camera;
import entities.Entity;
import entities.Light;
import entities.Player;

public class MainGameLoop {
public static KeyBindings keyBindings;

public static Camera camera;


public static void main(String[] args) {// TODO Auto-generated method stub
    DisplayManager.createDisplay();
    Loader loader = new Loader();

    //--------------------Terrain Texture------------------//


    TerrainTexture backgroundTexture = new TerrainTexture(loader.loadTexture("grassy2"));
    TerrainTexture rTexture = new TerrainTexture(loader.loadTexture("mud"));
    TerrainTexture gTexture = new TerrainTexture(loader.loadTexture("pinkFlowers"));
    TerrainTexture bTexture = new TerrainTexture(loader.loadTexture("stone"));

    TerrainTexturePack texturePack = new TerrainTexturePack(backgroundTexture, rTexture,
            gTexture, bTexture);

    TerrainTexture blendMap = new TerrainTexture(loader.loadTexture("blendMap"));


    //-----------------------------------------------------//

    ModelTexture fernTextureAtlas = new ModelTexture(loader.loadTexture("fern"));
    fernTextureAtlas.setNumberOfRows(2);

    TexturedModel tree1 = new TexturedModel(OBJLoader.loadObjModel("tree", loader), 
            new ModelTexture(loader.loadTexture("tree")));

    TexturedModel tree2 = new TexturedModel(OBJLoader.loadObjModel("lowPolyTree", loader), 
            new ModelTexture(loader.loadTexture("lowPolyTree")));

    TexturedModel fern = new TexturedModel(OBJLoader.loadObjModel("fern", loader), 
            fernTextureAtlas);

    TexturedModel flower = new TexturedModel(OBJLoader.loadObjModel("grassModel", loader), 
            new ModelTexture(loader.loadTexture("flower")));

    TexturedModel stall = new TexturedModel(OBJLoader.loadObjModel("stall", loader), 
            new ModelTexture(loader.loadTexture("stallTexture")));

    TexturedModel grass = new TexturedModel(OBJLoader.loadObjModel("grassModel", loader), 
            new ModelTexture(loader.loadTexture("grassTexture")));

    TexturedModel playerModel = new TexturedModel(OBJLoader.loadObjModel("person", loader), 
            new ModelTexture(loader.loadTexture("playerTexture")));

    grass.getTexture().setUseFakeLighting(true);
    grass.getTexture().setHasTransparency(true);
    fern.getTexture().setUseFakeLighting(true);
    fern.getTexture().setHasTransparency(true);
    stall.getTexture().setShineDamper(10);
    stall.getTexture().setReflectivity(1);
    tree1.getTexture().setShineDamper(10);


    Light light = new Light(new Vector3f(0, 20000, 20000), new Vector3f(1,1,1));

    Terrain terrain = new Terrain(0, 0, loader, texturePack, blendMap, "heightMap");

    List<Entity> entities = new ArrayList<Entity>();

    Random random = new Random();

    for (int i = 0; i < 400; i++) {
        if (i % 2 == 0) {
            float x = random.nextFloat() * 800;
            float z = random.nextFloat() * 600;
            float y = terrain.getHeightOfTerrain(x, z);
            entities.add(new Entity(fern, random.nextInt(4), new Vector3f(x, y, z), 0, random.nextFloat() * 360, 0, 0.9f));
        }
        if (i % 5 == 0) {
            float x = random.nextFloat() * 800;
            float z = random.nextFloat() * 600;
            float y = terrain.getHeightOfTerrain(x, z);
            entities.add(new Entity(tree1, new Vector3f(x, y, z), 0, random.nextFloat() * 360, 0, random.nextFloat() * 1 + 4));

            x = random.nextFloat() * 800;
            z = random.nextFloat() * 600;
            y = terrain.getHeightOfTerrain(x, z);
            entities.add(new Entity(tree2, new Vector3f(x, y, z), 0, random.nextFloat() * 360, 0, random.nextFloat() * 0.1f + 0.6f));
        }
        if (i % 4 == 0) {
            float x = random.nextFloat() * 800;
            float z = random.nextFloat() * 600;
            float y = terrain.getHeightOfTerrain(x, z);
            entities.add(new Entity(grass, new Vector3f(x, y, z), 0, 0, 0, 1.5f));

            x = random.nextFloat() * 800;
            z = random.nextFloat() * 600;
            y = terrain.getHeightOfTerrain(x, z);
            entities.add(new Entity(flower, new Vector3f(x, y, z), 0, 0, 0, 1.5f));
        }

    }

    MasterRenderer renderer = new MasterRenderer();

    Player.parsePlayerData();
    float terrainHeight = Player.getTerrainHeight(terrain, Player.PLAYER_X, Player.PLAYER_Z);
    Player player = new Player(playerModel, new Vector3f(Player.PLAYER_X, terrainHeight, Player.PLAYER_Z), 0, 0, 0, 1);

    camera = new Camera(player);



    while (!Display.isCloseRequested()) {

        camera.move();
        player.move(terrain);
        renderer.processEntity(player);
        renderer.processTerrain(terrain);

        for(Entity entity : entities) {
            renderer.processEntity(entity);
        }

        renderer.render(light, camera);

        DisplayManager.updateDisplay();
        keyBindings.run();

    }



    renderer.cleanUp();
    loader.cleanUp();
    Player.savePlayerData(player/*new Vector3f(player.getPosition().x, terrainHeight, player.getPosition().z)*/);
    DisplayManager.closeDisplay();

}

}

1 个答案:

答案 0 :(得分:0)

使用透视投影渲染3D场景后,您可以切换到正交投影并将2D图形渲染到其他所有内容之上。在您的情况下,Screen类非常适合UI呈现。

Game.render(); //Set Persp Proj; Render 3D world (terrain, meshes & models)
Screen.render(); //Set Orhto Proj; Render UI elements on top (textures, fonts)

实际上这个想法非常简单,困难的部分就是在OpenGL版本和编程语言的实现细节中。