2014-03-27 60 views
0

所以,我做了一个2D平台游戏。我得到了纹理,控制和一切正常,直到我决定让游戏拥有滚动相机。我读过的地方说,使用glOrtho移动和缩放相机,但当我打电话glOrtho我的屏幕变成黑色我知道我做错了什么,但不知道该怎么做。OpenGL得到了glOrtho黑色屏幕lwjgl

我的游戏循环之前得到这个:

glLoadIdentity(); 
glMatrixMode(GL_PROJECTION); 
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); 
glOrtho(0, GAME_WIDTH, GAME_HEIGHT, 0, 1, -1); 
glMatrixMode(GL_MODELVIEW); 
*enabling texture_2d and others 

和我得到这个在游戏循环,使相机跟随玩家:

glClear(GL_COLOR_BUFFER_BIT); 
xOff = player.x - GAME.WIDTH/2; 
yOff = player.y - GAME.HEIGHT/2; 
glOrtho(xOff, xOff + GAME_WIDTH, yOff + GAME_HEIGHT, yOff, 1, -1); 

但它给了我黑色的屏幕..当我更改第一次调用glOrtho的值时,这很好,但我已经在谷歌上搜索这个概要但找不到任何帮助?

编辑:这里的主类

package com.org.Game; 

import static org.lwjgl.opengl.GL11.*; 

import org.lwjgl.LWJGLException; 
import org.lwjgl.Sys; 
import org.lwjgl.input.Keyboard; 
import org.lwjgl.opengl.Display; 
import org.lwjgl.opengl.DisplayMode; 

import com.org.Game.Graphics.Draw; 
import com.org.Game.Graphics.Sprite; 
import com.org.Game.Graphics.Spritesheet; 
import com.org.Game.Level.Level; 
import com.org.Game.Level.Entity.Mob.Player; 

public class Main { 

    private static String title = "Platformer"; 
    private static int WINDOW_WIDTH = 800, WINDOW_HEIGHT = 600; 
    private static int GAME_WIDTH = 320, GAME_HEIGHT = 240; 

    private boolean exit = false; 
    private long lastFPS; 
    private int fps; 
    private long lastFrame; 
    private long delta; 
    private boolean fpscap = true; 

    private Level lvl; 
    private Player player; 
    private int xOff, yOff; 

    public Main() { 
     try { 
      Display.setDisplayMode(new DisplayMode(WINDOW_WIDTH, WINDOW_HEIGHT)); 
      Display.setTitle(title); 
      Display.setVSyncEnabled(true); 
      DisplayMode[] modes = Display.getAvailableDisplayModes(); 
      for (int i = 0; i < modes.length; i++) { 
       if (modes[i].getWidth() == WINDOW_WIDTH && modes[i].getHeight() == WINDOW_HEIGHT && modes[i].getFrequency() == 60 && modes[i].isFullscreenCapable()) { 
        Display.setDisplayMode(modes[i]); 
        System.out.println(modes[i].getWidth() + " " + modes[i].getHeight() + " " + modes[i].getBitsPerPixel() + " " + modes[i].getFrequency() + " " + modes[i].isFullscreenCapable()); 
        break; 
       } 
      } 
      // Display.setFullscreen(true); 
      Display.create(); 
     } catch (LWJGLException e) { 
      e.printStackTrace(); 
      Display.destroy(); 
      System.exit(0); 
     } 

     glLoadIdentity(); 
     glMatrixMode(GL_PROJECTION); 
     glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); 
     glOrtho(0, GAME_WIDTH, GAME_HEIGHT, 0, 1, -1); 
     glMatrixMode(GL_MODELVIEW); 

     glEnable(GL_TEXTURE_2D); 

     glEnable(GL_CULL_FACE); 
     glCullFace(GL_BACK); 

