Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » jalleg Java binding for Allegro ready to be used

This thread is locked; no one can reply to it. rss feed Print
jalleg Java binding for Allegro ready to be used
gillius
Member #119
April 2000

I've completed binding essentially all of Allegro and its addons in my jalleg Java language binding for Allegro and deployed a snapshot to the OSSRH (snapshots for Maven Central). That means you can have your Java build with Maven or Gradle automatically download everything you need for Allegro development. Only a few methods are missing that were hard to map, and it might be possible some of the bindings may need tweaking.

I currently only have included pre-built Allegro Windows 64 bit DLL but if anyone can provide and/or test in Linux I'd appreciate it. Theoretically this should work in Android as well.

To build and run you need JDK 7 or later. If you just want to run the current example you only need JDK 7 64 bit for Windows or later version, you can download a pre-compiled zip, unpack and run the bat file.

There are a few examples but the default one that runs is a ball and paddle game using a handful of Allegro features:

  • Display and primitives addon

  • Font addon for scores

  • Keyboard: A/Z left player, up/down right player

  • Mouse: click where you want the paddle to be

  • Joystick: controls the right player

  • Haptics addon: if you have for example XBox controller as your joystick, you get rumble effect when ball hits

  • Audio addon: sound effects generated by square waves

{"name":"BallAndPaddleExample.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/9\/79dbc6949eb903b87993b07f0647614b.png","w":642,"h":528,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/9\/79dbc6949eb903b87993b07f0647614b"}BallAndPaddleExample.png

Soon I will try a pull request to add jalleg as an Allegro 5 binding on liballeg.org.

Gillius
Gillius's Programming -- https://gillius.org/

amarillion
Member #940
January 2001
avatar

Very cool, I'm looking forward to giving this a try

gillius
Member #119
April 2000

Please do, no one else but myself have tried it yet, although I've run it on multiple machines. I'm especially interested if anyone who works with Allegro on Linux can try it, part of the point of this is to be cross-platform and I'm not sure how Allegro is loaded there. I also don't understand about al_run_main and how it's required on OSX and if it still applies in Java.

Gillius
Gillius's Programming -- https://gillius.org/

Rodolfo Lam
Member #16,045
August 2015

Very much appreciated. Will test whenever a time window opens.

Not really well versed at Java, but this might be enough to finally make me jump on the wagon properly.

gillius
Member #119
April 2000

I'm willing to help where I can. One of my aspirations for this project is to make a tutorial eventually of "how to get into programming via Allegro and game dev" that would kind of build off of assumed basic programming knowledge (like what is a variable, loop, function, etc.) but start with install of Java and IDE tools and build something simple.

EDIT: I started the tutorial, it is here: https://github.com/gillius/jalleg/wiki/Allegro-for-new-Java-developers.

I know Allegro isn't going to take the world by storm for real dev, and certainly neither jalleg. But, Allegro and game dev was instrumental in inspiring me to learn how to program and really get into this career and so I feel that Java and other JVM languages like JavaScript perhaps are an easier entry point than C. Allegro ties into that because it is so crazy simple to build a simple retro-style game, which is more than enough to get into the basics of programming and game design. Allegro is the easiest game dev environment I've seen outside of the "point and click" game assembly things out there which really I consider some of those more like level editors than dev environments.

My other goal for this is totally self-serving and that is just for fun. I program typical line-of-business software for a job now and miss those days I could just hack on a game on a weekend.

Gillius
Gillius's Programming -- https://gillius.org/

bamccaig
Member #7,536
July 2006
avatar

If I can find the time I'll do my best to get it running in Linux. That is not tonight though. If you really want to get it done I suggest joining IRC and bringing it up daily. Somebody should make it happen before long if you do. :) The same goes for OS X. I do not have any OS X machines, but I almost know for certain that some in IRC do.

gillius
Member #119
April 2000

What I need to know to make the Linux thing work is where I get the .so. Right now I just assume that the so is called liballegro_monolith-5.2.so and is located in the standard ldconfig path. If that assumption is correct then jalleg theoretically should just work. The alternative is for there to exist a mostly static-linked so (dynamic to libc/ldlinux/etc. of course as required) that I can put into my JAR file, then jalleg will unpack and load it as it does DLL on Windows.

Gillius
Gillius's Programming -- https://gillius.org/

bamccaig
Member #7,536
July 2006
avatar

Most people will not have a monolith library in Linux. It's possible to get one, I think, though I've never built one. The defaults only build the separate addons, as far as I know. I think that the monolith build started as a Windows creation to make it easier to setup Visual Studio and the like for beginners... In practice, you'd expect to find $PREFIX/lib/liballegro.so, $PREFIX/lib/liballegro_image.so, etc., where $PREFIX is one of /usr or /usr/local (usually). I'd imagine that the Java binding framework will search the usual paths though so the "where" probably doesn't matter so much. I can attempt to build a monolith library and see if that works, but I'm not sure.

gillius
Member #119
April 2000

OK, unfortunately, the binding would be different without the monolith library -- the way JNA works there would be a separate class for each component. However, it might not be that hard to refactor as I would just need to copy/paste the relevant functions into different classes and in the source I have them mostly sorted by the same pages as in the liballeg.org documentation (so each addon is in its own section).

It would be a little more work on the dynamic DLL/so loader as there would be a lot more files to unpack, and a little more work on the user of the library as there would be a separate import for each library instead of one import of AllegroLibrary, but it would allow the user to conditionally exclude DLLs/sos in their custom distribution to reduce the size. This was on my list of things I thought I'd have to do at some point but my first goal was just to simply get it working first.

Gillius
Gillius's Programming -- https://gillius.org/

bamccaig
Member #7,536
July 2006
avatar

This reminds me that I had already make a few attempts to get this working in Linux. Failed attempts. :-/ I had already built the monolith, but I don't think I tried it yet. Today I tried to run again, but it doesn't seem to be searching the correct paths:

Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'allegro_monolith-5.2': Native library (linux-x86-64/liballegro_monolith-5.2.so) not found in resource path ([file:/home/bambams/src/jalleg/jalleg-examples/build/classes/main/, file:/home/bambams/src/jalleg/jalleg-examples/build/resources/main/, file:/home/bambams/src/jalleg/jalleg-binding/build/libs/jalleg-binding-0.1.0-SNAPSHOT.jar, file:/home/bambams/src/jalleg/jalleg-rt-x86-64/build/libs/jalleg-rt-x86-64-0.1.0-SNAPSHOT.jar, file:/home/bambams/src/jalleg/jalleg-framework/build/libs/jalleg-framework-0.1.0-SNAPSHOT.jar, file:/home/bambams/.gradle/caches/modules-2/files-2.1/net.java.dev.jna/jna/4.2.2/5012450aee579c3118ff09461d5ce210e0cdc2a9/jna-4.2.2.jar])
        at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:277)
        at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:403)
        at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:342)
        at org.gillius.jalleg.binding.AllegroLibrary.<clinit>(AllegroLibrary.java:39)
        at org.gillius.jalleg.framework.AllegroSystem.install(AllegroSystem.java:26)
        at org.gillius.jalleg.framework.Game.run(Game.java:95)
        at org.gillius.jalleg.example.BallAndPaddleGame.main(BallAndPaddleGame.java:167)
