There is one thing missing on the web: A Java App Library (or App Store).
As I am testing the next release of WRoom, I want to create an app library built for WRoom. The task seemed easy until I realized that googling for Java apps and games is not that easy.
Results returned by Google are about tests, demos and game libraries. I did found a few gems here and there. So I decided to ask the web to send me links to great apps and games built in Java/JavaFX.
What I need:
Name of the app/game
A brief description (1 or 2 lines)
An image/logo link
Others images, screen captures, links to YouTube videos of your apps, tips, other links related
A main virtual room will be created to list the apps and a smaller room will be available, dedicated at your app/game.
Here's a short demo that I am currently working on:
Wanna help with WRoom? Talk about it and build your own virtual space. See the main website for downloads and documentation
If you did not know, I have been working on a new open source project called WRoom in the last few months. It's a big technical experiment but it has a lot of potential at the same time.
Basically, WRoom is a new web browser where you navigate virtual rooms create using a simple text file. It's easier than HTML/Javascript and you can create maps all over the web, linked together with Teleporters.
I have released a new version today: 0.0.10 ALPHA. In this new version, I have integrated Texture videos and a bunch of new stuff. Currently, the Windows version works pretty well and it kind-of work on Linux, at least on my Ubuntu Mate laptop.
Here's a demo of the latest version:
The main features of WRoom:
3D Browsing à la Doom FPS game
Supports textures (PNG, JPG)
New Video Textures using FFMPEG
Embedded chat room, (Simple avatars are showing other visitors)
Triggered actions: Teleport, play sound, open door
Animated textures using multiple image files
Easy to create your own using a simple text editor
Free as in Open Source
WRoom is a new twist on creating communities online without having to learn HTML and Javascript. A map editor is on the way to make things easier. Maps are hosted on any web hosting plan such as Mochahost or your own web server.
Here's a simple map example:
# Set the title for the room title=Planet Mars
# irc server chatroom=#wroommars server=irc.freenode.net port=6667
# Load the textures texture=wall03.png texture=wall01.jpg texture=wall03.png floor=floor.png ceiling=ceiling.jpg
# Define the actions # Actions are: teleport, sound, message, download # After the action command, enter the location of the action x,y # Then the parameter # action=teleport,x,y,URL # action=sound,x,y,sound.wav # action=message,x,y,Message string... # Actions are triggered by pressing the action key: space bar... action=teleport,43,29,http://wroom.crombz.com/,Congrats! Back to homebase
# Load text to display on walls # TEXT=x,y,HTML text entry... text=1,3,<div style='border:solid red 3px;background-color:#441111;color:#FF0000;font-size:12px;text-align:center;'>Welcome to Mars!<br>Can you find your wayback to WRoom homebase?<br>Good luck!</div>
If you are developing software in Java, you may need to capture the desktop at some point. There is the Robot API that does provide a simple way to capture the desktop, but it's not very efficient.
I've found a better way to capture the desktop, or the webcam in Java, relying on FFMpeg. There is no need for JNI bindings or other obscure libraries dependencies. All you need is an executable FFMpeg binary in your path.
Why not use Robot?
The Robot API is really easy to use but it has a major drawback: Speed. On some computers, you may be able to capture up to 30 fps but on other, you'll struggle to capture images at 3 fps. It seems that the operating system and the video driver are sensitive areas for the Robot API.
FFMpeg?
FFMpeg is a console application that can capture, transcode and even stream video and audio file. It's a swiss army knife for multimedia content. It is available on almost all Linux distros, OS X and Windows.
Once FFMpeg is installed on your system, you can invoke the binary using the Process class as any other executable.
The trick is to retrieve the captured data directly from FFMpeg using the Process class. Once the raw data is captured, use a BufferedImage to store those raw data and you'll end up with an Image available for whatever you want to do with it.
java.io.DataInputStream in =newjava.io.DataInputStream(p.getInputStream()); byte[] data = ((DataBufferByte) buffer.getRaster().getDataBuffer()).getData();
while (!stopMe) {
in.readFully(buffer);
}
in.close();
p.destroy();
This code will capture at the highest frame rate that the computer can support. The speed of the computer will be the limit of your capture processing speed.
The thing you need to focus is the output format of FFMpeg. The video encoding must be "rawvideo" with a pixel format matching the BufferedImage. In this example, a 24 bit/pixel is used in BGR format (Blue, Green, Red). The data is them exported directly to the console (notice the "-" at the end of the command line...) instead of a file. That means that using the InputStream from the Process class, Java is able to read the data as fast as it can.
Execute this capture process in a Thread making the BufferedImage available for other parts of your software.
See the whole thing running...
Using this method, I have built ScreenStudio to capture the desktop into a virtual video mixer built entirely in Java. If you want to see it running live, download the source code of ScreenStudio at http://screenstudio.crombz.com
Leave you questions in the comments or tweet me at http://twitter.com/patrickballeux
I've been working on ScreenStudio 2.2.0 today as I was stuck in bed with a major backache.
I took the time to rework the compositing of the desktop and the side panel to provide more customization in the future.
With version 2.1.x, the compositing was executed by FFMpeg itself. This is faster to render, but the drawback is the synchronization between the audio and video that does not always work as expected.
As of version 2.2.x, ScreenStudio will take charge of compositing all the video sources and FFMpeg will only have to encode the audio and video.
I was expecting a loss in performances but I was quite surprised to find out that nothing was lost. I even saw better performance in some specific cases.
More tests are to be done but if all goes well, it will open a lot of possibilities for ScreenStudio like dynamic layouts while streaming.
Source code is already available in the Github repository is you feel adventurous....
How would a software coder describe the recipe to make hard boiled eggs?
The procedural coder:
- Take a saucepan - Put water in the saucepan - Put the saucepan on the stove - Turn on the stove to maximum - Wait for the water to reach boiling temperature - Put three eggs in the boiling water - Wait 3 minutes - Turn off the stove - Take the saucepan - Empty boiling water into the sink - Take the first egg, be careful full it's hot - Roll the first egg on the kitchen counter to crack the shell gently - Remove completely the shell from the first egg - Put the first egg on a serving plate - Take the second egg, be careful full it's hot - Roll the second egg on the kitchen counter to crack the shell gently - Remove completely the shell from the second egg - Put the second egg on a serving plate - Take the third egg, be careful full it's hot - Roll the third egg on the kitchen counter to crack the shell gently - Remove completely the shell from the third egg - Put the third egg on a serving plate - Voilà, enjoy!
The object-oriented coder:
- On a stove, in a saucepan, put water - Turn on the stove to maximum - When the water is boiling, on the stove, in the saucepan, in the water, put three eggs - After 3 minutes, turn off the stove - Empty the water, from the saucepan, on the stove, into the kitchen's sink - For each egg, in the saucepan: - Be careful, it's hot - Roll it on the kitchen counter - When the shell, on the egg, is cracked, remove completely - Put it on a serving plate - Voilà, enjoy!
The delegate-oriented coder:
- You need a stove, a saucepan, water, a kitchen sink, a kitchen counter, a serving plate and three eggs - Turn on the thing that can heat to maximum with the thing that was filled with stuff that can boil - When the event where the result of boiling has been reach, add the items that can be cooked in the stuff that is hot enough to cook them - After a while, set to 3 minutes, remove the stuff that was boiling and put it in the thing that can dispose of it - For each item, in a container, roll it on the thing that is hard enough to crack the external stuff of the item. At the same time, be careful as a warning message and it has been set that it can be hot. - In the event that the item is cracked enough, remove the outer thing completely and put the item in something that can be used to serve for a meal - In the event that that everything is done, Voilà and at the same time, Enjoy! - When the items are cooked, turn off the heat source
One of the hardest thing to handle when developing a solution are dates. You always end-up in some worst case scenario if you are not careful with them.
This week, it happened to me. Lucky we found the issue while executing a series of test plans, just in time before shipping into the production environment...
Java is a great language that let's you concentrate on features to implement instead of figuring out how to manage the memory addresses for example. But sometimes, you can be challenged by the runtime and have to get dirty to create some advance functions.
Printing in Java is quite easy. But it can be a bit to simplified for your needs and you'll end up coding at a low level to get the desired result. Basically, when you want to print, you have to calculate the space required for each word, handle any carriage return and draw the result on a a Graphics. For images, you'll have to resize the image to fit the paper size, draw lines for underlined text, etc... You know the drill.
Of course, there are tons of libraries that will handle complex document printing like JasperReport. With these tools, you design your templates, invoke a database and print the result on your printer or a PDF file.
For simpler documents, you can populate a JTable and print it directly quite easily. The same goes for a JTextArea or a JTextPane. But you can only print one component in a PrinterJob at a time. There is no way to print a JTable and a JTextArea on the same page or in the same PrinterJob. Even combining both in a Book (Pageable class) will result as each component being printed on a new page instead of being printed one after the other.
Here's an example:
This is a case where you'll have to rely on an external library or do some low level coding... At least, until now...
The issue is that PrinterJob.print() will call the Printable object with a page index. The index will be 0 on the JTable, and 1 on the JTextArea in a Pageable object (Book). Only the JTable will be printed. If you manage manually the page index, calling 0 on both, you will have no other choice then printing on two different pages as there is no way to invoke the second printing on the same page, following the first one.
Basically, PageFormat is your friend as you can use it to specify here to print the component on your page. All you need to do is manage your page index and modify the PageFormat (Imageable Area) to indicate where you can start printing the next component. The problem is that you don't know where the printing operation ended on the Y axis. If you table heigh is know, there is a work around that can be used, but if your JTable height is greater than one page, you're stuck. You'll have to implement complex calculation to find how much was printed based on the paper size, paper orientation, cell size and so on. It can become quickly a nightmare if you plan printing several Printable components in a single PrinterJob.
I've search the Internet and that issue has been confusing Java coders for the last decade. Either you implement a low level printing algorithm or you use an external library and implements a totally different design just to be able to print tables and texts. JTable, JTextArea and JTextPane can handle printing by themselves and provide excellent results without much effort. But not together...
I finally found a clean solution to make them work together. The main issue is to find how much space is left when a component has finished printing. Using a BufferedImage to do a pre-printing is how I was able to do it. You'll have to pre-print anyway to find out the total page count required if you want to build a table of content, so it's not a big deal.
Here's the code, a simple Printable class, wrapping the Printable object of the component. This wrapper will handle the amount of space left after the printing. All you need to do is check how much space is left and create a new page when needed and restart the page index at 0 for each new page.
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package printer;
public void setMinimumRequired(double height) { minimumRequired = height; }
public double getMinimumRequired() { return minimumRequired; }
public double getSpaceLeft() { return spaceLeft; }
private int detectLastLine(BufferedImage img) { int lastIndex = 0; int[] data = ((DataBufferInt) img.getRaster().getDataBuffer()).getData(); for (int i = data.length - 1; i > 0; i--) { if (data[i] != 0) { lastIndex = i; break; } } return (lastIndex / img.getWidth()); }
@Override public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { BufferedImage img = new BufferedImage((int) pageFormat.getWidth(), (int) pageFormat.getHeight(), BufferedImage.TRANSLUCENT); Graphics2D g = img.createGraphics(); int retValue = delegate.print(g, pageFormat, pageIndex); if (retValue == PAGE_EXISTS) { //Find out bound of printing... //System.out.println("Last Line drawn is : " + detectLastLine(img)); // try { // ImageIO.write(img, "jpg", new File("img" + debugindex++ + ".jpg")); // } catch (IOException ex) { // } spaceLeft = (pageFormat.getImageableY() + pageFormat.getImageableHeight()) - detectLastLine(img); retValue = delegate.print(graphics, pageFormat, pageIndex); //Updating paper after the hardprint Paper paper = pageFormat.getPaper(); paper.setImageableArea(paper.getImageableX(), paper.getImageableY() + paper.getImageableHeight() - spaceLeft, paper.getImageableWidth(), spaceLeft); pageFormat.setPaper(paper); } return retValue; } }
For each Printable, JTable.getPrintable(...), wrap it with MyPrintable object and then print the wrapper.
MyPrintable prt = new MyPrintable(table.getPrintable(...)) ... while (prt.print(graphics,pf,pageIndex) == PAGE_EXISTS){ if (prt.getSpaceLeft() < 100){ // create a new page or a new graphics // reset page index to 0 } pageIndex++; } // looping to the next Printable...
I've worked on many projects and I've seen my share of code. There is all kinds of coding style going from the most elegant to the "I'm your worst nightmare".
The thing is that "not so elegant code" is often written because of lack of time to do better. Deadlines will force coders to implement some duck tape here and there, while thinking that when they'll have time, they'll make it more elegant and efficient.
That's kind of a wishful thinking process since we all know that going back to change what's already working is a no-no in the business of software developpement.
But some times, there is code that just does not make sense. From a computer point of view, the code works. But from a human perspective, it does not tell the story of the process at all.
Here's an example:
float r = 10f; while (i < 255){ int c = temp[i] * r / 100f; temp[i] = c; i++; }
Some of you may have guessed that it's a simple calculation to apply an alpha channel based on a ratio. This is a simple example, quite explicit for the initiate. But for a coder who never worked with colours, it will require some effort to understand. The code is clear, the context is not...
There is a much better way to do that kind of calculation, but I just wanted to illustrate that naming variables, avoiding unnatural operations and ensuring that the code can be described easily in plain English will help everyone, including you, when you'll have to go back in that code section, a few months later.
Another example is when you have to deal with delegate functions. It has the benefit of saving memory and process time but may render the code completely unreadable.
myObject.executeDelegate() is one of the worst line of code to debug. To find out what is the object and what it does, you'll have to debug line-by-line and follow the process to figure out what is going on.
Make sure that the code is explicit enough so that any experienced coders will be able to read it as plain English. Sometimes, we have to implements some twists to make it work. Add comments and try to make you code as clear as possible since it can be tricky to understand.
Finally, avoid multiple conditions in a single IF condition. You know, the kind that you need to split to find out which condition was TRUE and made the execution enter that block... I've seen some IF having to deal with 12 conditions to validate the execution of the code block below... And I'm not even talking about the infamous if not (not(x or y) and (z and x) or not y).