TUER: Truly Unusual Experience of Revolution, FPS using JOGL

The OpenGL menu is almost finished. It is extremely simple but it works. I hope there will be no more flickering under Windows. I will have this feature in the next version in a few days. Below is an example of the use of the new classes I wrote :

private final void initMainMenu(){
this.menu=new GLMenu(screenWidth/2.0f,screenHeight/2.0f,false,new TextRenderer(new Font(“SansSerif”,Font.BOLD,24)));
GLMenuItem resumeMenuItem=new GLMenuItem(“resume”);
resumeMenuItem.addActionListener(new ResumeGameActionListener(this));
this.menu.addGLMenuItem(resumeMenuItem);
GLMenuItem newMenuItem=new GLMenuItem(“new game”);
newMenuItem.addActionListener(new NewGameActionListener(this));
this.menu.addGLMenuItem(newMenuItem);
GLMenuItem loadMenuItem=new GLMenuItem(“load game”);
this.menu.addGLMenuItem(loadMenuItem);
GLMenuItem saveMenuItem=new GLMenuItem(“save game”);
this.menu.addGLMenuItem(saveMenuItem);
GLMenuItem aboutMenuItem=new GLMenuItem(“about”);
aboutMenuItem.addActionListener(new AboutActionListener());
this.menu.addGLMenuItem(aboutMenuItem);
GLMenuItem quitMenuItem=new GLMenuItem(“quit game”);
quitMenuItem.addActionListener(new QuitGameActionListener());
this.menu.addGLMenuItem(quitMenuItem);
this.canvas.addKeyListener(this.menu);
}

I have just updated the java archive of the game because the makefile doesn’t work anymore. I got this when I launch the jar produced by my makefile :

Exception in thread “AWT-EventQueue-0” java.lang.NoClassDefFoundError: main/GLMenuItem$1
at main.GLMenuItem.display(GLMenuItem.java:49)
at main.GLMenu.display(GLMenu.java:105)
at main.GameGLEventController.display(GameGLEventController.java:389)
at com.sun.opengl.impl.GLDrawableHelper.display(GLDrawableHelper.java:78)
at javax.media.opengl.GLCanvas$DisplayAction.run(GLCanvas.java:288)
at com.sun.opengl.impl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:194)
at javax.media.opengl.GLCanvas.maybeDoSingleThreadedWorkaround(GLCanvas.java:265)
at javax.media.opengl.GLCanvas.display(GLCanvas.java:130)
at javax.media.opengl.GLCanvas.paint(GLCanvas.java:142)
at sun.awt.RepaintArea.paintComponent(RepaintArea.java:248)
at sun.awt.X11.XRepaintArea.paintComponent(XRepaintArea.java:56)
at sun.awt.RepaintArea.paint(RepaintArea.java:224)
at sun.awt.X11.XComponentPeer.handleEvent(XComponentPeer.java:683)
at java.awt.Component.dispatchEventImpl(Component.java:4486)
at java.awt.Component.dispatchEvent(Component.java:4240)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)

The JVM does not find an enum defined in the separate file “MenuItemState.java” whereas this enum is in the jar. If someone had a solution, it would be useful. I can use ANT to build my jar correctly but many linux users prefer using a makefile.

On the other hand, these are the minor improvement in the game :

  • no more PopupMenu, I assume that there is no more flickering under Windows, I followed princec’s advice
  • a small ugly OpenGL menu
  • less memory usage : 32 MB at the beginning, only 9 MB after a minute instead of 63 MB last month
  • quicker loading : I stopped using ImageIcon to load images, I use ImageIO instead

you can try delete and rebuild from scratch again, plus your Manifest file can be on a wrong main-class if you changed it. This is perhaps Java that caches the classes at build time.

Thanks. I already checked it at first. My ANT script works but not the makefile. I didn’t change the main class location. The main class is found but not the only enum class of the whole project. I looked inside the jar, “MenuItemState.java” is inside the jar but the JVM looks for “main/GLMenuItem$1” instead of “main/MenuItemState”. I had the same problem with anonymous classes that I don’t use anymore. I don’t know how ANT does. WIth ANT, it works perfectly. Temporarly, I don’t advise my users to recompile the project by using the makefile until this problem is fixed.

what’s wrong about that makefile ? what command do you use ? I’ve always used the ant build-xml method to build and put in .jar whereas the makefile is usually delivered for a C build, isn’t it?

I use “jar cvmf manifest tuer.jar …”. The makefiles are usually delivered for a C build but are used with many other languages. Linux users prefer using a makefile, it is the only reason why I went on using it. As I still have no other choice, I will advise them to rather use the ANT script. I’ve improved the ANT script build.xml to perform all the operations done previously through several scripts. It is now possible to generate all the data files, generate the zip file containing the source code, compile the source code, build the unsigned Java archive, generate a key and sign the Java archive with this key.

I’m now working on the impacts and the cell-and-portal algorithm. As I have no holidays, it is a little bit hard. The menu is very very basic. It will be improved later. Can someone test the game under Microsoft Vista please? I would like to know if it works fine now.

