CSDGN Tale of the Lazy Programmer.

20Aug/100

Custom Java Look and Feel

I wanted to create a custom Java Look and Feel for a game I was working on. Of course I could have created my own windowing system (Again), however I didn’t feel up to this. Java already has a very use able and very complete windowing system, all I cared about was changing how it looked.

Of course my first thought was to just overwrite the paintComponent of everything I wanted to change…. but what about text? How do I get rid of those borders, the amount of work to get even simple functionality for the simplest of tools is annoying, just think if you made overwrote a list. Very painful!

Well of course I realized this and stopped to look for a better alternative. I know Java has pluggable Look and Feel. But I had never put much leg work into figuring out how to make my own, and all the other releases out in the wild looked monstrous and complex.

So I googled around, finding nothing on the actual ‘how’ of creating a custom theme. I decided to look at the Runtimes Environments own Look and Feels. This was a great idea. After only a bit of intense searching I found what I was looking for.

javax.swing.plaf.basic.BasicLookAndFeel

Well, I thought to myself. That looks mightly useful, but there is to much there. I need to cut things down some. A little googling I found a rather minimal if old custom look and feel and that helped me on making my own. Of course they use many things that are rendered unneeded in the latest JRE. Basically, override the obvious stuff. getDescription, getID, getName, isNativeLookAndFeel, and isSupportedLookAndFeel. Then hit the guts by overriding the initClassDefaults, this will put you well on your way to a custom UI. Of course then make your own versions of the XXYYUI.java classes, say BasicButtonUI is an example.

I recommended using the Basic as the parent classes for your L&F. It becomes somewhat difficult if you do not do so. Since it covers most of the basic events and such Java covers.

1Apr/100

EVE Online

Here I am going to speak a little more about games again. Eve Online, I tried it awhile ago, and it wasn’t the most terrible game in existence, however I dislike for one very simple reason. Their learning systems depends wholly on how long you have been paying them. Thats right, you don’t work hard, or grind monsters, or mine, or whatever else to learn skills, you character learns them at a set pace, which basically equates to for them, longer and more money you give us, the more skilled your character is. Honestly that is a bit annoying to me. I mean sure I can see learning time, or limiting how much you can learn in a given period, and while there are ways to optimize skill learning to a degree. I don’t want to wait around for a year to start having fun.

Oh yes that is another thing, permanent death is really possible, I mean there is a clone system and such, but dieing is really quite possible. Losing those years of hard work.

Truly anal people like me, who in a game of hard work, work our asses to hell and back. Like in Pokemon I usually out level the next gym leader since I trained my Pokemon to ex nauseam. People like me who could find some training engaging instead do not, as you generally log off and do nothing. So you are paying for a game that you do nothing in, and takes you almost a year to get to start to do anything really interesting (that is to say, being able to afford to be part of massive space battles). what. the. fuck.

Tagged as: , , No Comments
9Mar/100

Scrollbars revisited

Awhile ago I made a post on the behind the scenes scrollbar mechanics. I decided to type up a short Java class using my implementation. It is not ready to be put into anything in this form, but consider this another ‘example’ for how to put it together.

I have placed the example in the more section. :)

23Nov/093

Scrollbar Math and Mechanics

Well I found out very annoyingly there is not very much information on the Internet about the actual mathematics behind a scrollbar. What a scrollbar really, how hard could a scrollbar really be anyway. Surprisingly, pretty hard, if you do not take the time to think about it anyway. Explaining the actual math behind a scrollbar may take a little work so I am going to provide pictures!

Scrollbar

First off lets get some terminology out of the way, here I have a image explaining some of it, I realize not entirely perfect, but its enough for an explanation on scrollbars. The grip rides within the track. The track plus the grip is called a slider, the combined buttons plus the slider compose the scrollbar.

Now that we have that out of the way, now to time to discuss the actual mathematics. There are a few ways to handle the math involved, however most of them require the use of floating point numbers, which can be problematic on some systems without FPUs. Luckily most systems that require the use of scrollbars have fpus. But if it is a problem you can use fixed point decimals just as easily (but there is more work involved in converting to and from on a programmers part).

