I've been working on Elite4k, a trade and space sim, since December. The game is basically a clone of evergreens like Elite and Privateer: You fly your spaceship from planet to planet, trade goods, buy upgrades, hunt pirates, mine asteroids or turn pirate yourself ... I think you all get the picture I've almost finished the game now, with a size of around 4.8k and enough optimization potential remaining (hopefuly ) to reach 4k. However, some issues turned up during development which keep bothering me. I would be grateful for any input on the following questions:

Text rendering I'm currently using drawBytes to draw text from a resource byte array to a graphics context without string overhead. Is there a smarter way to do this?

Number rendering I'm currently using a method which fills a byte array from a given number by setting the current modulo-10-value of the numeric value to the current byte, then decimal shifting the number and advancing the output byte. Is there a smarter way to do this? Perhaps some light-weight number format method in the API I don't know about?

Matrix inversion For the 3D space sim, the inverse camera matrix is required. Two ways to get it: Matrix inversion (my unrolled version is 12 lines with lots of multiplies and adds) or premultiplication with the negated matrix components. Which way to go? Premultiplication eliminates the inversion code but requires some control flow in the geometry pipeline. Any experiences?

Loading and Saving For a game where you can easily spend dozens of hours, a load and save game function is a must. The amount of game data I have to load and save is around 20 bytes. One option is to write out a text representation of the values and let the user note it down and reenter it to load a game (old-skool console style). However, 20 bytes mapped to easily typable characters is a lot of text. So I consider using the clipboard: Copy to get the current game state as a string, paste the string (which you saved in some file) to resume. Does this make sense? I'm a bit in doubt

Array Access When accessing array cells in approximately linear (depending on control flow) sequences, is it better to have something like "data[basepointer+1] (...) data[basepointer+2] (...) data[basepointer+27] (...)" or is it better to go unary where possible "data[pointer++] (...) data[pointer++] (...)"?

Loading and saving: using base 64, 20 bytes is 27 characters. That's not much longer than the passwords in some games I've played, and it's a bit more intuitive for a non-technical user than putting stuff in the system clipboard.

1) I'm pretty sure drawBytes is the cheapest way of drawing text2) I think you're right again, the overhead of the necessary api method would be prohibitively expensive3) sorry can't help there.4) I'd bite the bullet & require the user to write down the code - I think you are going to be extremely strapped for bytes, making the usability hit an acceptable loss.5) It depends.

Loading and Saving For a game where you can easily spend dozens of hours, a load and save game function is a must. The amount of game data I have to load and save is around 20 bytes. One option is to write out a text representation of the values and let the user note it down and reenter it to load a game (old-skool console style). However, 20 bytes mapped to easily typable characters is a lot of text. So I consider using the clipboard: Copy to get the current game state as a string, paste the string (which you saved in some file) to resume. Does this make sense? I'm a bit in doubt

Or even smaller if you just draw it to the screen, since OP is already using methods to draw text to the screen.

Thanks for the input on the issue! Fortunately, neither the input nor the rendering of the save-game-string is the problem, I'll probably end up well below the mentioned byte counts by integrating it into the existing event logic.

From the responses so far, I conclude that a save-game-string of, say, 30, alphanumeric chars wouldnt be a problem (correct if wrong).

I tested this but (a) it compresses a lot worse than the solution I use now and (b) it does not support some required features. I need to draw tabular displays, with right-aligned numbers and a unit sign at the end of each number. Here is what I use now, input welcome:

note - pjt33 replied while I was typing, so there maybe some duplication

Only 2 optimisations I can see missing are to use the ternary operator & include the final if statement inside the loop.Both of these eliminate the duplicate array access instructions, which are rather large.Together. i'd guestimate around 10 byte saving?

Forgive the tampering with your literals - embedding non-trivial literals is one of my pet hates

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

/** * Formats a number into a byte array which can be rendered * as a string. * * @param numVal Numeric value to write * @param chrUni Sign to append to value * @returns Byte array of formatted numeric data */privatestaticbyte[] f(intnumVal, intchrUni) {// limit on the number of digits of numVal that will be displayedfinalintMAX_DIGITS = 7;// Define resultbyte[] resVal=newbyte[MAX_DIGITS+1];// Write unit signresVal[MAX_DIGITS]=(byte)chrUni;// Write valuesfor(intdigPos=MAX_DIGITS-1;digPos>=0;digPos--) {resVal[digPos] = (byte)(numVal>0||digPos==MAX_DIGITS-1?'0'+numVal%10:' ');numVal/=10; }// special case to handle numVal==0 moved into loop.

returnresVal; }

:edit:

Further optimised by combining the 2 ternary expressions inside the loop into a single or'ed one.

I tested this but (a) it compresses a lot worse than the solution I use now and (b) it does not support some required features. I need to draw tabular displays, with right-aligned numbers and a unit sign at the end of each number.

Yeah, i wrote that at 2am... my brain was not really firing well.. it makes sense that it should compress worse!

Yeah, i wrote that at 2am... my brain was not really firing well.. it makes sense that it should compress worse!

Anyhow, your solution raises an issue I've been thinking about a lot: API calls versus do-it-yourself. As I see it, there are three basic cases. Two are no-brainers:

Never ever use the API, as in max/min or event handling, where the API calls compress much worse than your own constructs. Always use the API, as in drawing ovals or filling polys, where your own constructs get much too long.

But the third is tricky: To use System.arrayCopy() or Arrays.fill(), or not? My guess is that for using such methods once, your have to pay the full overhead, but by using them frequently, the overhead should decrease ... where is the breakeven, when your own constructs start to get more expensive than the call overhead? I'm aware that this is almost a philosophical question and depends on the type of method we are talking about.

I'm drawing my circles myself. Admittedly this is in large part because I'm doing complicated things with them (e.g. drawing an anti-aliased circle to the alpha channel).

Of course, my general statement does not hold if the drawing functionality is a central part of your app and involves complex stuff hard to do using the API. In Ares, I referenced the backbuffer as a byte array and implemented the fake-phong rasterizer based on that.

On the other hand: setRenderingHints, setComposite and drawOval is worse than a hand-rolled antialiasing bresenham? Obviously, I don't know any details ...

Of course, my general statement does not hold if the drawing functionality is a central part of your app and involves complex stuff hard to do using the API. In Ares, I referenced the backbuffer as a byte array and implemented the fake-phong rasterizer based on that.

On the other hand: setRenderingHints, setComposite and drawOval is worse than a hand-rolled antialiasing bresenham? Obviously, I don't know any details ...

When writing the algorithm yourself you can ofcourse sacrifice speed for code simplicity/size, so bresenham's algo. might not be the best choice.

Of course, my general statement does not hold if the drawing functionality is a central part of your app and involves complex stuff hard to do using the API. In Ares, I referenced the backbuffer as a byte array and implemented the fake-phong rasterizer based on that.

On the other hand: setRenderingHints, setComposite and drawOval is worse than a hand-rolled antialiasing bresenham? Obviously, I don't know any details ...

I hadn't come across setComposite before, so thanks for that. It doesn't do everything I need for Grav4k, but I may well find it useful in the future.

I'm doing fillOval , which is simpler than drawOval. I'm also, as Abuse suggested, sacrificing some speed for simplicity.

When writing the algorithm yourself you can ofcourse sacrifice speed for code simplicity/size

Comprehension dawns ... still thinking too much from a performance point of view. Of course you could get away with evaluating a distance function per pixel, especially if you use a lut, and for filling antialiasing would be cheap. Nice one, pjt33, and thanks for the clarification, abuse!

I found today Elite Plus for DOS boxed for $6.00. It's on two 5 1/4 floppies!! But 150 pages manual its pure game design gold.

5,25" floppies?!?! What did you do with those? Got a toaster with a USB port? Anyhow, the novel included in the manual alone is worth the price!

Still playing it on DOS-Box. By the way, the original Elite was about 22k in size ... so quite a challenge to wrestle it down to 4k, despite all the help the api provides.

Brief status update: Finished the second iteration last week and ended up at 5.5k compressed. Now coding the third iteration, with many new ideas ... there is hope It looks like the space sim part (including models and all string resources for the trade sim) will end up at 3.2k, so at least a streamlined version of the trade sim should be possible. Stuff I definitely had to drop: Station and docking (you just fly straight at the planet until you automatically land), Thargoids, multi-galaxy, tribbles .Stuff that exceeds the original elite: Flat-Shaded graphics and the option to purchase a new ship (as a long-term motivation)Galaxy size is 1024 systems. Boa, Mamba, Kraith, Viper and Cobra are included. So is asteroid mining, cargo pickup, refuelling at sun.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org