Some students will reuse my engine to simulate the visit of a museum. Therefore, I will make it easier to add plugins and to customize all the look-and-feel. I need to use XML for the configuration files. I’ve thought about JDOM but it requires several Java archives. Has someone here already used JDOM through Java Webstart? Is it efficient to sign all the Java archives with the same certificate in order to avoid the users to need to click on “Ok” for each Java archive provided?

I have finally decided to use SAX. Now, I try to reduce the loading time by using java.nio.channels.FileChannel to read the float values not one by one, to put it directly in a FloatBuffer but it doesn’t work properly. The file is found but its like I read only some zeros. Does someone know how to use java.nio.channels.FileChannel to read floats?

depending the manner you write them, the read operations must be verified with integrity. To read properly a file you wrote into with [b]writeFloat/b, first open the file in read only mode. Then store the RandomAccessFile length(). Right after that, start to read 512 bytes each time. That looks so like :


// RandomAccessFile's always use the FileChannel's to read and write.
RandomAccessFile file = new RandomAccessFile((File), "r");
long len = file.length();
Vector<Float> floatValues = new Vector<Float>();
while(file.getFilePointer() < len - 1)
       floatValues.add(file.readFloat());

:slight_smile:

Runs on my Vista laptop. Though I could not find my mouse pointer in the menu, and also I could not shoot. I could turn and stuff with the mouse though fine. Does a mouse click shoot? I had sound.

A file written with a Java application is always in Big Endian. I wanted to use FileChannel to fill directly nio buffers without reading byte per byte and I’ve finally succeeded in this. Thanks for your suggestion. Nevertheless, file.readFloat() does not use optimally the channel, it reads still byte per byte whereas I wanted to read block by block. Now my solution works.

The mouse pointer does not appear in the menu, it is the expected behaviour. You can choose an item through the menu by using the keyboard. I think you were able to shoot as you heard the sound but many effects are still missing, explosions, rockets, impacts… It doesn’t help to realize that you’re shooting, I admit. I’m going to work on plenty of things at the same time, I’ll try to do my best to improve these aspects. Thank you very very much for testing my game.

As it is really time to improve the usability of the game, today I’m going to add some small indications when you pause the game and when you die. I will update the source and the game itself at the evening. I have reduced again the use of memory. ImageIO.read(URL url) is asynchronous, this behavior remains even though I use a MediaTracker. Then, I have forgiven to use this method. I’m inverting all the textures to be able to use directly TextureIO.newTexture(…) without needing to invert the image with ImageUtil.flipImageVertically(…). This need appeared when I began using JOGL 1.1.0. The workaround costs too much memory, it is easier to invert all the images used to create the textures. I’m still open to your suggestions. broumbroum was right, all the IO classes have been rewritten to use FileChannel but if they still allow byte per byte reading, it is faster to read block per block when you need to read a large amount of data.

The update has been done a few minutes ago.

Bad news :
java.lang.IllegalArgumentException: URI is not hierarchical
at java.io.File.(File.java:363)
at main.GameModel.(GameModel.java:448)
at main.GameView.(GameView.java:32)
at connection.GameServiceProvider.main(GameServiceProvider.java:81)

It seems not to be possible to use an URI to read a file that is inside a Java archive. Therefore I can’t use FileChannel.
I’ve corrected some bugs :

  • objects became unbreakable after the game had been paused once
  • the crosshair and the information panel disappeared on some video chipsets
    As some people asked me to display something when the player dies, I did it. Tomorrow, I’m going to keep concentrate on the computations of the impacts and blending some textures to get a nice effect.

I’m going to update the game anew maybe tonight. I corrected some bugs in the menu and in the “pause” item. I’m still working on the impacts. The computations allowing to determine the point of impact are simple as the geometry of the level is completely orthogonal, only some equations of the first degree are required to perform this. I’m improving the documentation of the source code and I’m preparing a progress bar too.

The equations to compute the impacts in my simplified case are ready to be implemented. I hesitate in implementing the equations to compute the impacts in the general case by throwing a ray into a finite section of a planar surface. It would help me to prepare some future features, for example allowing the player to look up and down. It would make it easier to add weapons whose projectiles don’t have a rectilinear trajectory (grenades, sort of old railgun like the one in Quake 2…).

As you noticed, the loading progress is now displayed. I still plan to build a true progress bar in some days.

The method below computes the impact point in the planar surface Oxz with orthogonal walls by using the previous and the next position of the projectile :

