Archive for June 2007

It’s the Silly Mistakes

After looking at my shadow rendering code looking for ways to speed it up I discovered I had a rather silly bug in the code. In order to get out of the loop when a wall was hit I was setting the loop variable to less than the amount needed. I don’t know how this didn’t create an infinite loop or maybe it did but Java was smart enough to exit the loop.

I also lowered the accuracy to 8 pixels instead of 16. The maximum accuracy is 64 which would be pixel perfect. Another speed boost came from disallowing pixels with the color 0xFF000000 to be plotted. Instead they’re changed to 0xFF010101. For some bizzaro reason Java choaks on that pixel color.

The result is that without any non-global lighting, Bunnies now runs up to 40FPS on the test map instead of 30. Having lights that cast shadows is still expensive. I havn’t created particularly large or complicated maps yet so I don’t know how much different lighting will affect the framerate.

Bunnies Update

One of the issues I was having was making the map editor easy to use. There are three layers of the map: floors, walls and ceilings and obviously they stack. The solution to the problem was having the tiles shift for the cell when the mouse is over it. That way you can easily see the tiles that make up that cell.

Also, since the ceiling hides everything and the walls hide the floor, it’s possible to hide one or more layers.

Also, I’m going to be getting rid of the word “tracks” and replacing it with “maps” because this tool is useful for any tile based game. Bunnies is a shooter and Bunny Racers will be a racing game. There’s no reason to pretend the tool is only good for one of them.

The next challenge is the object editor. I havn’t figured out exactly how I want to handle that one. Bunnies doesn’t really allow for much customizing when it comes to objects. That’s going to have to change. The first release of the Bunnies site will probably only allow for placing of objects. They’ll already be predefined. We’ll see though. It may turn out to be a very easy task to make it more customizable.

Intermission: File Store

While working on Bunnies I was interrupted for a bit by a request to build a file sharing site. I took up the challenge and a week later here it is. File Store is a free and easy way to share your files. You can upload large files up to 256MB and e-mail links to friends so they can download them. You can also hotlink JPG and PNG files.

The site supports an unlimited number of harddrives so I can just add them as needed. While I stress test the site out, paid accounts are free. Just sign up and you’ll be given the resources of a paid account. One of the cool features of the site is a progress bar that tells you how far along your upload is. It uses PHPs recently completed plugin so it’s very accurate and doesn’t rely on silly hacks involving perl.

The site doesn’t look like much yet but that will be improved in the coming weeks. Right now the focus is on features.

The Bunnies are Coming

In 1992 Wolfenstein 3D was released on an unsuspecting public.

Wolfenstein 3D

In 2006 Bunnies was born

Bunnies

With true color graphics, unlimited texture sizes. colored lighting with shadows, floor and ceilings, a Wolf3D clone has never looked so good.

Soon a web-site will be unleashed that will allow you to upload any number of graphics files and create custom levels. You’ll be able to easily download them to play and share them with your friends. The web-site is free and compatible with all the latest browsers.

Built with the power of Java you’ll be able to play Bunnies with any Java enabled device.

Java Hates 0xFF000000

In my previous post I noted that Java seemed unsuitable for Bunnies since I was demanding more textures, etc. But behind the scenes I noticed something very odd. When I was on a large grassy patch in the middle of the track the framerate was fine. However, when I neared the large patch of pure black track tiles the framerate plummeted to around 2fps. Changing the tile from pure black to not black brought the framerate back up.

Bunnies now runs at 30fps at 320×240 with the following addition of code to the texture loading routine:


int k =0;
int m = textures[num].w * textures[num].h;
for(k = 0;k<m ;k++)
if(textures[num].pixels[k]==0xFF000000)
textures[num].pixels[k] = 0xFF010101;

That’s right, every pure black pixel is changed to not quite black and now Java is cruising along. Another side effect is that the mystery gaps between floor tiles has also disappeared.

Maybe there’s some logical explaination to this mystery but I havn’t figured it out yet. Silly me thinking black would be treated just like every other color. Apparently, Java thinks differently.

Is Java Suitable for Games?

Software Rendering is all about creating Wolfenstein 3D clones in a variety of languages. The most recent incarnation is “Bunnies” in Java. It features lighting, floors and ceilings on top of the standard walls and objects that most clones contain.

