If you don't need thread synchronization, use StringBuilder instead of
StringBuffer.

R/

On Mon, May 25, 2009 at 3:47 PM, Robert Green <rbgrn....@gmail.com> wrote:
>
> 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