如何在Android中零对象分配的实时游戏中绘制String?

发布于 2024-11-03 07:08:27 字数 1784 浏览 1 评论 0原文

我正在 Android 中编写实时游戏,我不想在主循环中分配任何对象。问题是得分的 String 值。

我有一个类,它实现了 CharSequence 并使用 StringBuilder

public class MyString implements CharSequence {

    protected String prefix;
    protected StringBuilder stringBuilder;

    public MyString(String prefix) {
        this.prefix = prefix;
        stringBuilder = new StringBuilder(prefix);
    }

    public void setValue(int value) {
        removeValue();
        stringBuilder.append(value);
    }

    public void setValue(float value) {
        removeValue();
        stringBuilder.append(value);
    }

    private void removeValue() {
        if (prefix == null) {
            stringBuilder.setLength(0);
        } else {
            stringBuilder.setLength(prefix.length());
        }
    }

    @Override
    public char charAt(int index) {
        return stringBuilder.charAt(index);
    }

    @Override
    public int length() {
        return stringBuilder.length();
    }

    @Override
    public CharSequence subSequence(int start, int end) {
        return null; // not necessary
    }

}

这个类的用法是:

Paint paint = new Paint();
MyString myString = new MyString("Your score: ");

// Main loop
while(true) {
    myString.setValue(Game.score);
    canvas.drawText(myString, 0, myString.length(), 0, 0, paint);
}

问题是, StringBuilder.append(int)每次迭代都会创建 String 对象(通过 String.valueOf(int))。

你有什么方法来解决这样的问题?

我的下一个想法是将 intfloat 转换为字符数组,并且 setValue() 方法会将此数组添加到 StringBuilder< /代码>。该数组将存储在 MyString 类中,并且仅创建一次,然后就可以重用。但我找不到方法,如何将 float 正确转换为字符数组。 int 没有问题。

感谢您的帮助!

I'm writing real-time game in Android and I'd like to do not allocate any object in main loop. The problem is String value for score.

I have class, that implements CharSequence and uses StringBuilder:

public class MyString implements CharSequence {

    protected String prefix;
    protected StringBuilder stringBuilder;

    public MyString(String prefix) {
        this.prefix = prefix;
        stringBuilder = new StringBuilder(prefix);
    }

    public void setValue(int value) {
        removeValue();
        stringBuilder.append(value);
    }

    public void setValue(float value) {
        removeValue();
        stringBuilder.append(value);
    }

    private void removeValue() {
        if (prefix == null) {
            stringBuilder.setLength(0);
        } else {
            stringBuilder.setLength(prefix.length());
        }
    }

    @Override
    public char charAt(int index) {
        return stringBuilder.charAt(index);
    }

    @Override
    public int length() {
        return stringBuilder.length();
    }

    @Override
    public CharSequence subSequence(int start, int end) {
        return null; // not necessary
    }

}

The usage of this class is:

Paint paint = new Paint();
MyString myString = new MyString("Your score: ");

// Main loop
while(true) {
    myString.setValue(Game.score);
    canvas.drawText(myString, 0, myString.length(), 0, 0, paint);
}

The problem is, that StringBuilder.append(int) creates String object (by String.valueOf(int)) every iteration.

What is your way to solve a problem like this?

My next thought was to convert int and float to array of chars and the setValue() methods would add this array into StringBuilder. The array would be stored in MyString class and it would be created only once and then would be reused. But I can't find way, how to convert float correctly into array of chars. The int is not problem.

Thank you for your help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小红帽 2024-11-10 07:08:27

下面是我为此目的编写的一些 C# 代码。将其转换为 Java 应该非常简单。 minDigits 参数会导致左侧进行零填充——如果您愿意,可以跳过它。

// drawInteger doesn't allocate like string.Format()
int[] digitBuff = new int[10];
string[] digits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };

void drawInteger(SpriteFont font, int i, int minDigits, Vector2 pos, Color colour) {
    Debug.Assert(i >= 0 && minDigits > 0 && minDigits <= digitBuff.Length);
    int index = 0;
    while (i > 0 || index < minDigits) {
        digitBuff[index] = i % 10;
        i /= 10;
        ++index;
    }
    while (index > 0) {
        --index;
        string digit = digits[digitBuff[index]];
        sb.DrawString(font, digit, pos, colour);
        pos.X += font.MeasureString(digit).X;
    }
}

Here is some C# code that I wrote for exactly this purpose. It should be pretty simple to convert this to Java. The minDigits parameter causes zero-padding on the left -- You can skip that if you like.

// drawInteger doesn't allocate like string.Format()
int[] digitBuff = new int[10];
string[] digits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };

void drawInteger(SpriteFont font, int i, int minDigits, Vector2 pos, Color colour) {
    Debug.Assert(i >= 0 && minDigits > 0 && minDigits <= digitBuff.Length);
    int index = 0;
    while (i > 0 || index < minDigits) {
        digitBuff[index] = i % 10;
        i /= 10;
        ++index;
    }
    while (index > 0) {
        --index;
        string digit = digits[digitBuff[index]];
        sb.DrawString(font, digit, pos, colour);
        pos.X += font.MeasureString(digit).X;
    }
}
嘿哥们儿 2024-11-10 07:08:27

您可以尝试位块传送方法:
将您的“您的分数:”预先渲染为可绘制的。
然后为每个数字0-9制作drable。
在主循环中,您可以通过将所需的数字绘制到另一个绘图来构建分数字段。
我不确定这会更快,但您不需要创建任何新对象。

You could try a blitting approach:
Pre render your "Your Score: " as a drawable.
Then make drables for each digit 0-9.
In the main loop you can build your score field by drawing the numbers needed to another drawble.
I am not sure this will be faster, but you will not need to create any new objects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文