:jalleg-examples:run FAILED

I'm not sure how to tell it what paths to search...

gillius
Member #119
April 2000

Thanks for trying this out!

The start of the AllegroLibrary class had a hardcoded name of the library, but I just pushed a commit to make it configurable (the hardcoded value, and the new default is "allegro_monolith-5.2").

You can try it this way: gradlew -PAL_NAME=alleg run will try to load alleg.dll or liballeg.so. Or you can put an absolute path like gradlew -PAL_NAME=/home/bambams/allegro.so run

My understanding of JNA is that it first tries to load the so the normal way (i.e. from /lib and /usr/lib). Then it looks in your classpath for /os-arch/libx.so, as you see linux-x86-64/liballegro_monolith-5.2.so in your case. Since I don't have a JAR with static Linux Allegro in it, if you don't have Allegro installed in global ld paths, use the method above to specify the absolute path.

Documentation for NativeLibrary.getInstance parameter says the first parameter is "the library name to load. This can be short form (e.g. "c"), an explicit version (e.g. "libc.so.6"), or the full path to the library (e.g. "/lib/libc.so.6")."

Another thing I note about the doc is that it allows multiple classes binding to the same library, that's good it means I can break out AllegroLibrary per the way Allegro is normally built and put some logic to load the small file first, then try monolith.