First off the size of the grip is determined based on the relative size of the window compared to the content that it slides over. This is very simple, it uses the same ratio, but in comparison to the track instead. You must keep in mind that a scrollbar has a minimum and a maximum size however. Luckily at this point, it is very easy deal with the size of the grip by just limiting the maximum size to the size of the track, and the minimum size to some convenient number specific to your implementation, I will use 24.

Note I am only using floats, this code can easily be optimized!
This is for demonstration purposes only!

Here is some psudo-code for your enjoyment:

float trackSize = 180;
float windowSize = 200;
float contentSize = 520;

float minGripSize = 24;
float maxGripSize = trackSize;

//0.4
float gripRatio = windowSize / contentSize;

//72
float gripSize = trackSize * gripRatio;

if(gripSize < minGripSize) {
        gripSize = minGripSize;
}
if(gripSize > maxGripSize) gripSize = maxGripSize;

Now that we have the grip size out of the way, things start to get a bit harder. We must now determine the position of the grip in the track. This is more complicated then it sounds. Because of the minimum and maximum size of the grip, and the fact that the grip is positioned based off its center, not off its top. Otherwise to scroll to the bottom of the content the scrollbar would fly right off the track! The region the scrollbar actually ‘scrolls’ is a subset of the area of the track, not the entirety of the track itself! Its actually trackSize-gripSize. This is the optimized form of trackSize – (gripSize/2 + gripSize/2), since each side of the grip cuts off scrollable area on the track. But since we will work with the top position of the scrollbar, we can ignore this and use the optimized value.

The positioning again requires a ration of the window and content, but in this case we determine how far down the content the window is displaying. I visualize it as a window overlooking the content, which is sorta the idea, and why windows are called windows. Just how you define how the window displays over your content is left up to you. For a list it could be for each item in the list, or for say a web browser it could be for every pixel down from the top of the content it is. In the end it doesn’t matter, the math is the same for any given unit.

Now for more psudo-code, please note I am carrying over variables from the previous set of code:

float windowPosition = 40;

//108
float scrollSize = trackSize - gripSize;

//0.08
float scrollRatio = windowPosition / contentSize;

//Take Note: This is for the top of the grip
//8.64
float gripPosition = scrollSize * scrollRatio;

Now that we have both the Grip Position and the Grip Size, we can easily render it without problems, and because it was limited above in the first bit of code, we do not have to worry about figuring out what if its at the bottom of the scrollbar and also the minimum size, and other special cases, since that has already been covered! It looks fairly simple now that I have the code down right, but just trying figuring it out the first time yourself, its not as simple, especially if your new to working with hand made user interfaces.

There is obviously more to this, for reference the buttons normally move the scroll position up and down by a single unit. Clicking above or below the grip in the track causes the window to move up by the size of the window, or alternatively by the size of the window minus some magic number. This is so it is easier for people to keep track of where they are and the like.

Also keep in mind when a mouse clicks the grip, it rarely clicks the exact top of the grip or the exact center, or the very bottom, remember this when calculating the moved distance for the grip drag. For these cases I supply you with some code to help you out with grip dragging. Generally we take the movement the mouse moved along the axis of dragging. Then we do the reverse of what we did before to get the new window position.

Even more psudo-code:

//This is the distance between the last mouse position and the new one.
//This only matters along the axis of the slider.
float mouseDelta = newMousePosition - oldMousePosition;

float newGripPosition = gripPosition + mouseDelta;

//Limit it so it is not out of bounds
if(newGripPosition < 0) newGripPosition = 0;
if(newGripPosition > scrollSize) newGripPosition = scrollSize;

//Just reverse the algorithms we did before to get back
//to the windowPosition
float newScrollRatio = newGripPosition / scrollSize;
windowPosition = newScrollRatio * contentSize;

I hope you enjoyed my first informative posting here on CSDGN! Feel free to comment.

16Oct/090

PPSE-DS r9

Okay Revision 9 is now out, here is my change log. It has an highly experimental eeprom loader, ergo loading from retail carts, I added it in as a afterthought, it probably doesn’t work very well at all, if at all (it will load renamed saves in no$gba, thats all I know).

Download

Oct 16, 2009: r9
+ Added Complete Item Editing Support
+ Added Highly Experimental Eeprom Loader
(do A+B+X+Y+START+SELECT on main menu)
= Fixed screens to render on demand
= Fixed countless preformance bugs
= Fixed minor pokemon disappearance bug
= Fixed a few empty scroll menu bugs