LWJGL Game Init and Main Loop

With the advent of LWJGL 0.9 marking a freeze in the API I thought there might be some clubies who’d like to see how simple a LWJGL game can look.

So here is a complete Game class. Fill in the blanks with your game :wink: (This code is checked into LWJGL CVS too)


/*
 * Copyright (c) 2002 Light Weight Java Game Library Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'Light Weight Java Game Library' nor the names of
 *   its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.lwjgl.examples;

import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.openal.AL;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.Window;

/**
 * $Id: Game.java,v 1.3 2004/05/05 14:35:05 cix_foo Exp $
 *
 * This is a <em>very basic</em> skeleton to init a game and run it.
 *
 * @author $Author: cix_foo $
 * @version $Revision: 1.3 $
 */
public class Game {
      
      /** Game title */
      public static final String GAME_TITLE = "My Game";
      
      /** Desired frame time */
      private static final int FRAMERATE = 60;
      
      /** Exit the game */
      private static boolean finished;
      
      /**
       * No constructor needed - this class is static
       */
      private Game() {}
      
      /**
       * Application init
       * @param args Commandline args
       */
      public static void main(String[] args) {
            try {
                  init();
                  run();
            } catch (Exception e) {
                  e.printStackTrace(System.err);
                  Sys.alert(GAME_TITLE, "An error occured and the game will exit.");
            } finally {
                  cleanup();
            }
      }
      
      /**
       * Initialise the game
       * @throws Exception if init fails
       */
      private static void init() throws Exception {
            // Create a fullscreen window with 1:1 orthographic 2D projection, and with
            // mouse, keyboard, and gamepad inputs.
            Window.create(GAME_TITLE);
            
            // Enable vsync if we can
            Window.setVSyncEnabled(true);
            
            // Start up the sound system
            AL.create();
            
            // TODO: Load in your textures etc here
      }
      
      /**
       * Runs the game (the "main loop")
       */
      private static void run() {
            while (!finished) {
                  // Always call Window.update(), all the time
                  Window.update();
                  
                  if (Window.isCloseRequested()) {
                        // Check for O/S close requests
                        finished = true;
                  } else if (Window.isActive()) {
                        // The window is in the foreground, so we should play the game
                        logic();
                        render();
                        org.lwjgl.Display.sync(FRAMERATE);
                  } else {
                        // The window is not in the foreground, so we can allow other stuff to run and
                        // infrequently update
                        try {
                              Thread.sleep(100);
                        } catch (InterruptedException e) {
                        }
                        logic();
                        if (Window.isVisible() || Window.isDirty()) {
                              // Only bother rendering if the window is visible or dirty
                              render();
                        }
                  }
            }
      }
      
      /**
       * Do any game-specific cleanup
       */
      private static void cleanup() {
            // TODO: save anything you want to disk here

            // Stop the sound
            AL.destroy();
            
            // Close the window
            Window.destroy();
      }
      
      /**
       * Do all calculations, handle input, etc.
       */
      private static void logic() {
            // Example input handler: we'll check for the ESC key and finish the game instantly when it's pressed
            if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
                  finished = true;
            }
            // TODO: all your game logic goes here.
      }
      
      /**
       * Render the current frame
       */
      private static void render() {
            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
            // TODO: all your rendering goes here
      }

}

fixed a bug in cleanup
New timing code!

Cas :slight_smile:

             // Create a fullscreen window with 1:1 orthographic 2D projection, and with
            // mouse, keyboard, and gamepad inputs.
            Window.create(GAME_TITLE) ;

Sweet! ;D

It’s in things like that where LWJGL really shines.

as dobbie said…sweet! Been wanting to play with this for while…that being said, let me fall into my semi-permanent roll as a clubie!

I found a statement that went something like this: must have good graphics card to use lwjgl.

I don;t on my dev box and I am getting the follwoing error running any of the openGL demos:
org.lwjgl.LWJGLException: Could not choose ARB pixel formats.

I posted to this forum because I am getting a error:

Exception in thread "main" java.lang.NoClassDefFoundError
        at org.lwjgl.openal.AL.<clinit>(Unknown Source)
        at org.lwjgl.examples.Game.cleanup(Game.java:147)
        at org.lwjgl.examples.Game.main(Game.java:77)

