# Types in action

To give you an idea how of types can be used a program has been made that creates a space ship, that flies left and right, firing lasers at set intervals.

This program relies on some external media. The easiest way of running this program is to click here and download the project. Once the file has been downloaded, extract the files and open MyFirstAGKProject.agk within AppGameKit.

There's a lot to take in with this program, as it's using types and a number of functions. Try running the program first and watch it for several seconds to see what happens.

The program moves the space ship left and right whilst continually firing lasers. The kind of data we need to store includes the speed of the ship, which direction the ship is moving in, how often the ship should fire, the speed at which the lasers move etc. All of this data could be declared as individual variables. For example, the ship's data might look like this.

    sprite as integer
    speed as integer
    direction as integer
    fireTimer as float

    laserSprite as integer [ 10 ]
    laserSpeed as float [ 10 ]
    laserState as integer [ 10 ]

This approach does work, but it's not necessarily the best way of storing the data. Think about what might happen if you needed more data for the laser - you would need to declare another array to store it. The problem is that all this data is connected to each other, but stored in lots of different arrays. It's not an ideal method to deal with your data.

Given the relationship between the data it would make sense to utilise types. The laser that gets fired could be considered as one type, while the ship could be considered as another type that contains an array of lasers. The above code could be rewritten as.

    type laserType
    	sprite as integer
    	speed as float
    	state as integer
    endtype

    type shipType
    	sprite as integer
    	speed as integer
    	direction as integer
    	fireTimer as float
    	lasers as laserType [ 10 ]
    endtype

This results in more effective way of dealing with our data. To declare one ship we simply do this.

    spaceShip as shipType

If we needed multiple ships it's just a case of changing the declaration to an array.

    spaceShip as shipType [ 5 ]

By taking this approach everything we need is now contained within the variable spaceShip. This makes our code much easier to read and manage.

Now let's take a look at the whole program.

    // create a space ship on screen that flies left and right
    // and also fires lasers

    // declare a type to store data for our lasers
    type laserType
    	sprite as integer
    	speed as float
    	state as integer
    endtype

    // declare a type to store data for our ship
    type shipType
    	sprite as integer
    	speed as integer
    	direction as integer
    	fireTimer as float
    	lasers as laserType [ 10 ]
    endtype

    // variable for our ship, make it global so it can be
    // easily accessed by all parts of the program
    global spaceShip as shipType

    // set a virtual resolution of 1024 x 768
    SetVirtualResolution ( 1024, 768 )

    // call functions to set up the ship and its lasers
    SetupShip ( )
    SetupLasers ( )

    // our main loop
    do
    	// call functions to update the ship and its lasers
    	UpdateShip ( )
    	UpdateLasers ( )

    	// update the screen
    	sync ( )
    loop

    function SetupLasers ( )

    	// this function will set up the lasers

    	// load an image for the laser
    	image = LoadImage ( "laser.png" )

    	// create sprites for each laser
    	for i = 1 to spaceShip.lasers.length
    		spaceShip.lasers [ i ].sprite = CreateSprite ( image )
    		ResetLaser ( i, 0 )
    	next i

    endfunction

    function ResetLaser ( index as integer, visible as integer )

    	// this function will reset the lasers, giving them default values

    	// state, speed, position to match the ship and visibility
    	spaceShip.lasers [ index ].state = 0
    	spaceShip.lasers [ index ].speed = Random ( 80, 100 ) / 10.0
    	SetSpritePosition ( spaceShip.lasers [ index ].sprite, GetSpriteX ( spaceShip.sprite ) + GetSpriteWidth ( spaceShip.sprite ) / 2 - 8 , GetSpriteY ( spaceShip.sprite ) - 12 )
    	SetSpriteVisible ( spaceShip.lasers [ index ].sprite, visible )

    endfunction

    function UpdateLasers ( )

    	// this function updates the lasers

    	// increment the timer to control when the lasers should fire
    	spaceShip.fireTimer = spaceShip.fireTimer + 0.01

    	// run through all the lasers
    	for i = 1 to spaceShip.lasers.length

    		// if the state is 0 then this laser is available
    		if spaceShip.lasers [ i ].state = 0

    			// only fire the laser if the fire timer is over 0.25
    			if spaceShip.fireTimer >= 0.25

    				// reset the laser, set the state to 1 and reset the timer
    				ResetLaser ( i, 1 )
    				spaceShip.lasers [ i ].state = 1
    				spaceShip.fireTimer = 0.0

    			endif

    		endif

    		// when the state is 1 the laser has been fired
    		if spaceShip.lasers [ i ].state = 1

    			// move the laser up the screen
    			SetSpritePosition ( spaceShip.lasers [ i ].sprite, GetSpriteX ( spaceShip.lasers [ i ].sprite ), GetSpriteY ( spaceShip.lasers [ i ].sprite ) - spaceShip.lasers [ i ].speed )

    			// check for the laser leaving the screen
    			if GetSpriteY ( spaceShip.lasers [ i ].sprite ) < 0

    				// reset the laser and allow it to be used again
    				ResetLaser ( i, 0 )

    			endif
    		endif
    	next i

    endfunction

    function SetupShip ( )

    	// set up for our ship

    	// create a sprite, control how fast it moves and set its initial direction
    	spaceShip.sprite = CreateSprite ( LoadImage ( "TopFighter1.png" ) )
    	spaceShip.speed = 2
    	spaceShip.direction = 0

    	// position the sprite towards the centre and near the bottom of the screen
    	SetSpritePosition ( spaceShip.sprite, 1024 / 2, 626 )

    endfunction

    function UpdateShip ( )

    	// control the movement of the ship

    	// get the X coordinate of the ship
    	x = GetSpriteX ( spaceShip.sprite )

    	// find out whether it has moved to the left or right side
    	if ( spaceShip.direction = 0 and x > 976 ) or ( spaceShip.direction = 1 and x < 0 )

    		// reverse the speed and direction
    		spaceShip.speed = -spaceShip.speed
    		spaceShip.direction = not spaceShip.direction

    	endif

    	// add the current speed to the X position
    	x = x + spaceShip.speed

    	// update the position of our ship
    	SetSpritePosition ( spaceShip.sprite, x, GetSpriteY ( spaceShip.sprite ) )

    endfunction

