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
-~----------~----~----~----~------~----~------~--~---

Reply via email to