Gillius
Gillius's Programming -- https://gillius.org/

bamccaig
Member #7,536
July 2006
avatar

That works perfectly! :) Append: I'm not a Java programmer, but this "property" business seems rather unfortunate. Does Java have a cross-platform API to access environment variables? That seems like the better approach to this if it can do it. Then I don't need such a long command line all of the time. I can put something in .bashrc and I'm done.

gillius
Member #119
April 2000

Of course, Java has System.getenv("AL_NAME") to do that, so I just pushed a change to do exactly that. The "property business" is just a more common way in the Java world, because people are used to using java -DAL_NAME=blah to launch.

I just pushed a change:

  1. If Java system propery AL_NAME is set, use it

  2. else if environment variable AL_NAME is set, use it

  3. else use "allegro_monolith-5.2"

So questions for Linux Allegro users... If you install Allegro (for example as from the Ubuntu PPA), what files do you get, where, and their names? I could search for them.

Also, if there is a common environment variable set for Allegro users (like ALLEGRO_PATH) that can be used to find the so, I can use that as well for those that build themselves.

EDIT: jalleg now automatically falls back to trying to load the Allegro components such as liballegro.so, liballegro_audio.so, etc. Therefore, you can follow https://wiki.allegro.cc/index.php?title=Install_Allegro_from_Ubuntu_PPAs or build and install Allegro "globally" (i.e. into /usr/lib or another ld path), and it will work with Linux out of the box. The AL_NAME method to point to monolith Allegro still works.

EDIT2: Full Linux getting started instructions available at https://github.com/gillius/jalleg/wiki/Allegro-for-new-Java-developers

Gillius
Gillius's Programming -- https://gillius.org/

amarillion
Member #940
January 2001
avatar

I tried it only briefly now, and I didn't follow your tutorial to the letter, but I'm getting an error message and I was wondering if anybody else has seen this:

Exception in thread "main" java.lang.UnsatisfiedLinkError: Can't obtain updateLastError method for class com.sun.jna.Native
	at com.sun.jna.Native.initIDs(Native Method)
	at com.sun.jna.Native.<clinit>(Native.java:148)
	at com.sun.jna.NativeLibrary.<clinit>(NativeLibrary.java:84)
	at org.gillius.jalleg.binding.AllegroLibrary.<clinit>(AllegroLibrary.java:62)
	at nl.helixsoft.jalleg.helloworld.HelloAllegro.main(HelloAllegro.java:9)

Any idea what this means? Googling the error seems to suggest that there is a version conflict on JNA, but I'm using the one that you suggested.

Here is what I did.

I installed allegro 5.2 from ppa, and set up a project in eclipse with the following in the classpath:

jalleg-framework-0.1.0-SNAPSHOT.jar
jalleg-binding-0.1.0-SNAPSHOT.jar
jna-4.2.2.jar

I'm using java 8 openjdk on linux.

Then I copied your example code:

package nl.helixsoft.jalleg.helloworld;
import static org.gillius.jalleg.binding.AllegroLibrary.*;

/**
 * Displays a 640x480 red window for 1 second.
 */
public class HelloAllegro {
    public static void main(String[] args) throws Exception {
        al_install_system(ALLEGRO_VERSION_INT, null);

        ALLEGRO_DISPLAY display = al_create_display(640, 480);

        al_clear_to_color(al_map_rgb_f(1f, 0f, 0f));
        al_flip_display();
        Thread.sleep(1000);

        al_destroy_display(display);

        al_uninstall_system();
    }
}

gillius
Member #119
April 2000

Thanks for trying out the lib, Amarillion!

That error is when the JNA classes are loading. JNA tries to load native code installed in the system before it unpacks libraries bundled within the JAR itself. Based on https://github.com/java-native-access/jna/issues/281, that seems to be what might be happening to you, if you have libjnispatch.so on your ld path (i.e. in /usr/lib) for an older JNA, this will happen. The JNA author's suggestion from the GH issue is to use "-Djna.nosys=true" to force JNA to use the bundled native lib over the pre-installed one. It seems odd to me that a Linux would include a libjnidispatch.so, but it's also bad on their part that they didn't add (or use) numbers onto their so like libjnidispatch.so.0 that's supposed to handle this... This is a shortcoming of JNA I did not know about.

