Switching from while to for loop won't indeed have any impact on frame rate.
As far as I have read, compilers do normally compile both instructions to the very same thing.
Do you have any general tips on reducing function complexity?
One thing you can try is to replace local variables of actions by entity skills. Acknex do restore and save actions stack memory each frame. It has a significant impact on execution when there are a lot. Entity skills are slower to read and write, so it is not a fire-written law but something to take into account in reference to variables usage. I did a messurement of the impact of 'wait' and stack size in my oldy computer some time ago:
https://opserver.de/ubb7/ubbthreads.php?ubb=showflat&Number=474652#Post474652Recursively accesing array members by its index is a little waste of resurces that can be avoided by getting the proper pointer. I mean:
var array[100];
// acces array members by its index
int i = 0;
for(; i<100; ++i)
array[i] = random(1); // it performs an addition each loop in order to access the array member: *(array + i) = ...
// faster approach
var *ptr = array;
var *ptrLast = ptr + 100;
for(; ptr<ptrLast; ++ptr)
*ptr = random(1); // No extra additions. The more accesses to array members, the more additions it avoids.
The use of var type as indexes on arrays also have a little penalty since the program have to cast them to long type. It is just a 10 bits right shift, but you know, dunes grow grain by grain.
I will always recomend the use of function pointers on complex state machines. Function pointers let you atomize the execution and avoid the whole switch/case block commonly used to build state machines. I do normally set the function scheduler and state machines into the same system. Something like the following:
#include <acknex.h>
#include <default.c>
//-------------------------------------------------------------------------------------------
#define ITEMS_MAX 1000
typedef struct SCHEDULER_ITEM
{
void *object;
void *state(void *item);
void remover(void *item);
} SCHEDULER_ITEM;
SCHEDULER_ITEM items[ITEMS_MAX];
int itemCount = 0;
SCHEDULER_ITEM *itemAdd(void* object, void *remover, void *state)
{
SCHEDULER_ITEM *item = items + itemCount;
itemCount += 1;
item->object = object;
item->state = state;
item->remover = remover;
return item;
}
void itemRemoveAll()
{
SCHEDULER_ITEM *item = items;
SCHEDULER_ITEM *itemLast = item + itemCount;
for(; item < itemLast; ++item)
item->remover(item->object);
itemCount = 0;
}
//-------------------------------------------------------------------------------------------
// Prototypes
void *stMoveUp(ENTITY *ent);
// States
void *stWaitDown(ENTITY *ent)
{
ent->skill2 += time_step;
if(ent->skill2 > ent->skill1)
{
ent->skill4 += 1;
if(ent->skill4 > ent->skill3)
{
return NULL;
}
ent->skill1 = random(200);
ent->skill2 = 0;
return stMoveUp;
}
return stWaitDown;
}
void *stMoveDown(ENTITY *ent)
{
ent->z -= time_step * 10;
if(ent->z < ent->skill1)
{
ent->skill1 = 4 + random(16);
ent->skill2 = 0;
return stWaitDown;
}
return stMoveDown;
}
void *stWaitOnTop(ENTITY *ent)
{
ent->skill2 += time_step;
if(ent->skill2 > ent->skill1)
{
ent->skill1 = -random(200);
ent->skill2 = 0;
return stMoveDown;
}
return stWaitOnTop;
}
void *stMoveUp(ENTITY *ent)
{
ent->z += time_step * 10;
if(ent->z > ent->skill1)
{
ent->skill1 = 4 + random(16);
ent->skill2 = 0;
return stWaitOnTop;
}
return stMoveUp;
}
void sphereCreate()
{
if(itemCount > ITEMS_MAX - 1)
return;
ENTITY *ent = ent_create(SPHERE_MDL, vector(0, random(600) - 300, -random(200)), NULL);
ent->skill1 = random(200); // limit
ent->skill2 = 0; // limit counter
ent->skill3 = 1 + random(4); // Count of loops
ent->skill4 = 0; // loop counter
itemAdd(ent, ent_remove, stMoveUp);
}
//-------------------------------------------------------------------------------------------
void scheduler()
{
int index = 0;
SCHEDULER_ITEM *item = items;
for(; index < itemCount; ++index, ++item)
{
item->state = item->state(item->object);
if(item->state != NULL)
continue;
item->remover(item->object);
itemCount -= 1;
memcpy(item, items + itemCount, sizeof(SCHEDULER_ITEM)); // The fastest deletion but sorting gets broken.
index -= 1;
item -= 1;
}
}
//-------------------------------------------------------------------------------------------
void createMultipleEntities()
{
int i = 0;
for(; i<ITEMS_MAX; i+=1)
sphereCreate();
}
void main()
{
max_entities = maxv(ITEMS_MAX, 5000);
wait(3);
level_load("");
camera->x = -600;
createMultipleEntities();
on_esc = NULL;
on_space = sphereCreate;
while(!key_esc)
{
scheduler();
wait(1);
}
itemRemoveAll();
sys_exit(NULL);
}
Hope it helps...
Salud!