     glEnable(GL_BLEND); 
     glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_DST_COLOR); 

     glPolygonMode(GL_FRONT, GL_FILL); 

     lvl = new Level(); 
     lvl.loadLevel("level0.dat"); 
     if (lvl == null) System.out.println("NULL"); 
     player = new Player(16, 16, Sprite.cobalt, lvl); 

     start(); 

     Spritesheet.tiles.tex.release(); 
     Spritesheet.bg_day.tex.release(); 
     Display.destroy(); 
     System.exit(0); 
    } 

    int a; 

    private void render() { 
     Draw.clearScreen(); 

     glLoadIdentity(); 
     glMatrixMode(GL_PROJECTION); 
     glOrtho(xOff, xOff + GAME_WIDTH, yOff + GAME_HEIGHT, yOff, 1, -1); 
     glMatrixMode(GL_MODELVIEW); 

     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 

     Draw.setTexture(Spritesheet.bg_day); 
     Draw.drawBackground(GAME_WIDTH, GAME_HEIGHT, Spritesheet.bg_day); 

     Draw.setTexture(Spritesheet.tiles); 
     lvl.renderLevel(GAME_WIDTH, GAME_HEIGHT, xOff, yOff); 

     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
     player.render(); 
    } 

    private void update(long delta) { 
     player.update(delta); 
     if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) exit = true; 
     if (Keyboard.isKeyDown(Keyboard.KEY_Z)) fpscap = true; 
     if (Keyboard.isKeyDown(Keyboard.KEY_X)) fpscap = false; 
    } 

    public void start() { 
     lastFPS = getTime(); 
     getDelta(); 

     while (!Display.isCloseRequested() && !exit) { 
      getDelta(); 

      xOff = (int) player.x - GAME_WIDTH/2; 
      yOff = (int) player.y - GAME_HEIGHT/2; 

      render(); 
      update(delta); 

      updateFPS(); 
      Display.update(); 
      if (fpscap) Display.sync(120); 
     } 
    } 

    private void getDelta() { 
     long now = getTime(); 
     delta = now - lastFrame; 
     lastFrame = now; 
    } 

    private void updateFPS() { 
     fps++; 
     if (getTime() - lastFPS > 1000) { 
      lastFPS += 1000; 
      Display.setTitle(title + " FPS: " + fps); 
      fps = 0; 
     } 
    } 

    private long getTime() { 
     return Sys.getTime() * 1000/Sys.getTimerResolution(); 
    } 

    public static void main(String[] args) { 
     new Main(); 
    } 

} 
+0

所以,你的模型视图堆栈将邻投影矩阵呢?为什么? – genpfault

+0

所以你说我需要切换到第二次glOrtho之前再次gl_projection? – Greffin28

+0

@ Greffin28:你的方法存在一些潜在的问题,但没有进一步的代码,很难说出发生了什么。如果你把这个矩阵放到两个堆栈上,它们将被应用两次。这不会给你预期的结果,'glOrtho'只是创建一个合并的缩放转换矩阵。 – derhass

回答

0

这里的问题是,你不改变矩阵模式切换正投影,据我可以告诉前GL_PROJECTION - 作为你的第二个代码片段呢没有矩阵模式状态改变。所以,试试这个:

glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
xOff = player.x - GAME.WIDTH/2; 
yOff = player.y - GAME.HEIGHT/2; 
glOrtho(xOff, xOff + GAME_WIDTH, yOff + GAME_HEIGHT, yOff, 1, -1); 
glMatrixMode(GL_MODELVIEW); 

请记住这个代码段将重置变换矩阵,所以任何glTransform()或glRotate()调用或glScale()调用,当然就会失去效果,但由于这是在你的游戏循环开始,并且每运行一次我都会运行,我怀疑这应该不是问题。

+0

我试过了,但它仍然给我黑色屏幕:/ – Greffin28

+0

那么,你正在调用glClear(GL_COLOR_BUFFER_BIT)清除屏幕。 – SDLeffler

+0

等待..什么..但我清除屏幕后,我叫glOrtho不会做任何改变? – Greffin28

0

你的代码有两个问题:你在做“OpenGL初始化”。为什么? OpenGL是一个状态机,它不会被初始化。你将OpenGL置于你需要的状态,当你需要的时候。构造函数中的大多数OpenGL调用都是不必要的,并且不起作用。大多数OpenGL的东西只能在渲染函数中完成。

对于渲染方法试试这个:

private void render() { 
      // glViewport does not depend on the matrix state 
    glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); 

    Draw.clearScreen(); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glOrtho(xOff, xOff + GAME_WIDTH, yOff + GAME_HEIGHT, yOff, 1, -1); 

    glMatrixMode(GL_MODELVIEW); 
      glLoadIdentity(); 

    glEnable(GL_TEXTURE_2D); 

    glEnable(GL_CULL_FACE); 
    glCullFace(GL_BACK); 

      // probably don't want to blend the background 
      // actually get your blending stuff right, I removed it entirely 
      // because it's completely unclear from your code what you want 
      // to blend which way 
    glDisable(GL_BLEND); 
    Draw.setTexture(Spritesheet.bg_day); 
    Draw.drawBackground(GAME_WIDTH, GAME_HEIGHT, Spritesheet.bg_day); 

    Draw.setTexture(Spritesheet.tiles); 
    lvl.renderLevel(GAME_WIDTH, GAME_HEIGHT, xOff, yOff); 

      // probably needs its texture set. 
    player.render(); 
} 
+0

噢是的,它的作品太..但我可能会更舒服的调用一次,永远不会再被改变..哦耶和感谢提醒我禁用混合背景之前:) – Greffin28

+0

@ Greffin28:设置投影的成本矩阵非常小,因此将每个显示器调用的好处都大大超过了它。迟早你会最终出现在你需要在渲染帧的过程中多次改变投影参数的情况,并且如果你的程序是围绕“只投影一次”而建立的,它最终会变成一个试图保持跟踪的巨大混乱哪些东西以什么顺序改变。相信我,你想重置渲染每一帧的投影。 – datenwolf

+0

不,我不是指投影矩阵,但其他像启用gl_texture_2d – Greffin28