I’m working on a web-based map editing tool and discovered something: Java tanks as soon as you have too many different textures. And by too many I mean a few dozen 64×64 pixel textures. When I download the map information to load with the applet and there are more than few dozen textures the frame rate tanks and it occasionally becomes non-responsive.

When I download a map with just a few tiles, the game runs just fine.

So in conclusion, no, Java can’t handle the memory or number crunching required to run a computationally expensive game. Which is fine actually. The Java version of Bunnies is complete. This next set of tutorials in this project will be using C#. We’ll see how well it handles. I suspect it will do about as well as the C++ version except this time around the code is more optimized, less buggy and does more.

The Secret to a Long and Happy Marriage

A couple was celebrating their 75th wedding anniversary on the beach in Montego Bay, Jamaica.

Their domestic tranquility had long been the talk of the town.

“What a peaceful & loving couple”.

A local newspaper reporter was inquiring as to the secret of their long and happy marriage.

“Well, it dates back to our honeymoon in America ,” explained the man.

“We visited the Grand Canyon in Arizona and took a trip down to the bottom of the canyon by horse. We hadn’t gone too far when my wife’s horse stumbled and she almost fell off.”

My wife looked down at the horse and quietly said, “That’s one.”

We proceeded a little further and the horse stumbled again, this time causing her to drop her water.

Once more my wife quietly said, “That’s two.”

We hadn’t gone a half-mile when the horse stumbled for a third time.

My wife quietly removed a revolver from her purse and shot the horse dead.

I shouted at her, “What’s wrong with you, Woman! Why did you shoot the poor animal like that? Are you crazy??”

She looked at me, and quietly said, “That’s one.”

“And from that moment we have lived happily ever after”.

Software Induced Latency

Digg recently ran an article about what latency is and what causes it. I pointed out that latency is often caused by software. Not the internet. Of course this comment was dugg down by people who assume that graphics cards and sound cards free up CPU time to handle messages promptly. This is the problem with the internet: people who have never actually created an on-line game make silly assumptions and act like they know something.

Real world example: I created a simulator using DEM (geological survey data) to render real terrain using OpenGL. This simulator had two parts. The first part was the graphical application that rendered everything. It didn’t do much of any logic. It was just told what was were and what direction it was moving and how fast. The second part was any number of clients controlling any number of objects. The clients rendered exactly no graphics whatsoever. They were text apps that just bombarded the server with messages.

Fact: when the server was not restricted in the frame rate it would crash after a few minutes because it didn’t have enough time to process all the messages. The buffer would get full and it could no longer receive messages. If I had it only process a few messages per frame it only delayed the inevitable crash when the message buffer overflowed and it stopped receiving messages. If I had it process all messages before rendering a frame it would just stop rendering frames after awhile.

The lesson: it doesn’t matter that the graphics card was doing all the heavy lifting. If framerates were priority there simply wasn’t enough horsepower left to handle messages. This was a 3ghz machine with a nice graphics card. Also, if the message buffer can’t be emptied faster than messages are coming in you also have a problem. This indicates a necessity for an efficient protocol and finding ways to reduce the need for a large number of messages being sent. It is also necessary to give the program ample CPU time to process messages and this means restricting frame rates.

Second Real World Example: Sack Armies (which will be running live one of these days) also relies on TCP for the messaging protocol. There are no throw away messages so a guarenteed protocol was necessary. When I first started I was treating TCP like a messaging protocol. The server would process a message from a client, form a response and send it off right away. Certain actions required more than one message to be sent. Back on the client side the first message would come in and then a pause and then the second message.

This happened when the server and client were on the same computer or on the same network. That’s latency. The solution? Instead of sending the messages right away they were buffered both on the client side and the server side. The server would flush its buffer (actually send the messages down the pipe) once per iteration of the main loop which was running at 100’s of iterations per second. The client would buffer all the data coming in and process messages once per interation as well. The client would also only send messages once per iteration as well.

Keep in mind that with a couple if statements it’s possible to run the main loop at thousands of iterations per second while only rendering new frames a fraction of the time.

The result? No perceived latency. Because, for example, three messages were sent all at once, the client got them more or less all at once and processed them all before the next frame was rendered.

I set up a message type for testing the latency. The client would put a message into the out buffer and start a timer. The message would be fired off and the server would get the message and put a response into the out buffer on its end. The server would then send the response to the client. The client would get it, buffer it and then process it. The entire process took 30ms or less even with miles between the client and server and different internet companies.