Okay, well now that I have a more concrete idea of what you've been having trouble with, I can help more easily now. I'll try to write this in a tutorial kind of way instead of just giving you pure code in hopes that you learn instead of just coming here every time you need someone to write code for you. I'm also not testing the code as I write this so, lol.
First off, you need to create an effect object for each digit, so decide on how many digits you want to display first. For now, I'm going to go with the assumption that you want 10 digits with no decimal places.
task DisplayScore {
let digits = [];
loop(10){
digits = digits ~ [Obj_Create(OBJ_EFFECT)]; // Yes, this is allowed. :V
}
}
Now we need to make it set up all the initial values of the effects. They're all going to be the same except with different x values so I'll use an ascent for that.
task DisplayScore {
let digits = [];
loop(10){
digits = digits ~ [Obj_Create(OBJ_EFFECT)]; // Yes, this is allowed. :V
}
ascent(i in 0..10){
let obj = digits[i]
Obj_SetPosition(obj, GetClipMaxX+32+16*i, GetClipMinY+32); // I don't know if this is a good position or not. Fiddle around with it for a bit.
ObjEffect_SetTexture(obj, imgNumber); // Make sure imgNumber is actually defined and that you loaded it.
ObjEffect_SetLayer(obj, 8); // The rest of this is copied from your post.
ObjEffect_SetPrimitiveType(obj, PRIMITIVE_TRIANGLEFAN);
ObjEffect_CreateVertex(obj, 4);
ObjEffect_SetVertexXY(obj, 0, -8, -8);
ObjEffect_SetVertexXY(obj, 1, 8, -8);
ObjEffect_SetVertexXY(obj, 2, 8, 8);
ObjEffect_SetVertexXY(obj, 3, -8, 8);
}
}
That's it for the initial set up of the effects. You might have noticed that I didn't set the UV vertices yet. That's because those need to change every time the score changes. We'll handle that in the loop in the task. However, first we need to get the score in a way where we can easily tell what each digit is, this isn't directly related to displaying the score, and since you might need to format other things that need to be displayed on the side screen, let's make a function for that.
function FormatNumberString(number, digits){
// number is the number you want to format, and digits is the number of digits you want to display
// In the case of the example score counter I'm building right now, I'd use FunctionNumberString(GetScore, 10);
let str = ToString(number);
loop(7){
str = erase(str, length(str)-1); // Erase the last 7 characters of the string because those are the decimals and the decimal point.
}
while(length(str) < digits){
str = "0" ~ str; // If the string is shorter than the amount of digits wanted, add some 0s in the beginning.
}
while(length(str) > digits){
str = erase(str, length(str)-1); // If the string is longer than the amount of digits wanted, remove the digits on the end until it fits. This is how ZUN actually handles this.
}
return str;
}
We can now use this function to get a string with digits that match up with the number of effects. The beauty about a string is that it behaves like an array of characters too, so you can do string[0] and it will give you the first character of the string. We can use this to our advantage to look at every digit in a number after converting it into a string like I just did with this function. Now let's get the basic logic out for updating the effects in the score counter.
task DisplayScore {
yield; // Yielding in the beginning because you can't create effect objects in @Initialize, yet I was expecting this task to be called in there.
let digits = [];
loop(10){
digits = digits ~ [Obj_Create(OBJ_EFFECT)]; // Yes, this is allowed. :V
}
ascent(i in 0..10){
let obj = digits[i];
Obj_SetPosition(obj, GetClipMaxX+32+16*i, GetClipMinY+32); // I don't know if this is a good position or not. Fiddle around with it for a bit.
ObjEffect_SetTexture(obj, imgNumber); // Make sure imgNumber is actually defined and that you loaded it.
ObjEffect_SetLayer(obj, 8); // The rest of this is copied from your post.
ObjEffect_SetPrimitiveType(obj, PRIMITIVE_TRIANGLEFAN);
ObjEffect_CreateVertex(obj, 4);
ObjEffect_SetVertexXY(obj, 0, -8, -8);
ObjEffect_SetVertexXY(obj, 1, 8, -8);
ObjEffect_SetVertexXY(obj, 2, 8, 8);
ObjEffect_SetVertexXY(obj, 3, -8, 8);
}
loop {
let score = FormatNumberString(GetScore, 10); // The function I just wrote earlier.
ascent(i in 0..10){
let obj = digits[i];
let number = score[i]-48; // I'm exploiting a strange quirk of Danmakufu here. I'll explain it after this code block. All you need to know for now is that I'm changing the character into a number.
let offset = number*16;
ObjEffect_SetVertexUV(obj, 0, 0+offset, 0); // Add the offset to the x value of all the vertices.
ObjEffect_SetVertexUV(obj, 1, 16+offset, 0); // It wasn't necessary to add it to the y values as you did in the code in your post.
ObjEffect_SetVertexUV(obj, 2, 16+offset, 16);
ObjEffect_SetVertexUV(obj, 3, 0+offset, 16);
}
yield; // Don't forget the yield in @MainLoop either!
}
}
If you looked at the code, you'll definitely have noticed this line: let number = score[i]-48;. This is an exploitation of how Danmakufu stores characters. Let's say, for example, that score was the string "0123456789". In this case, score[0] will return the character '0' (notice the single quotes instead of double... that is how Danmakufu differentiates between strings and characters). However if you attempt to do a mathematical operation on a character, Danmakufu will turn it into its ascii value and use that in the mathematical operation. The ascii values for the characters '0' through '9' are stored as 48 through 57. Therefore, if you subtract 48 from the ascii value of a number's character, it will become the numerical equivalent.
Anyways, so what we have here should be a working score counter now (except for any silly errors I made :V). At this point, you can stop, but there actually are ways to optimize this. If you're interested in the optimization methods I'm thinking of, just let me know, but they probably aren't necessary.