public static final Impact computeImpactFromTargetoryBipoint(float x1,float z1,
float x2,float z2,float wx1,float wz1,float wx2,float wz2,float wnx,
float wnz){
boolean isHorizontal=(wnz!=0);
if(x1==x2)
{if(!isHorizontal)
{if(x1==wx1)
{if(wz1>wz2)
{if(wz2<=z2 && z2<=wz1)
{if(z1>z2)
return(new Impact(x1,0.0f,wz1,wnx,0,wnz));
else
return(new Impact(x1,0.0f,wz2,wnx,0,wnz));
}
else
return(null);
}
else
{if(wz1<=z2 && z2<=wz2)
{if(z1>z2)
return(new Impact(x1,0.0f,wz2,wnx,0,wnz));
else
return(new Impact(x1,0.0f,wz1,wnx,0,wnz));
}
else
return(null);
}
}
else
return(null);
}
else
{if(wx1>wx2)
{if(wx2<=x1 && x1<=wx1)
{if(z1>z2)
{if(z2<=wz1 && wz1<=z1)
return(new Impact(x1,0.0f,wz1,wnx,0,wnz));
else
return(null);
}
else
{if(z1<=wz1 && wz1<=z2)
return(new Impact(x1,0.0f,wz1,wnx,0,wnz));
else
return(null);
}
}
else
return(null);
}
else
{if(wx1<=x1 && x1<=wx2)
{if(z1>z2)
{if(z2<=wz1 && wz1<=z1)
return(new Impact(x1,0.0f,wz1,wnx,0,wnz));
else
return(null);
}
else
{if(z1<=wz1 && wz1<=z2)
return(new Impact(x1,0.0f,wz1,wnx,0,wnz));
else
return(null);
}
}
else
return(null);
}
}
}
else
{float a=(z2-z1)/(x2-x1);
float b=z1-(ax1);
float impx,impz;
if(!isHorizontal)
{impx=wx1;
impz=(a
impx)+b;
if(wz1>wz2)
{if(wz2<=impz && impz<=wz1)
return(new Impact(impx,0.0f,impz,wnx,0,wnz));
else
return(null);
}
else
{if(wz1<=impz && impz<=wz2)
return(new Impact(impx,0.0f,impz,wnx,0,wnz));
else
return(null);
}
}
else
{if(a!=0)
{impz=wz1;
impx=(impz-b)/a;
if(wx1>wx2)
{if(wx2<=impx && impx<=wx1)
return(new Impact(impx,0.0f,impz,wnx,0,wnz));
else
return(null);
}
else
{if(wx1<=impx && impx<=wx2)
return(new Impact(impx,0.0f,impz,wnx,0,wnz));
else
return(null);
}
}
else
{if(z1==wz1)
{if(wx1>wx2)
{if(wx2<=x2 && x2<=wx1)
{if(x1>x2)
return(new Impact(wx1,0.0f,z1,wnx,0,wnz));
else
return(new Impact(wx2,0.0f,z1,wnx,0,wnz));
}
else
return(null);
}
else
{if(wx1<=x2 && x2<=wx2)
{if(x1>x2)
return(new Impact(wx2,0.0f,z1,wnx,0,wnz));
else
return(new Impact(wx1,0.0f,z1,wnx,0,wnz));
}
else
return(null);
}
}
else
return(null);

                  }
             }
        }      
}

Notice that I did my best to avoid any division by zero of course. Comparing two floats by using == might be dangerous but it depends on the way we have got them. in my case, it is not dangerous as they have been read from a file. It would be more dangerous if I had got them after some computations and some conversions from double to float, from float to double and then from double to float. I will try to draw a true progress bar tomorrow if I’m not too much tired.

The progress bar that I’ve written in JOGL is working:

http://tuer.tuxfamily.org/screenshots/snapshot_progressbar.png

I take into account the suggestions that people have made here. EgonOlsen suggested me to put a progress bar some months ago and princec advised me not to use SWING. I’ve done what they suggested and it works fine. WARNING: if you want to reuse my components, don’t forget to disable the depth test and use gluOrtho2D before. I hesitate in doing these tests in my methods.

I’m updating the game right now. There are only some very small improvements. I will try to finish to implements the impacts. I wish you a merry Christmas and a happy new year.

The chipset VIA/S3G UniChrome IGP is still not supported by my game. Other tests under Microsoft Windows XP and Vista have proven that there are some problems with other chipsets. Sometimes, the progress bar becomes frozen or the game refuses to start and there is still this exception :

javax.media.opengl.GLException: Error swapping buffers
at com.sun.opengl.impl.windows.WindowsOnscreenGLDrawable.swapBuffers(WindowsOnscreenGLDrawable.java:132)
at javax.media.opengl.GLCanvas$SwapBuffersAction.run(GLCanvas.java:295)
at com.sun.opengl.impl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:194)
at javax.media.opengl.GLCanvas.maybeDoSingleThreadedWorkaround(GLCanvas.java:265)
at javax.media.opengl.GLCanvas.swapBuffers(GLCanvas.java:245)
at main.GameGLEventController.display(GameGLEventController.java:574)
at com.sun.opengl.impl.GLDrawableHelper.display(GLDrawableHelper.java:78)
at javax.media.opengl.GLCanvas$DisplayAction.run(GLCanvas.java:288)
at com.sun.opengl.impl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:194)
at javax.media.opengl.GLCanvas$DisplayOnEventDispatchThreadAction.run(GLCanvas.java:305)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

If you have this problem with a recent graphics card, please let me know. Some VIA, Sis and ATI chipsets are currently not supported. The “about” menu works bad under Windows.