I’m feeling a movement part 1 – Exploratory Surgery

12-27-2017

This next section, I think is going to take a while to fully compose, in fact, I think this is going to take several sections. Moving our enemy sprites.

When we are referring to the enemy movement, there is a loop that goes through each enemy sprite and it’s a complex little loop.

The code to which I am referring is below.

// movement of sprites
for ( i = 1; i < 5; i++ )
{
	if( sprites[i].n < 0x80 )
	{
		for ( j= 0; j < num_bullets; j++ )
					
		if( abs(bullets[j].x-sprites[i].x) + abs(bullets[j].y-sprites[i].y) < 10) 		{ 			sprites[i].n+= 0x80; 			remove_bullet(j); 			tmpx= sprites[i].x>>4;
			tmpy= sprites[i].y>>4;
			tiles[tmpy * scrw + tmpx]= 66;//where enemy dies??
			//tiles[tmpy * scrw + tmpx]= 68;						
			tilepaint(tmpx, tmpy, tmpx, tmpy);						
						
			Sound(EFFX, 1+killed++%5);						
						
			*drwout= (unsigned int)update_scoreboard;
		}
					
		if( sprites[i].f&1 )
			if( sprites[i].y>0 )
			{
				sprites[i].y--;
			}
					
		else
			sprites[i].f ^= 1;

		else
			if( sprites[i].y < scrh*16 ) 				sprites[i].y++; 		else 			sprites[i].f ^= 1; 					 		if( sprites[i].f&2 ) 			if( sprites[i].x > 0 )
				sprites[i].x--;
		else
			sprites[i].f^= 2;
		else
		  if( sprites[i].x < scrw * 16 )
			sprites[i].x++;
		else
			sprites[i].f ^= 2;
	}
}

Why that looks like a hot mess there, certainly some voodoo going on. Let’s see if we can break it down.

First, let’s rehash a note that Antonio gave me

Each line is one sprite. The .n is the number of sprite (will draw a different sprite if change), the .x and .y are the coordinates (will change of position if modified), and the .f has no effect on the engine, but it’s used by the demo to store the direction of movement (it’s diagonal movement so only 4 directions).

So our first loop which shows as

for ( i = 1; i < 5; i++ )

Loops through Sprite 1 to 4

Our next line down is

if( sprites[i].n < 0x80 )

Which goes to say is if our Sprite 1-4 .N (whereas N is the sprite graphic number) is less than hex 80 Then we are going to do something.

What the devil is hex 80 doing, and why do we care if the sprite is less than 80 hex?

Hex 80 is decimal 128.

So is the Sprite is less than 128 then something will happen.

That something is the rest of the loop, however, what does the 128 represent?

I don’t know at the moment so I will play around with the line of code.

If you reverse the sign

if( sprites[i].n > 128 )

All of the enemy Sprites freeze.

If you increase the value to 256

if( sprites[i].n > 256 )

All of the enemy Sprites freeze.

If you increase the value to 255

if( sprites[i].n > 255 )

the game plays as normal.

If you comment out the line, the game plays as normal.

I may have to use another lifeline.

For now, we will ignore the line and come back to it.

Our next line of code

for ( j= 0; j < num_bullets; j++ )

Has something to do with the number of bullets we have.

In fact, it directly relates to the next If statement below it.

if( abs(bullets[j].x-sprites[i].x) + abs(bullets[j].y-sprites[i].y) < 10)

Those two lines in combination basic are saying that if any of the x number of bullets you fire hit an enemy, then, perform an action.

You can call me bracket crazy, I decided to reformat the code slightly to look like this.

for ( j= 0; j < num_bullets; j++ )//cycle through all of your bullets
{	
	//does your bullet hit a baddie
	if( abs(bullets[j].x-sprites[i].x) + abs(bullets[j].y-sprites[i].y) < 10) 	{ 		sprites[i].n += 0x80; 		remove_bullet(j); 		tmpx= sprites[i].x>>4;
		tmpy= sprites[i].y>>4;
		tiles[tmpy * scrw + tmpx]= 66;//graphic where enemy dies
					
		tilepaint(tmpx, tmpy, tmpx, tmpy);						
							
		Sound(EFFX, 1+killed++%5);						
							
		*drwout= (unsigned int)update_scoreboard;
	}
}

I am a big fan of enclosing stuff in brackets, so at a quick glance, I do not have to reinterpret the command sequence. Thus, I enclose the J loop within brackets, even though it really doesn’t matter to the compiler.

This group of commands has a lot going on that deals with the engine. A quick overview of the commands is in order.

if( abs(bullets[j].x-sprites[i].x) + abs(bullets[j].y-sprites[i].y) < 10)

If any of the bullets hit a baddie line has 3 evaluations.

abs(bullets[j].x-sprites[i].x) +
abs(bullets[j].y-sprites[i].y) <
10

This looks suspiciously like a distance formula. However, what does the 10 represent?

If you change the value to 20, then you will kill a baddie if they are immediately behind you or in front of you with a greater distance, your bullet does not even have to hit the baddie. If you change the value to 30, you kill a baddie if the distance is even greater.

Further increasing this value makes matters even worse and the distance of your bullet to kill the baddie increases.

If you decrease this value to 4, then bullets will pass through most of the enemies, unless you hit it exactly in the center.

If you change the value to 8, the evaluation seems fairly accurate, though it can allow bullets to pass through the extremities of the enemy without killing them.

In conclusion, it seems that the 10 is an offset from the center of the enemy.

Now that we know what the evaluation of hitting a baddie is, let’s look at the action taken once you hit a baddie.

sprites[i].n += 0x80;

Here, we are increasing the value of the Nth Sprite to Hex 0x80 or decimal 128.

Going back to one of my original questions, what is 128 have to do with the rest of the loop?

Well, it seems the answer is here.

If you hit a sprite, then it’s value will change to 128. Then it’s probably a value that the engine uses to make a sprite disappear or at least take it out of circulation.

Our next line

remove_bullet(j);

Calls up a function, and as it explains, removes the bullet from the screen. We may or may not evaluate this function, as it works perfectly. That function is defined in the code.

Our next two lines

tmpx= sprites[i].x>>4;
tmpy= sprites[i].y>>4;

Grab the x and y value of the baddie sprite and works with the next line below.

tiles[tmpy * scrw + tmpx]= 66;//where enemy dies

This places a tile in the spot where the baddie was.

So, the 3 lines together find the X and Y of the baddie and paints a tile where the X and Y were.

The screen needs to be updated, so the next line exists to do that very thing.

tilepaint(tmpx, tmpy, tmpx, tmpy);

This refreshes the screen from the first XY pair to the next XY pair, which just happens to be the same coordinates. In order to speed up repainting, we paint a character space where we need instead of repainting the entire screen.

Our next line

Sound(EFFX, 1+killed++%5);

Plays a sound effect. I am staying away from the sound at the moment, it’s out of scope for the moment.

Our final command is

*drwout= (unsigned int)update_scoreboard;

Updates our scoreboard, it works fine, we will perhaps explore that in the future, for right now it’s irrelevant.

There we go, a small exploration of hitting an enemy sprite. It seems like quite a bit, but hopefully, with the exploration, it’s not quite so bad.

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