Other than that, what you did should work. You can also try to run my example program from the jalleg source by:

git clone https://github.com/gillius/jalleg.git
cd jalleg
./gradlew run

However, if your issue is libjnidispatch.so already on your ld path, the same problem will occur. I'm not sure -Djna.nosys=true will work on gradlew because it would apply to gradle and not the executing process. If this situation is more common I can observe also an environment variable like I did with AL_NAME.

Gillius
Gillius's Programming -- https://gillius.org/

amarillion
Member #940
January 2001
avatar

Thanks Gillius, I got the hello world example working now. Nice red screen :)

Indeed, the -Djna.nosys=true option solves the problem with Can't obtain updateLastError method for class com.sun.jna.Native

I also got the error:

Unable to load library 'allegro_monolith-5.2': Native library (linux-x86-64/liballegro_monolith-5.2.so) not found in resource path

Either installing allegro 5.2 through ppa or building it myself doesn't put this file in a location that it gets found automatically. Instead I solved this by adding liballegro_monolith-5.2.so to my project class path.

I'm wondering if it's useful to package these dynamic libraries in a jar file and publishing that as a maven dependency.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

I've programmed Java before, and used Allegro as well. Could you give me an example of what it takes to use jalleg? A small tutorial perhaps? Are the functions all named the same? How do you access them?

Oh, okay, I saw your tutorial. It doesn't included how to actually use jalleg yet, only to set it up. Are there any docs for jalleg included?

I would love to be able to use allegro with java. It could make some things so much easier than it is with swing.

Edit
I like how it (your example program and the ball) speeds up. Does the original pong do that?

gillius
Member #119
April 2000

amarillion, is it possible that you downloaded an older 0.1-SNAPSHOT? The original version looked only for monolith, but after working with bamccaig earlier I revised it to try loading the monolith first, and then load the individual libs in the order shown here. Although, if that fails the error message shown is "can't find the monolith". At that time I installed Ubuntu 16.04 into a Virtualbox and was able to install Allegro from PPA, git, openjdk-8-jdk, jalleg and build/run jalleg without setting any properties or flags.

As for packaging the libraries, I would love to do that for Linux, if I knew how. I already have it for Windows 64-bit out of the box. But to do it for Linux I would need a static Linux build of Allegro, which I have not found how to do or even evidence that such a thing exists. Looking at the ldconfig output for Allegro it's pretty intense. It's possible such a thing is not even "legal" (if any LGPL is used), so the best I can do is make jalleg work with PPA install (or make install), which is what I've done. If you still have issues with loading from PPA, let me know.

Edgar, the jalleg binding uses the same functions as Allegro. It's a straight binding. Where you use pointers in Allegro you just use normal object references in Java. The only thing that could be tricky is how unions are mapped into Java via JNA:

ALLEGRO_EVENT event = new ALLEGRO_EVENT();
al_wait_for_event(eventQueue, event);
if (event.type == ALLEGRO_EVENT_TIMER) {
  ALLEGRO_TIMER_EVENT timerEvent = event.asType(ALLEGRO_TIMER_EVENT.class);
  //...
}

(You can see this in more detail in the Game class of jalleg-framework).

My thought is that those who know how to program Allegro and jalleg should be able to use jalleg very easily, if you see the HelloAllegro example posted by amarillion above (same as on my README), let me know what else someone needs to know to use jalleg. There's no dedicated documentation for the binding because I reference liballeg.org. The jalleg framework sits on top of Allegro and there is some Javadoc there but I haven't published docs yet online but you can build them or see them in source or download them from Maven Central.

As jalleg is on GitHub and open source any one is welcome to contribute, especially on the wiki tutorial and documentation it is as easy to edit as any wiki.

As for the pong game speeding up on hits, I actually don't know if that's the case, but I thought as the match progresses it has to get harder or no one will ever miss, and I feel like it got harder as you went along. I just worked from my memory of the original I haven't seen in about 20 years :). My intent wasn't to make a direct clone as much as pong is pretty much the easiest game to program that actually feels like a legitimate game, and I was able to use a surprising amount of Allegro features in such a small game.

Edit: I pushed out a 0.1 release so it's on the main Maven Central repository now.

Gillius
Gillius's Programming -- https://gillius.org/

Go to: