The score changes every frame. I like how it works because it's tons of tiny increments. I actually just did the thing I talked about with the reusable char[]. The only caveat is that I have to allocate a new one when the length of the string changes, but that only happens when the score has changed by a factor of 10 and I don't see scores going over 6 digits long. I suppose it's possible someone could play the game forever and score much higher but it's highly unlikely.
This is about as efficient as I will ever care to make such a thing. If you want to _never_ allocate, you could make a char[][] where the first dimension is the length of the second dimension arrays. That would be char[1], char[2], char[3], char[4] and so on. That would make it so that if your string size were 5 chars, you would say char[] correctArray = myArrays[5]. I didn't both with that because a few allocations are ok, just not one every tick of the loop. This is ugly but if you need something like this, it does work: I have a class called Util and I put this in it: private final static int[] intSizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE }; private final static char[] DigitTens = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', }; private final static char[] DigitOnes = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', }; private final static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; // Requires positive x private static int stringSize(int x) { for (int i = 0;; i++) { if (x <= intSizeTable[i]) { return i + 1; } } } public static void getChars(int i, int index, char[] buf) { if (i == Integer.MIN_VALUE) { System.arraycopy("-2147483648".toCharArray(), 0, buf, 0, buf.length); } int q, r; int charPos = index; char sign = 0; if (i < 0) { sign = '-'; i = -i; } // Generate two digits per iteration while (i >= 65536) { q = i / 100; // really: r = i - (q * 100); r = i - ((q << 6) + (q << 5) + (q << 2)); i = q; buf[--charPos] = DigitOnes[r]; buf[--charPos] = DigitTens[r]; } // Fall thru to fast mode for smaller numbers // assert(i <= 65536, i); for (;;) { q = (i * 52429) >>> (16 + 3); r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... buf[--charPos] = digits[r]; i = q; if (i == 0) break; } if (sign != 0) { buf[--charPos] = sign; } } Then in my game code it looks like this (for my FPS counter): int fps = this.fps; int fpsStringLength = Util.getSize(fps); if (fpsChars.length != fpsStringLength) { // re-allocate fpsChars = new char[fpsStringLength]; } char[] fpsChars = this.fpsChars; //copy the chars into the array Util.getChars(fps, fpsStringLength, fpsChars); StringBuffer fpsText = this.fpsText; fpsText.delete(0, fpsText.length()); fpsText.append(fpsChars).append(FPS_TEXT); canvas.drawText(fpsText, 0, fpsText.length(), worldWidth - 60, worldHeight + INFO_HEADER_HEIGHT - 20, gameResources.fpsPaint); That is SO MUCH more code than I ever wanted there but it's ridiculously more efficient than it was before so I'm going to call it good and move on. Thanks for the help everyone! On May 25, 5:19 pm, Jason Proctor <ja...@particularplace.com> wrote: > i'll suggest this again :-) > > when the score changes, convert to a string then, save it away, and > draw that each frame. at least then, you're only doing an allocation > when it changes. > > good enough? > > > > >My new method doesn't have problems with concatenating but no solution > >so far has gotten around converting an integer into a String or > >CharSequence. Any time you put an integer where a String should be, > >java automatically uses Integer.toString(i) to build a String out of > >it which allocates a char[] and also makes a new String. > > >So, besides ripping out stringSize and getChars from integer and > >holding my own char[] for the converted int, is there a clean way to > >handle that without new allocations? > > >On May 25, 4:29 pm, Jason Proctor <ja...@particularplace.com> wrote: > >> i think Mark is saying that you could redraw the score separately > >> from the label, potentially saving an implicit new StringBuffer > >> (stuff).toString () ? > > >> if score is a number, then it will need to make a new String anyway. > >> but you could cache the string of the score until the score changes, > >> so that drawing the score becomes drawing to strings as opposed to > >> going through StringBuffer. > > >> hth > > >> >It's a surface view so the whole scene must be rendered every frame. > >> >I could put it on the background I suppose but it's simple enough to > >> >just redraw the text. > > >> >On May 25, 4:10 pm, Mark Murphy <mmur...@commonsware.com> wrote: > >> >> Robert Green wrote: > >> >> > I said StringBuffer but I meant "Implied" StringBuffer, you know: > > >> >> > canvas.drawText(score + POINTS_LABEL, x, y, paint); > > >> >> Why redraw POINTS_LABEL every time? Can't you rework your scoreboard > >> to > >> >> only draw that once? > > >> >> -- > >> >> Mark Murphy (a Commons > >> >>Guy)http://commonsware.com|http://twitter.com/commonsguy > > >> >> Android App Developer Training:http://commonsware.com/training.html > > >> -- > >> jason.software.particle > > -- > jason.software.particle --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to android-developers@googlegroups.com To unsubscribe from this group, send email to android-developers-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/android-developers?hl=en -~----------~----~----~----~------~----~------~--~---