I don't know about NBC, but here's a slightly more micro-optimized version:
Code: Select all
// These remain "constant"
int maxval_x = ceil(xadd / -16) + 6;
int maxval_y = ceil(yadd / -16) + 4;
int init_c = floor(xadd / -16); // This one's actually unnecessary... But let's keep it consistent.
int init_d = floor(yadd / -16);
int circle_x = x + 8;
int circle_y = y + 8;
int init_c2 = (init_c << 4) + xadd; // init_c << 4 is the same as init_c * pow(2, 4) or init_c * 16
int init_d2 = (init_d << 4) + yadd;
// Relative/Delta Steps
int c2 = init_c2;
int d2 = init_d2;
CircleOut(circle_x, circle_y, 8, DRAW_OPT_FILL_SHAPE); // WHY do you keep redrawing this??
for(int c = init_c; c < maxval_x; ++c)
{
d2 = init_d2;
for(int d = init_d; d < maxval_y; ++d)
{
var[0] = map[c][d].x;
var[1] = map[c][d].y;
GraphicOutEx(c2, d2, "gmtilesb.ric", var);
d2 += 16; // Take a "delta step".
}
c2 += 16; // Take a "delta step".
}
Converting to NBC doesn't magically make it faster. Sure, NXC compiles the
for
-loops as fail-safe for every case (this could be optimized slightly), but you should really look at the actual algorithm. (In this case, I admit that it may be harder to find a "better" algorithm.)
A few micro-optimization tricks for bottlenecks;
- Are you reevaluating unchanging values? If so, put them in a temporary variable. (Such as
maxval_x
.)
- If you look at the NBC code for
CircleOut()
, you'll see that it's copying the values to a DrawCircleType
struct every time. Spiller did something similar in his Bezier Curve program when he also took the sacred route of NXC->NBC. What I recommend instead: using the SysDrawCircle()
function directly in your NXC code. Same with SysDrawGraphicEx()
.
- Notice any patterns? Can you change variables' values using relative/delta steps, instead of "absolute evaluation" (mathematicians love the "absolute" stuff, but theoretical computer scientists don't).
Here it is with the
Sys
stuff (
post under construction):
Code: Select all
// These remain "constant"
int maxval_x = ceil(xadd / -16) + 6;
int maxval_y = ceil(yadd / -16) + 4;
int init_c = floor(xadd / -16); // This one's actually unnecessary... But let's keep it consistent.
int init_d = floor(yadd / -16);
int circle_x = x + 8;
int circle_y = y + 8;
int init_c2 = (init_c << 4) + xadd; // init_c << 4 is the same as init_c * pow(2, 4) or init_c * 16
int init_d2 = (init_d << 4) + yadd;
// Relative/Delta Steps
int c2 = init_c2;
int d2 = init_d2;
// Drawing stuff
DrawCircleType dcArgs;
DrawGraphicType dgArgs;
// This is part of the code is unnecessary, unless you're putting it in a loop. I'll leave it here anyways, though.
dcArgs.Center.X = circle_x;
dcArgs.Center.Y = circle_y;
dcArgs.Size = 8; // radius
dcArgs.Options = DRAW_OPT_FILL_SHAPE;
SysDrawCircle(dcArgs);
// This part IS necessary.
dgArgs.Filename = "gmtilesb.ric";
ArrayInit(dgArgs.Variables, 0, 2);
// If that previous line doesn't work, use this instead:
// ArrayBuild(dgArgs.Variables, 0, 0);
dgArgs.Options = 0;
for(int c = init_c; c < maxval_x; ++c)
{
dgArgs.Location.X = c2;
d2 = init_d2;
for(int d = init_d; d < maxval_y; ++d)
{
// GraphicOutEx(c2, d2, "gmtilesb.ric", var);
dgArgs.Location.Y = d2;
dgArgs.Variables[0] = map[c][d].x;
dgArgs.Variables[1] = map[c][d].y;
SysDrawGraphic(dgArgs);
d2 += 16; // Take a "delta step".
}
c2 += 16; // Take a "delta step".
}
Again, micro-optimizations make your code
less readable and
less maintainable. If you're sure that your code is causing slowdowns, and you're not going to be modifying it any time soon... well, I guess it's
OK.