From f75088cb63c181874886401b3fa52df7f52664c0 Mon Sep 17 00:00:00 2001 From: Brian Matzon Date: Tue, 25 Jan 2005 20:57:02 +0000 Subject: [PATCH] removed more obsolete stuff --- doc/openal_c-to-java.html | 87 ---------- doc/tutorial/intro.html | 150 ----------------- doc/tutorial/openal_basics.html | 153 ------------------ doc/tutorial/skeleton_code.html | 275 -------------------------------- 4 files changed, 665 deletions(-) delete mode 100644 doc/openal_c-to-java.html delete mode 100644 doc/tutorial/intro.html delete mode 100644 doc/tutorial/openal_basics.html delete mode 100644 doc/tutorial/skeleton_code.html diff --git a/doc/openal_c-to-java.html b/doc/openal_c-to-java.html deleted file mode 100644 index 2fda3eaa..00000000 --- a/doc/openal_c-to-java.html +++ /dev/null @@ -1,87 +0,0 @@ - - - - OpenAL Tutoral - - - - - -

Array Conversion
-(by Brian Matzon <brian@matzon.dk>)
-

-1.0 About this document
-This document describes the typical rules for converting arrays often used in -C/C++ OpenAL (and indeed OpenGL too)  code.
-It is not bullet proof, but should handle most cases.
-
-1.1 Array to ByteBuffer
-
When using an array of some data type in C/C++ -you will typically convert that
-to the corresponding ByteBuffer type. ie:

ALfloat -floatv[3];

-

becomes

-

-FloatBuffer floatv = createFloatBuffer(3);

-

In this example, createFloatBuffer -is this utility method:

-

-public FloatBuffer createFloatBuffer(int size) {
-  -//allocate bytebuffer, using 4 bytes per float
-  -ByteBuffer temp = ByteBuffer.allocateDirect(4*size);
-  -temp.order(ByteOrder.nativeOrder());
-  -
-  -return temp.asFloatBuffer();
-}

-

-1.2 Examples
-Using the above FloatBuffer, you would typically use it like this (examples -taken from altest.c/ALTest.java):

-

-1.2.1 Example 1

-

-alGetListenerfv(AL_POSITION, floatv);

-

-becomes

-

-al.getListenerfv(AL.POSITION, Sys.getDirectBufferAddress(floatv));

-

1.2.2 Example 2

-