The program begins by declaring our types. laserType contains data for the lasers and shipType contains data about the ship, including an array of 10 lasers.

    type laserType
    	sprite as integer
    	speed as float
    	state as integer
    endtype

    type shipType
    	sprite as integer
    	speed as integer
    	direction as integer
    	fireTimer as float
    	lasers as laserType [ 10 ]
    endtype

A variable is declared named spaceShip using the type shipType. It has global prefixed to the declaration so that it will be accessible throughout the whole program, as later on some of the functions require access to it. It is possible to pass in types as parameters to functions, but for now declaring the variable as global will do.

    global spaceShip as shipType

The next part contains two calls to functions.

    SetupShip ( )
    SetupLasers ( )

Let's take a look at what the function SetupShip does.

    function SetupShip ( )
    	spaceShip.sprite = CreateSprite ( LoadImage ( "TopFighter1.png" ) )
    	spaceShip.speed = 2
    	spaceShip.direction = 0

    	SetSpritePosition ( spaceShip.sprite, 1024 / 2, 626 )
    endfunction

The function creates a sprite using the image "TopFighter1.png" and stores the sprite ID within the sprite variable, that is part of the spaceShip variable. It also assigns a value of 2 to the speed part of spaceShip. This is later used to determine how fast the ship moves across the screen. A lower value will make the ship move slower, whereas a higher value will make it move quickly. This is followed by the direction part of spaceShip getting assigned 0. This variable controls the direction in which the ship moves. If direction is 0 then the ship moves from left to right. If direction is 1 then the ship moves from right to left. The final call is used to position the newly created sprite towards the centre and bottom of the screen.

After SetupShip has finished its work a call is made to SetupLasers. This function is responsible for creating 10 lasers that the ship will fire. Let's see the code.

    function SetupLasers ( )

    	image = LoadImage ( "laser.png" )

    	for i = 1 to spaceShip.lasers.length
    		spaceShip.lasers [ i ].sprite = CreateSprite ( image )
    		ResetLaser ( i, 0 )
    	next i
    endfunction