for me line 147 is:

  AL.destroy(); 

[quote]I found a statement that went something like this: must have good graphics card to use lwjgl.
[/quote]
Hmm, no - but it does make sense to have an OGL capable card :wink: - that said, some use mesa - and you have to specify allowSoftwareOpenGL to enable software gl mode.

[quote]I don;t on my dev box and I am getting the follwoing error running any of the openGL demos:
org.lwjgl.LWJGLException: Could not choose ARB pixel formats.
[/quote]
Hmm, strange - do normal OpenGL apps work at all? - it’s a pretty fatal error.

That error is a bit strange:
1 - the constructor has never been called in the init, which is why it’s just now being called in the destroy
2 - It can’t find the AL class - sure you have lwjgl.jar in the classpath ??

[quote]Hmm, strange - do normal OpenGL apps work at all? - it’s a pretty fatal error.
[/quote]
Well Java3D for OpenGL works fine.

Classpath…it compiles fine, just does not run. i wil double check classpath for run command in JCreator.

Here is a texture loader:


import org.lwjgl.*;
import org.lwjgl.opengl.*;
import org.lwjgl.opengl.glu.*;

import javax.swing.*;
import java.awt.image.*;
import java.io.*;
import java.awt.*;
import java.nio.*;


public class Main
{


      private void programExec()
      {
      buff = BufferUtils.createIntBuffer(MAX);

      buff.put(getIntContents()).flip();

      GL11.glGenTextures(buff);
      }


      private int[] getIntContents()
      {
            int[] c = new int[MAX];
            int i=0;

            try
            {
          c[i] = fr.read();

          while(c[i] != -1)
                  {
                        i++;
                        c[i] = fr.read();
                  }
            }catch (Exception e)
            {
                  JOptionPane.showMessageDialog(null, e.getMessage());
                  e.printStackTrace();
            }

            return c;
      }



      /**
       * MAIN
       */
      public Main()
  {
        try
            {
               fr = new FileReader("c:\\texture.PNG");
            } catch (Exception e)
            {
                  JOptionPane.showMessageDialog(null, e.getMessage());
                  e.printStackTrace();
            }
      }

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

            main.programExec();
      }
      /**
       * MAIN
       */

      BufferedImage bufImg;
      Image img;
      ImageIcon imgIc;
      FileReader fr;
      IntBuffer buff;

      final static int MAX = 25000;
}

[quote]With the advent of LWJGL 0.9 marking a freeze in the API I thought there might be some clubies who’d like to see how simple a LWJGL game can look.
[/quote]
Are you trying to convince me that LWJGL is better than others, or that game development in general is simple?

I think he was spending is time trying to give out a simple game loop to help out newbies who might want to be able to get a game going up quickly with a solid framework.

I think that’s great. More people should be giving back to the community. We should encourage this, not be all ‘mean’ about it.

???

I could never run any lwjgl demos until I installed a newer driver for my POS intel onboard gfx. I didn’t think drivers would be available for it but after about 30 minutes of searching I did find them on the intel site.

So you might try updating your drivers.