-if (floatv[0] != 100.0)) {

-

becomes:

-

-if (floatv.get(0) != 100.0f) {

-

1.2.3 Example 3

-

-alGetListener3f(AL_POSITION, &floatv[0],
-                             -&floatv[1],
-                             -&floatv[2]);

-

becomes

-

-al.getListener3f(AL.POSITION, Sys.getDirectBufferAddress(floatv),
-                              -Sys.getDirectBufferAddress(floatv) + 4,
-                              -Sys.getDirectBufferAddress(floatv) + 8);

-

the last case is a bit special, since we start of by getting the base -address of the buffer, and then add the datatype size to the base address
-to get the address of that specific index. This is just how it has to -be in Java.

- - \ No newline at end of file diff --git a/doc/tutorial/intro.html b/doc/tutorial/intro.html deleted file mode 100644 index ce9dbc74..00000000 --- a/doc/tutorial/intro.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - -Lightweight Java Game Library Tutorial Index - - - - - -

Lightweight Java Game Library

-

Tutorial

-

Written by Caspian Rychlik-Prince

-

Please direct comments, errata, and flames to the author at cix_foo@users.sourceforge.net

-

Last modified 23 August 2002 -

-

 

-

1.0 Introduction

-

The Lightweight Java Game Library (LWJGL) is a solution aimed directly at -professional and amateur Java programmers alike to enable commercial quality -games to be written in Java. This tutorial is nonetheless aimed at experienced -programmers and won't be explaining some obvious techniques.

-

LWJGL is not meant to make writing games particularly easy; it is -primarily an enabling technology which allows developers to get at -resources that are simply otherwise unavailable or poorly implemented on the -existing Java platform. We anticipate that the LWJGL will, through evolution and -extension, become the foundation for more complete game libraries and "game -engines" as they have popularly become known, and hide some of the new -evils we have had to expose in the APIs.

-

2.0 Contents

-

 

-

3.0 Aims & Design

-

Because the LWJGL API is not meant to be a fully featured game engine it has -been ruthlessly pruned of all non-essential code. Its ultimate philosophy is -that it provides the bare minimum of API functionality which will let a -game programmer produce games in Java without having to write native code in -order to get performance or access some hardware feature not exposed -by Java 2. We settled on using two other open technologies as our major -foundations, namely OpenGL and OpenAL for graphics and sound respectively.

-

A sub-requirement of the LWJGL is that it be freed Java programmers from the -requirement to ship a whole JRE with their games. Currently the Sun licensing -terms dictate that J2SE be shipped in its entirety, even for the tiniest of -demos. As this could easily triple the size of a demo and discourage end users -with configuration issues we have made it a primary concern that games written -using LWJGL can be compiled into completely standalone native binary executables -by compilers such as GNU's GCJ and Excelsior's JET. We have done this by -implementing the library in such a way that no dependencies on Sun's -proprietry JRE binaries are present in the library.

-

3.1 General API

-

The general API gives us the foundations of game programming: we have a -Display class, for initialising the display and querying its available modes; we -have a Math class to provide us with some floating point maths functions (rather -than the double-precision ones provided by Java), and matrix batch operations; -and a Sys class, which gives us our most useful gaming functions: the -ability to get the address of a direct byte buffer so we can cache it on the -Java side of the JNI barrier, and hence access all those lovely hardware calls -we need for performance; and the ability to use the system's hires timer, -which is so critical for animation timing. In addition we can also create a -direct byte buffer at any address in memory.

-

The Evil Of Pointers And What It Means For Security

-

Yes, we have exposed pointers to Java programmers. Yes, you can write -to just about any bit of memory you so please, and cause untold havoc. You can -break things. You can bypass security constraints and exploit the dreaded buffer -vuln.

-

But why? Because without pointers, all those nice easy native API -calls would suddenly become complex and behave slightly differently to their C -counterparts, and require us to pass direct ByteBuffers to JNI for every call. -This requires that every single call which takes a pointer calls the JNI method -GetDirectBufferAddress every time, which is an unnecessary overhead.

-

The implications for security are simple and final: your game can no -longer be considered secure and part of the Java security model. This puts -it in exactly the same boat as any other application on the user's system. This -also means you will not be able to use it in applets or with Webstart without -getting your code signed and trusted. LWJGL itself will not be signed nor -trusted; you are expected to deliver it bundled in with every application you -ship and verify that your entire distribution is safe.

-

We feel that our target developer, the commercial game developer, should not -be concerned with this issue as the status quo is merely maintained from the old -ways of programming with any other language; and used wisely, your exposure to -pointers is unlikely to cause you any problems.

-

If you are concerned about security, or wish to write games which will run as -applets or from Webstart, or would rather have a full game library which takes -care of things for you, you don't want to use LWJGL at all - it's that simple! -What you need is Sun's Java Gaming Profile, or Java3D. If you feel a need to -argue, you're using LWJGL for the wrong reasons.

-

3.2 Graphics

-

Graphics is based on the latest OpenGL1.4, and all the extensions we could -implement that might be vaguely useful for games programmers. These include all -of Nvidia's and ATI's proprietry extensions, and all the ARB extensions, -and most of the EXT extensions, as well as numerous other miscellaneous ones.

-

For Windows programmers, our primary target, the WGL extensions are present.

-

All OpenGL functions that take pointers are passed ints. These pointers can -be obtained from direct ByteBuffers using the Sys.getDirectBufferAddress() -method. There are a very few native methods that return pointers as ints as -well. Be sure to read the caveat about using pointers in Java!

-

3.3 Sounds

-

Sound is based on the latest OpenAL1.0 specification. The LWJGL binary -distribution includes the OpenAL libraries.

-

3.4 Input

-

Input can be a complicated topic. A user can have all sorts of strange fancy -force-feedback hardware installed on their systems, with scrolly knobs and -twistgrips and bristling with many buttons. However, the vast majority of gamers -have just a keyboard and a mouse; some of them have analogue joysticks too, and -some of them have a gamepad attached from some console or other. For our first -cut of the input library we've just kept it all rather simple, and decided that -there is but one of each of these devices, and that force feedback and multiple -potentiometers is a feature we may add another time.

-

So in the interests of keeping things simple, the four input classes - -Keyboard, Mouse, Gamepad and Joystick - are all static, and can all be polled -once per game loop iteration to determine where they've moved since you last -looked and what buttons are down at the time. The Gamepad and Keyboard may -additionally support buffering which is a more reliable way of detecting -rapid changes of state which may occur rather more quickly than your framerate.

-

3.5 Maths

-

Java's maths performance leaves much to be desired, particularly with respect -to bulk operations for 3D rendering engines. The main problem is that the -existing maths libraries use double precision when single precision is entirely -adequate for most realtime games programming; and that no clever -processor-specific optimisations can be done because the Hotspot compiler is -simply not supplied enough semantic context to understand that it could use some -special SIMD instruction to achieve the effect you desire in a fraction of the -cycles. Furthermore, all maths in Java is done in Java - and once you've -computed the results you usually have to subsequently copy them into a buffer to -pass to a native rendering method in OpenGL anyway.

-

The Math class provides two totally generic vector operators for unary -and binary vector operations performed on direct ByteBuffers containing packed -floating point vectors. The idea is to set up the source(s) of the operations -and then perform a single call to JNI to perform a highly optimised operation -on the whole lot in one go. The JNI code is specially optimised for the common -cases in 3d games programming to use processor-specific instructions and take -advantage, where feasible, of memory caching architecture. And the end result is -placed directly back in memory, ready to simply send as a pointer direct to -OpenGL or some other API.

-

In addition we provide implementations of common Vector and Matrix sizes -similar to those provided by the javax.vecmath package, but ours are open -source and available without downloading the whole of Java3D.

-

 

- - - - diff --git a/doc/tutorial/openal_basics.html b/doc/tutorial/openal_basics.html deleted file mode 100644 index 205b6d2d..00000000 --- a/doc/tutorial/openal_basics.html +++ /dev/null @@ -1,153 +0,0 @@ - - - - OpenAL Tutoral - - - - - - -

OpenAL Tutorial
-(by Brian Matzon <brian@matzon.dk>)
-

-1.0 OpenAL Basics
-Before embarking on our little OpenAL adventure, some tools are needed.
-
-1.0.1 Ingredients
-Head on over to Creatives site -and snag a copy of the OpenAL specification along with a copy of the Programmers -reference.
-If you haven't already done so, get a copy of the OpenAL runtime environment -too (and install it).
-
-1.1 OpenAL theory
-Uhm... I'm not going to write this... In all honesty reading the specification -would be a good thing before continuing - but it isn't required...
-
-1.2 Basic setup
-Lets start out by creating a skeleton class for some very basic sound. We'll -start of by creating the required OpenAL object
-

import -org.lwjgl.openal.AL;
-
-public class PlayTest {
-   
-  /** OpenAL instance */
-  protected AL al;
-
- -  /**
-   * Creates an instance of PlayTest
-   */
-  public PlayTest() {
-    try {
-
          - al = new AL();
-      al.create();
-   } catch (Exception e) {
-      e.printStackTrace();
-    }

-  }
-}

-

1.3 Buffer and Source creation
-Now that we have created the AL instance, we need to create -two things to actually get some sound. We need to create a buffer to hold -sound data, and a source that is to play the sound data.
-Lets start of by creating one source, and one buffer:

-

- -  //create one IntBuffer as buffer and one as source
-  //createIntBuffer is a utility method which allocates a direct ByteBuffer in native order
-  IntBuffer buffers = createIntBuffer(1);
-  IntBuffer sources = createIntBuffer(1);
-
-  //generate buffers and sources
-  al.genBuffers(1, Sys.getDirectBufferAddress(buffers));
-  al.genSources(1, Sys.getDirectBufferAddress(sources)); -
-

-

There, all set for actually loading some sound data into the buffer.
-

-1.4 Loading sound data and setting up a buffer
-Now that we have a buffer, we need to load some sound data into this buffer. -This is done using the al.bufferData method. In our example we will -"cheat" a bit, by using the WaveData class to load -a wave file, and copy this into the buffer:
-

  -//load wave data
-  WaveData wavefile = WaveData.create("mywavefile.wav");
-        
-  //copy to buffer
-  al.bufferData(buffers.get(0), wavefile.format, Sys.getDirectBufferAddress(wavefile.data), wavefile.data.capacity(), wavefile.samplerate);
-        
-  //unload file again
-  wavefile.dispose();        
-

-Having loaded the data, we pass it to bufferData. Once the buffer -has been filled with sound data, we unload it from the system using wavefile.dispose(). -Don't worry about deleting it this soon - the sound data has been copied -to the buffer.
-
-1.5 Associating sources and buffers
-To associate a source to a buffer we set the integer BUFFER attribute on -the source, and assign it a value of the buffer to play:
-

  -//set up source input
-  al.sourcei(sources.get(0), AL.BUFFER, buffers.get(0));

-

-1.6 Setting source properties
-Having set up the source, it is time to set some attributes on the source -- there are many that can be set, but in this example we only set the looping -attribute to true by doing the following:
-

  -//loop source
-  al.sourcei(sources.get(0), AL.LOOPING, AL.TRUE);

-

-1.7 Sound...
-
There, ready to play the sound, do this using the sourcePlay method -of the AL class. to stop and pause use sourcePause and -sourceStop respectively, and supply the source to affect:
-

  -//play source 0
-  al.sourcePlay(sources.get(0));
-       
-  //wait 5 secs
-  try {
-    System.out.println("Waiting 5 seconds for sound to complete");
-    Thread.sleep(5000);
-  } catch (InterruptedException inte) {
-  }
-       
-  //stop source 0
-  al.sourceStop(sources.get(0));

-1.8 Cleaning up
-
Having had loads of fun playing a sound (!), it is now time to do some -house chores. We need to clean up what we have created, this amounts to:
- - deleting source and buffer
- - destroying AL
-as is shown here:
-
-

  -//delete buffers and sources
-  al.deleteSources(1, Sys.getDirectBufferAddress(sources));
-  al.deleteBuffers(1, Sys.getDirectBufferAddress(buffers));
-        
-  //shutdown
-  al.destroy();
-
-

-There, all set. Now you should be able to play some basic sound!
-This tutorial is rather short, and the above examples feature no error checking. -For the complete source code, look at the classes in the
-org.lwjgl.test.openal package.
- - diff --git a/doc/tutorial/skeleton_code.html b/doc/tutorial/skeleton_code.html deleted file mode 100644 index 5a40765e..00000000 --- a/doc/tutorial/skeleton_code.html +++ /dev/null @@ -1,275 +0,0 @@ - - - - - - - -4 - - - - -

4.0 Skeleton Game Code

-

So now you want to know how to just get stuck in and start writing games. -First you need to understand a couple of game programming design patterns and -why they'll make your life easier; and then you'll want to fill in the gaps in a -bit of skeleton code that we're going to discuss below.

-

4.1 Design Decisions

-

4.1.1 Static Game Class

-

How many instances of your game do you expect to be running in a JVM? One, -and only one. Given this, you may feel the urge to implement the singleton -pattern on your game, where your game class holds a single instance of itself -and a method to retrieve that instance, something like:

-

public -class Game {
-   
-    /** The single instance of the Game */
-    private final Game game = new Game();
-
-    /** Don't allow construction from anywhere else */
-    private Game() {

-    }
-

-    /** @return the game instance */
-    public static Game getGame() {
-        return game;

-    }
-
-    /** Start a new game */
-    public void newGame() {
-        // etc
-    }
-
-    /** The main game loop */
-    public void mainLoop() {
-        // etc
-    }
-
-    // etc
-}

-

However this does result in code all over your application calling -Game.getGame().someMethod() - and to what end? It might look like -object-oriented code but in reality you're just making things harder for -yourself. It's far more intuitive to write your class purely statically, like -this:

-

public -class Game {
-
-    /** Don't allow construction from anywhere else */
-    private Game() {

-    }
-
-    /** Start a new game */
-    public static void newGame() {
-        // etc
-    }
-
-    /** The main game loop */
-    public static void mainLoop() {
-        // etc
-    }
-
-    // etc
-}

-

Now you can just call your methods directly on the Game class. We're going to -use this pattern in the forthcoming skeleton game code.

-

4.1.2 About Threads and Timeslicing

-

There is a tendency for Java programs to be heavily multithreaded, simply -because you can in Java, whereas it is exceedingly difficult to do -properly in C++. However, you are likely to fall into a number of pitfalls in -game programming above and beyond those experienced in general multithreaded -programming:

-

Firstly, threads were designed a long time ago for a specific purpose, and -that purpose is keeping the processor busy whilst some slow I/O operation is -being carried out. How many slow I/O operations are you going to do in your -game? Apart from loading the graphics, sounds, and level data at the start - -none (unless you're doing networking but that's a whole other issue).

-

What does this mean for you? Well, in normal Java, programmers will tend to -set off a number of threads and expect them to more or less behave like time -slices rather than threads. Time slices work in a rather different -way to threads: each is executed, in turn, for a finite amount of time. You can -more or less guarantee that a slice will execute for its allotted time, and that -all slices will get a look-in.

-

Threads don't work like this. To put it bluntly, you can't accurately -predict when a thread is going to execute (or if it will ever be executed), or -even how long it will execute for. Therefore you should not be using threads to -do stuff that you expect to occur in a timely fashion. This includes collision -detection, animation, sound playback and device input, and the -ultimate blow, event handling.

-

In the absence of threads to do this useful stuff, we have to resort to a single-threaded -model where the game effectively runs in one, very busy, thread - the -"main loop". This is quite convenient, however, because it highlights -another problem with multithreaded game code that is not immediately obvious.

-

4.1.3 About Threads and Hardware

-

Your machine's hardware is only ever in one state at a time, unless -it is some kind of quantum computer. The device drivers for the hardware - -namely OpenGL and the like - keep track of this state in order to send the -correct hardware setup commands to the device. Can you imagine what might happen -if one thread is trying to do some drawing at the same time that another thread -is trying to do some drawing? Yes, you get a mess. You will discover that in -order to draw in a thread in OpenGL that you need to associate the current -rendering thread with the current state of the hardware (the -"context"). Suddenly you need to synchronize every method which can -alter the hardware state. Suddenly your application looks incredibly -complicated and runs like a dog! So much for threads.

-

So be aware of this next time you think it's a good idea to load your -textures in a background thread, and remember that only one thread - the main -thread - is allowed to execute any commands on your hardware devices.

-

It is for this reason that we use polling to read input devices as -well. Not to mention the fact that we can't guarantee that an event loop will be -executed every game frame, and so our input will be erratic.

-

4.1.4 Object-orientation

-

Object-orientation is good when it's done right. It makes your code -much, much, easier to understand and work on. However you may be led astray by parrots -who repeat mantras. There are some programmers that say everything should -be private and you should expose your instance variables with getters and -setters. The Hotspot virtual machine is even cleverly optimised to make this -operation almost entirely free. But wait! Ask yourself why you're filling -your classes up with getters and setters when a dot would do the same job -without any need to maintain it.

-

You're writing a game: the source code is probably only going to be used -once, or by a very few people. Most of your game code is so unique to your -actual game that it is disposable code. So save yourself some effort and -use a dot if you can. A critical mistake I have observed time and time again in -object-oriented projects is to get so bogged down trying to design a perfect -object-oriented model that the project takes absolutely ages to design. Before -you know it there are hundreds of getters and setters to maintain, and -interfaces all over the place to keep the reuse of your classes to a maximum - -when all along the project design goal was not reuse but to get the bloody -thing finished on time and under budget!

-

Your mileage may vary...

-

4.2 Show Me The Money

-

Ok, ok, without further ado, here is a skeleton listing which you can use to -write a fullscreen Java game using LWJGL. Because we're games programmers, we -don't want to do a Hello World as we'd probably rather shoot it. But before we -can make bullets we must pay homage to the rotating square!

-

import -org.lwjgl.*;
-import org.lwjgl.opengl.*;
-import org.lwjgl.input.*;
-
-
-public -final class Game {
-    static {
-        try {
-            DisplayMode[] modes = Display.getAvailableDisplayModes();
-            System.out.println("Available display modes:");
-            for (int i = 0; i < modes.length; i ++)
-                -System.out.println(modes[i]);
-            // For now let's just pick a mode we're certain to have
-            Display.create(new DisplayMode(640, 480, 16, 60), true);
-            System.out.println("Created display.");
-        } catch (Exception e) {
-            System.err.println("Failed to create display due to "+e);
-            System.exit(1);
-        }
-    }
-
-    public static final GL gl = new GL(16, 0, 16, 8);
-    static {
-        try {
-            gl.create();
-            System.out.println("Created OpenGL.");
-        } catch (Exception e) {
-            System.err.println("Failed to create OpenGL due to "+e);
-            System.exit(1);
-        }
-    }
-    public static final GLU glu = new GLU(gl);
-
-    /** Is the game finished? */
-    private static boolean finished;
-
-    /** A rotating square! */
-    private static float angle;
-
-    /**
-     * No construction allowed
-     */
-    private Game() {
-    }
-
-    public static void main(String[] arguments) {
-        try {
-            init();
-            while (!finished) {
-                -Keyboard.poll();
-                -mainLoop();
-                -render();
-                -gl.swapBuffers();
-            }
   
-        } catch (Throwable t) {
-            -t.printStackTrace();
-        } finally {
-            cleanup();
-        }
-    }
-
-    /**
-     * All calculations are done in here
-     */
-    private static void mainLoop() {
-        angle += 1f;
-        if (angle > 360.0f)
-            angle = 0.0f;
-
-        Keyboard.poll(); -
-        if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE))
-            finished = true;
-    }
-
-    /**
-     * All rendering is done in here
-     */
-    private static void render() {
-        gl.clear(GL.COLOR_BUFFER_BIT);
-        gl.pushMatrix();
-        gl.translatef(Display.getWidth() / 2, Display.getHeight() / 2, 0.0f);
-        gl.rotatef(angle, 0, 0, 1.0f);
-        gl.begin(GL.QUADS);
-        gl.vertex2i(-50, -50);
-        gl.vertex2i(50, -50);
-        gl.vertex2i(50, 50);
-        gl.vertex2i(-50, 50);
-        gl.end();
-        gl.popMatrix();
-    }
-
-    /**
-     * Initialize
-     */
-    private static void init() throws Exception {
-        Keyboard.create();
-        // Go into orthographic projection mode.
-        gl.matrixMode(GL.PROJECTION);
-        gl.loadIdentity();
-        glu.ortho2D(0, Display.getWidth(), 0, Display.getHeight());
-        gl.matrixMode(GL.MODELVIEW);
-        gl.loadIdentity();
-        gl.viewport(0, 0, Display.getWidth(), Display.getHeight());
-        // Fix the refresh rate to the display frequency.
-        gl.wglSwapIntervalEXT(1);
-    }
-
-    /**
-     * Cleanup
-     */
-    private static void cleanup() {
-        Keyboard.destroy();
-   
          gl.destroy();
-        Display.destroy();
-    }
-}

- - - -