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 @@ - - -
-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.
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 -
-- -
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 @@ - - - -
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.
-
-//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();
-
-//set up source input
- al.sourcei(sources.get(0), AL.BUFFER, buffers.get(0));
-
-//loop source
- al.sourcei(sources.get(0), AL.LOOPING, AL.TRUE);
-
-//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));
-//delete buffers and sources
- al.deleteSources(1, Sys.getDirectBufferAddress(sources));
- al.deleteBuffers(1, Sys.getDirectBufferAddress(buffers));
-
- //shutdown
- al.destroy();
-
-
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();
- }
-}