                           BOUNCING BACK AGAIN
Show the programmers how to make good games.  Bullfrog's Mark Lamport and 
Peter Molyneux return to show you how easy it is to write games with C,  
using Syndicate as an example.

Did you manage to get the Syndicate agent to bounce off the right edge of 
the screen following last month's feature?  Well for those of you who didn't
lets take a look at how its done. 

Last month's program code only enables the agent to bounce off the left-
hand side of the screen.  But if the agent is more than 307 pixels across 
the screen,  then we want to make the agent bounce left by 80 pixels.  The 
program code for this is just the same as the program code for bouncing off 
the left-hand side of the screen with a few minor alterations.  We've 
outlined these changes in figure 1.

The x coordinate is only tested if the agent is more than 307 pixels across 
the screen.  Then the x coordinate is decremented and the agent is drawn at 
the new x position while x is greater than 307 - 80 (227).  Insert the 
command "else" above the line which reads if (inkey==KB_RIGHT) and then 
insert the above program code underneath the "else".  Make sure that when 
you copy the examples you use the same letter case as the ones we've used 
because C is very particular about its upper and lower case characters.

If you were to move x number of agents on the screen you would have to 
declare lots of variables for them the way the program looks at the moment. 
However,  if you construct some sort of record structure for each Syndicate 
agent which contains their current x and y position,  their angle,  the 
animation frame,  the height and width of the sprite and their current 
state (ie if they are bouncing off the side) and some general purpose 
counter,  the program code will be more organized.  Make a backup of your 
program and rename the file called SM1.c to sample.c. See figure 2 below.  
The code has created a record structure called Man which contains the 
following elements :  X,  Y,  Angle,  Anim,  Sheigth,  Swidth,  State,  
Counter.  The type "struct" tells the C compiler that a record structure 
has to be created.  Now you have to declare the struct so that you can use 
it.  Look at the line which reads : 

Struct Man agent;

This declares a variable agent to be part of record structure man.  Now you 
have to go ahead and initialize the Syndicate agent's X and Y position,  
Angle,  Anim,  height,  width,  State and Counter.

So to access elements of the structure you need to specify the record name 
(in this case it's agent) followed by a full stop by the element name 
(which instructs your C compiler to expect an element of the structure).  
To set the X and Y elements to 25 and 50 respectively use the following 
lines of code :

agent.X=25;
agent.Y=50;

Easy isn't it.  Look at the main game loop in figure 3.  As you can see in 
the above program code,  all the elements in the agent's structure are 
initialized to a value.  So,  when you draw the agent using the routine 
draw_a_simple_sprite... you simply give the x,y and sprite animation frames 
the values agent.X,  agent.Y and agent.Anim as the parameters.

If you compile the program and run it you will see that the agent is drawn 
on the screen but doesn't animate.  That's because you haven't used the 
code for this yet.  You still want to have lots of agents on the screen,  
so you need a record structure for each agent.  You can have an array of 
structures,  which is just like an array of numbers as used in BASIC except 
that it can hold structures.  Let's create 10 structures for 10 agents.  
This is how we declare a variable structure :

struct Man agent[10];

This declares 10 record structures,  so if you wanted to initialize X to 20 
in the first record structure you would type :

agent[0].X=20; (0 is the first index of the agent array of structures).  

If you wanted to initialize X to 30 in the fourth record structure you 
would type :

agent[3].X=30;

Its easy once you get going.  Now let's draw 10 agents.  Make a backup of 
this file somewhere,  And then rename the file sm2.c sample.c and edit the 
new sample.c.  You see this line in the program :

struct Man agent[MAX_AGENTS];

This is to declare 10 record structures.  If you take a look near the top 
of the program you see that MAX_AGENTS is a #define and has a value of 10.  
See figure 4 for the code in the program.
  
Look at the line which reads setup_man();  This sets up all the agents at 
random X positions and at random angles.  The line which reads 
draw(MAX_AGENTS) draws the Syndicate agents,  and you must tell it the 
number of agents to be drawn,  in this case it is MAX_AGENTS which equals 
10.

The line in the code which reads move_man(MAX_AGENTS); moves the Syndicate 
agents,  and the first agent to be moved is your agent - the one controlled 
by the cursor keys which we created last month.  The Syndicate agents move 
in a set direction and when they hit the side of the screen they bounce off 
and then change direction.  Now re-compile the program code and run it.

Now that you have done that you can liven things up by making each agent 
bounce off to the opposite angle if they hit each other.  

Look at the line which reads void colide_man(void).  This is the start of 

the module routine that tests for collisions between the agents.  The { 
underneath tells the C compiler where the routine starts and the last } 
tells the C compiler where the routine finishes.  To test to see if the 
agents have collided,  you have to test an agent's current x position with 
all the other agents.  

So,  what we want to say is if the agent's x position is greater than or 
equal to the other agent's x position,  and if the agent's x position is 
less than or equal to the other agent's x position plus its width,  then 
bounce at the opposite angle.  Take a look at this code : 

xpos=agent[c1].X;
nxpos=agent[c2].X;
nxpwid=agent[c2].X;

xpos equals the agent's x position,  nxpos equals the other agent's x 
position nxpwid equals the other agent's width plus the x position.  The 
code to test the X collision would look something like this :

if (xpos>=nxpos && xpos <= nxpwid)

Insert the following line underneath the line which reads 
move_man(MAX_AGENTS);

colide_man(MAX_AGENTS);

Now if you re-compile the program and run it,  you find that the agents 
now bounce off each other.

Thats it for this month.  By now you can probably understand the use of 
structures well,  But if you want more information you can get hold of a 
book called The C Programming Language by Kernigan & Ritchie.  This 
includes a comprehensive explanation of the use of structures.  Anyway 
don't miss next month's installment.

FIGURE 1

if (x>307)
{
 for(x=307;x>(307-80);x-=4)
 {
  update_screen();
  draw_a_simple_sprite(x,50,sprite_frame);
  wait_for_a_while(80);
 }
}

FIGURE 2

struct Man
{
 UWORD X;
 UWORD Y;
 UBYTE Angle;
 UBYTE Anim;
 UWORD Sheight;
 UWORD Swidth;
 UBYTE State;
 UWORD Counter;
}

FIGURE 3

void my_game_bit(void)
{
 agent.X=25;
 agent.Y=50;
 agent.Angle=RIGHT;
 agent.Anim=START_RIGHT_DIRECTION;
 agent.Sheigth=28;
 agent.Swidth=18;
 agent.State=0;
 while (Inkey!=KB_ESC)
 {
  draw_a_simple_sprite(agent.X,agent.Y,agent.Anim);
  update_screen();
  keyboard();
 }
}

FIGURE 4

void my_game_bit(void)
{
 setup_man();
 while (Inkey!=KB_ESC)
 {
  draw_man(MAX_AGENTS);
  move_man(MAX_AGENTS);
  update_screen();
  Keyboard();
 }
}