[quote]I think that’s great. More people should be giving back to the community. We should encourage this, not be all ‘mean’ about it
[/quote]
Oops…looks like I miscommunicated something :-[.
Don’t get me wrong here, I think this is a great idea! To me, all these relatively low-level APIs are just scary :’(.
Thanks Cas. ;D

  1. /bump

  2. woot! thx a zillion, that’s gonna motivate me to actually do something (heck I’ve been around for a while and have yet to start anything, gd time constraints)

  3. private static final float FRAMETIME = 1.0f / 60.0f; claps at the time based loop what happens if the fps drops below 60? (i.e. if the graphic card/cpu can’t handle it?) and huh if this works like I think it does, do you really need to put setVSyncEnable?

  4. no mouse? tsk tsk :wink:

Thanks again from the most experienced in noobiness newless clubie ;D

I’ve just started my 80hr game project based on this code. 4 hrs down, 76 to go.

Then it slows down :slight_smile: If you can use vsync then you’ll not get any tearing, and that’s all the difference it makes.

Mouse, controller, and keyboard are automatically created and polled by LWJGL for you now.

Cas :slight_smile:

Found where I am dying when trying to run your simple game loop:
Window.create(GAME_TITLE);

I have a println in front of this and after. The after never gets called, nothing is caught, then it goes straight to the finally() and throws a nullpointer because the AL.create() was never called. (since I cant get past WIndow.create(GAME_TITLE):wink:

hmmmm, I am cluieless and lost.

Try running in debug mode:
-Dorg.lwjgl.Sys.debug=true

in the finally clause...
Exception in thread "main" java.lang.NoClassDefFoundError
        at org.lwjgl.openal.AL.<clinit>(Unknown Source)
        at org.lwjgl.examples.Game.cleanup(Game.java:163)
        at org.lwjgl.examples.Game.main(Game.java:81)

same as above…the AL is never created, debug mode showed nothing different

hmm, you really sholdn’t ever receive a NoClassDefFoundError, unless you have your project setup in some wierd way…

could I get a copy of your project to find the error - this is really strange…

another way would be to grab the source and start adding debug code to find the exact line thats failing. I just dont get why you don’t get any output when running in debug mode… ponder

I’m getting the same error…

[quote]Exception in thread “main” java.lang.NoClassDefFoundError
at org.lwjgl.openal.AL.(Unknown Source)
at org.lwjgl.examples.Game.cleanup(Game.java:147)
at org.lwjgl.examples.Game.main(Game.java:77)
[/quote]

[quote]Try running in debug mode:
-Dorg.lwjgl.Sys.debug=true
[/quote]
How do I do this? (I’m using JCreater freeware, by the way…)

hmm this is getting odd…

the debug switch is something you append to your commandline… so if you normally do:
java org.lwjgl.examples.Game
you should now do:
java -Dorg.lwjgl.Sys.debug=true org.lwjgl.examples.Game

if you don’t get any output - something is way wrong… I get:

[quote]Window registered
Releasing DC
Destroy window
Could not locate symbol glPointParameteriNV
NOTICE: GL_NV_point_sprite disabled because of missing driver symbols
Could not locate symbol glLoadProgramNV
Could not locate symbol glVertexStream1fATI
NOTICE: GL_ATI_vertex_streams disabled because of missing driver symbols
found X-axis
found Y-axis
found Wheel
found Button 0
found Button 1
found Button 2
found Button 3
found Button 4
found Button 5
found Button 6
found Button 7
WARNING: Clamping to 4 mouse buttons
found X Axis
found Y Axis
found Button 0
found Button 1
found Button 2
found Button 3
Adapter key: \Registry\Machine\System\CurrentControlSet\Control\Video{70DC50FE-
FB2D-4BF2-BEB0-EAB6417827E1}\0000
Adapter key: \Registry\Machine\System\CurrentControlSet\Control\Video{70DC50FE-
FB2D-4BF2-BEB0-EAB6417827E1}\0000
Adapter: ati2dvag Version: 6.14.10.6430
JWS Classloader looking for: lwjglaudio
Failure locating OpenAL using classloader:java.lang.NoSuchMethodException: sun.m
isc.Launcher$AppClassLoader.findLibrary(java.lang.String)
Found 2 OpenAL paths
Testing ‘…\libs\win32’
Found OpenAL at ‘…\libs\win32’
Deleting GL context
Destroying directinput
Releasing DC
Destroy window
[/quote]

Interesting I am using JCreator Pro. Decided to try from command line with the following:

C:\java\simple\lwjgl\Test\classes>java -Dorg.lwjgl.Sys.debug=true -classpath .;c:\java\simple\lwjgl9\lwjgl-win32-0.9\lwjgl.jar org.lwjgl.examples.Game

and still get the exact same thing.

My package
http://www22.brinkster.com/mbowles/lwjgl_test.zip

Hmm, and where’s the lwjgl.dll placed? It might look like you’d need a:

java -Djava.library.path=c:\java\simple\lwjgl9\lwjgl-win32-0.9\ -Dorg.lwjgl.Sys.debug=true -classpath .;c:\java\simple\lwjgl9\lwjgl-win32-0.9\lwjgl.jar org.lwjgl.examples.Game

?