It begins by loading an image named "laser.png" and storing its ID within the variable image. This is followed by a loop that will cycle from 1 to the size or length of the lasers array (10) contained within the spaceShip variable. For each iteration of the loop a sprite is created, with its identifier stored in the lasers array. This will give us 10 separate laser sprites that can be used by the ship. It's finished off with a call to ResetLaser.

    function ResetLaser ( index as integer, visible as integer )
    	spaceShip.lasers [ index ].state = 0
    	spaceShip.lasers [ index ].speed = Random ( 80, 100 ) / 10.0
    	SetSpritePosition ( spaceShip.lasers [ index ].sprite, GetSpriteX ( spaceShip.sprite ) + GetSpriteWidth ( spaceShip.sprite ) / 2 - 8 , GetSpriteY ( spaceShip.sprite ) - 12 )
    	SetSpriteVisible ( spaceShip.lasers [ index ].sprite, visible )
    endfunction

The ResetLaser function is used to apply default values to the lasers. It takes in two parameters letting us specify the laser to modify with the index, and the visibility of the sprite using visible. SetupLasers calls this function to modify all 10 lasers that get created and sets visible to 0. The actual function sets the state of each laser to 0 (the state determines whether it's available to be fired), gives it a random speed, sets its position to match that of the space ship and finally sets the sprite to be visible or invisible.

The next part of the program is the main loop.

    do
    	UpdateShip ( )
    	UpdateLasers ( )

    	sync ( )
    loop

It calls the functions UpdateShip and UpdateLasers.

Here's the UpdateShip function.

    function UpdateShip ( )
    	x = GetSpriteX ( spaceShip.sprite )

    	if ( spaceShip.direction = 0 and x > 976 ) or ( spaceShip.direction = 1 and x < 0 )
    		spaceShip.speed = -spaceShip.speed
    		spaceShip.direction = not spaceShip.direction
    	endif

    	x = x + spaceShip.speed

    	SetSpritePosition ( spaceShip.sprite, x, GetSpriteY ( spaceShip.sprite ) )
    endfunction

The function performs a few simple operations. It gets the X position of the space ship sprite. It then checks whether the ship is moving left or right and if it has left the boundaries of the screen. If this condition is met the ship is set to move in the opposite direction. Finally the position of the ship is updated using the modified X value.

The UpdateLasers function cycles through all 10 lasers and will launch one every so often.

    function UpdateLasers ( )
    	spaceShip.fireTimer = spaceShip.fireTimer + 0.01

    	for i = 1 to spaceShip.lasers.length
    		if spaceShip.lasers [ i ].state = 0
    			if spaceShip.fireTimer >= 0.25

    				ResetLaser ( i, 1 )
    				spaceShip.lasers [ i ].state = 1
    				spaceShip.fireTimer = 0.0
    			endif
    		endif

    		if spaceShip.lasers [ i ].state = 1
    			SetSpritePosition ( spaceShip.lasers [ i ].sprite, GetSpriteX ( spaceShip.lasers [ i ].sprite ), GetSpriteY ( spaceShip.lasers [ i ].sprite ) - spaceShip.lasers [ i ].speed )

    			if GetSpriteY ( spaceShip.lasers [ i ].sprite ) < 0
    				ResetLaser ( i, 0 )
    			endif
    		endif
    	next i
    endfunction

The function performs the following tasks.

- It begins by incrementing a timer contained within spaceShip by 0.01 every time the function is called.
- It then performs a for loop cycling through all of the lasers that the ship has.
- If the state of the laser is 0 then another check is made to see if the fireTimer is greater than or equal to 0.25. If this is the case a laser can be fired.
- When the condition is met to launch a laser the ResetLaser function is called passing in the index of the laser to launch and setting its visibility to 1. This is followed by a state change to 1, meaning this laser has been launched. Last of all the fireTimer is reset to 0.0 letting us specify a delay before firing the next laser.
- When the state of a laser is 1 this means the laser has been fired. Any lasers with this state must continually move up the screen. When the laser is off screen (checked by its Y value being less than 0), it gets reset and its visibility set to 0. The reset function returns its state to 0, meaning that it can be used to fire again.

Overall it's quite a simple program but it does demonstrate how effective types can be when grouping data together.