Optimizing memory part 3

1-31-2018
My big error so far is trying to directly interpret the xxxx bytes free statement as a direct statement of how many bytes there are left. But I have started to notice a pattern. If the number of bytes left is less than 12587, then there are going to be crashes at the end of the game, so we need to shave some more memory off from the routines.

Today, I’m going to examine the enemyAI function.

If you recall previously, our enemy AI function looks like this.

//remember that this is called once for every enemy
void enemyAI(unsigned char enemyData[], unsigned char playerX, unsigned char playerY)
{
    unsigned char enemyX;
    unsigned char enemyY;
    unsigned char enemyF;
    unsigned char enemyImage;
    unsigned char enemyStatus;
    unsigned char randomNumber;    
    unsigned char decision;
    unsigned char a;//junk variable
    unsigned char b;//junk variable
    
    //tiles array is unsigned char

    romCounter ++;//randomize function
    if (romCounter > 8192) romCounter = 0;//randomize function    
    
    randomNumber = bpeek (romCounter);//randomize function
    decision = 0;
    
    //artificial stupidity 2
    enemyX = enemyData[0];
    enemyY = enemyData[1];
    enemyImage = enemyData[2];
    enemyF = enemyData[3];
    enemyStatus = enemyData[4];
    
    decision = ((unsigned char)randomNumber % 5);//randomize function
    //printtester1(decision);//printtester1(decision);// 23672    
    //Pause(4);

    if (decision == 0)
    {
        //do nothing
    }
else
    if (decision == 1)
    {
        //move toward player y
        if (enemyY > playerY)
        {
            enemyY--;
        }        
        if (enemyY  playerX)
        {
            enemyX--;
        }
        if (enemyX  playerX)
        {
            enemyX--;
        }
        if (enemyX  playerY)
        {
            enemyY--;
        }
        if (enemyY  playerX + 16)
        {
            enemyX--;
        }
        if (enemyX  playerY + 16)
        {
            enemyY--;
        }
        if (enemyY  playerY)
        {
            enemyY--;
        }
        
        
        if (enemyY  playerX)
        {
            enemyX--;
        }
        if (enemyX  playerY)
        {
            enemyY--;
        }
        if (enemyY  playerX)
        {
            enemyX++;
        }
        if (enemyX  playerY)
        {
            enemyY++;
        }
        if (enemyY < playerY)
        {
            enemyY--;
        }
    }

    enemyData[0] = enemyX;
    enemyData[1] = enemyY;
    enemyData[2] = enemyImage;
    enemyData[3] = enemyF;
    enemyData[4] = enemyStatus;
}

There are 9 local variables called in that function. There are also 3 globals that are used to call the function
unsigned char enemyData[], unsigned char playerX and unsigned char playerY

We call our function from the main with the following

enemyData[0] = sprites[i].x;
enemyData[1] = sprites[i].y;
enemyData[2] = sprites[i].n;
enemyData[3] = sprites[i].f;
                    
enemyAI(enemyData, playerXpos, playerYpos);
                    
//artificial stupidity 2
sprites[i].x = enemyData[0];
sprites[i].y = enemyData[1];
sprites[i].n = enemyData[2];
sprites[i].f = enemyData[3];

There is a number of items here in this routine that can save some memory. A small array we can get rid of along with our local variables.

Let’s start with our local variables.

Move our locals in the enemies function to our Globals section

unsigned char enemyX,enemyY,enemyF,enemyImage,enemyStatus;
unsigned short decision;
unsigned char range;
unsigned char randombit2;

Our enemies function uses the following code to take in data.

enemyX = enemyData[0];
enemyY = enemyData[1];
enemyImage = enemyData[2];
enemyF = enemyData[3];
enemyStatus = enemyData[4];

However, since we are using global variables instead, we don’t really need those variables, so for now, let’s comment them out. If we compile it now, there will be some bugs, so we need a little more follow through before we can test it.

We have to add in the main.c a replacement for the variable assignment

replace the assignment as

enemyX = sprites[i].x;
enemyY = sprites[i].y;
enemyImage = sprites[i].n;
enemyF = sprites[i].f;

And now we can compile and test, Most reassuringly, it works.

At the end of our function, we use the following to send the data back to the main.

enemyData[0] = enemyX;
enemyData[1] = enemyY;
enemyData[2] = enemyImage;
enemyData[3] = enemyF;
enemyData[4] = enemyStatus;

Since our enemy data is now global, we don’t need the above code and it can be commented out.

To follow through, the returning data can be changed also

from

sprites[i].x = enemyData[0];
sprites[i].y = enemyData[1];
sprites[i].n = enemyData[2];
sprites[i].f = enemyData[3];

to

sprites[i].x = enemyX;
sprites[i].y = enemyY;
sprites[i].n = enemyImage;
sprites[i].f = enemyF;

That means our array is not needed, let’s modify our function

from

void enemyAI(unsigned char enemyData[], unsigned char playerX, unsigned char playerY)

to

void enemyAI(unsigned char playerX, unsigned char playerY)

and our call to the function

from

enemyAI(enemyData, playerXpos, playerYpos);

to

enemyAI(playerXpos, playerYpos);

That, of course, means the array enemyData can be eliminated

//unsigned char enemyData[5] = {0,0,0,0,0};//used to send enemy AI to function

We have to make sure all references to that array are eliminated as well.

Our call to the enemyAI should now look like

enemyX = sprites[i].x;
enemyY = sprites[i].y;
enemyImage = sprites[i].n;
enemyF = sprites[i].f;
                    
//artificial stupidity 2
enemyAI(playerXpos, playerYpos);
                    
//artificial stupidity 2
sprites[i].x = enemyX;
sprites[i].y = enemyY;
sprites[i].n = enemyImage;
sprites[i].f = enemyF;

Now, we are at a smaller size for our game which means we can put in some more logic.

A leaner function call and leaner function mean fast code and yes, once we compile, it is faster.

I’m going to have to nitpick along with my routines and continue to optimize. It’s the only way I’m going to be able to stuff it all in memory.

Advertisements

Author: andydansby

I'm a hobbyist coder working with the ZX Spectrum. Living in New York state near the Syracuse area. I grew up in Virgina. The first computer my parents bought for me was a Timex Sinclair 2068.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s