36
1 Adding Tomato Targets Session 12.2

11 Adding Tomato Targets Session 12.2. Session Overview We now have a game which lets a player bounce a piece of cheese on a bread bat Now we have

Embed Size (px)

Citation preview

11

Adding Tomato Targets

Session 12.2

Session Overview

We now have a game which lets a player bounce a piece of cheese on a bread bat

Now we have to add some targets for the player to steer the cheese towards

We are going to add a line of tomato targets across the top of the screen

When the cheese hits a tomato the tomato will disappear

Chapter 12.2: Adding Tomato Targets 2

Adding Tomato Targets

We want to have a large number of targets We also want it to be easy to change the

number of targets we have

The way to manage a large number of items is by creating an array

The above code declares the array reference and sets the number of tomatoes at 20

These variables are part of the game world

Chapter 12.2: Adding Tomato Targets 3

GameSpriteStruct[] tomatoes;int numberOfTomatoes = 20;GameSpriteStruct[] tomatoes;int numberOfTomatoes = 20;

The Tomato Texture

The targets we are going to add are tomatoes

They will all be drawn from the same texture

The texture was created and added as content in the same way as the bread and cheese

Chapter 12.2: Adding Tomato Targets 4

tomatoTexture = Content.Load<Texture2D>("Images/Tomato");tomatoTexture = Content.Load<Texture2D>("Images/Tomato");

Arrays of Structures

Putting the bread and cheese information into GameSpriteStruct structures was a good move

Not only did it make them easy to manage, but it also made it possible for us to store lots of sprites very easily, simply by making an array of GameSpriteSruct values

Once you have created a type of your own, you can use it in arrays like any other C# type

Your new type becomes another building block in your programs

Chapter 12.2: Adding Tomato Targets 5

Creating the Tomato Array

This statement creates an array of GameSpriteStruct values that will hold the tomatoes in the game

The size of the array is given by the variable numberOfTomatoes

Each element of the array is created “empty” with numeric fields set to 0 and reference fields set to null

Chapter 12.2: Adding Tomato Targets 6

tomatoes = new GameSpriteStruct[numberOfTomatoes];tomatoes = new GameSpriteStruct[numberOfTomatoes];

Spacing Out the Tomatoes

This statement creates a local variable that holds the space between each tomato on the row

This is calculated from the drawable width of the display (maxDisplayX – minDisplayX) divided by the number of tomatoes that we are drawing

This means the game will handle different numbers of tomatoes or sized displays automatically

Chapter 12.2: Adding Tomato Targets 7

float tomatoSpacing = (maxDisplayX - minDisplayX) / numberOfTomatoes;float tomatoSpacing = (maxDisplayX - minDisplayX) / numberOfTomatoes;

Setting Up the Tomato Sprites

This small loop sets up all the tomato sprites

For each sprite the code sets the texture and then sets its position and size by calling setupSprite

Chapter 12.2: Adding Tomato Targets 8

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

Sprite Setup for Loop

This for loop works through each tomato in turn The local variable i is created to count through

the elements in the tomatoes array

Chapter 12.2: Adding Tomato Targets 9

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

Sprite Setup Loop

This makes the texture reference in each tomato refer to the same tomato texture

This means that all tomatoes will look the same

Chapter 12.2: Adding Tomato Targets 10

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

Calling setupSprite for Each Sprite

This call sets up each sprite

It uses the same method as is used to set up the bread and cheese sprites

Chapter 12.2: Adding Tomato Targets 11

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

Passing a Reference to the Sprite

setupSprite needs a reference to the sprite it is going to work on

Otherwise the element will be passed by value

Chapter 12.2: Adding Tomato Targets 12

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

Setting the Size of Each Tomato

setupSprite needs a reference to the sprite it is going to work on

Otherwise the element will be passed by value

Chapter 12.2: Adding Tomato Targets 13

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

Setting the Speed of Non-Moving Tomatoes

The tomatoes don’t move in this version of the game

However, we still have to provide a speed value

Chapter 12.2: Adding Tomato Targets 14

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

Setting Tomato X Position

The X position of each tomato is calculated using the spacing value we created earlier

The first one will be at the left-hand edge

Chapter 12.2: Adding Tomato Targets 15

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

Setting Tomato Y Position

All the tomatoes are presently along the very top of the screen

We set their Y position to reflect this

Chapter 12.2: Adding Tomato Targets 16

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteTexture = tomatoTexture; setupSprite( ref tomatoes[i], 0.05f, // 20 tomatoes across the screen 1000, // 1000 ticks to move across the screen minDisplayX + (i * tomatoSpacing), // x position minDisplayY); // y position}

The Tomato Update Behavior

During Update,we need to copy the X and Y positions of each tomato into the Rectangle that will be used to draw it

We need to do this even though the tomatoes don’t move at the moment

Chapter 12.2: Adding Tomato Targets 17

// Update the tomatoes

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteRectangle.X = (int)tomatoes[i].X; tomatoes[i].SpriteRectangle.Y = (int)tomatoes[i].Y;}

// Update the tomatoes

for (int i = 0; i < numberOfTomatoes; i++){ tomatoes[i].SpriteRectangle.X = (int)tomatoes[i].X; tomatoes[i].SpriteRectangle.Y = (int)tomatoes[i].Y;}

The Tomato Draw Behavior

The Draw behavior is very simple

The for loop works its way through each tomato

The call of spriteBatch.Draw uses the texture and rectangle of each tomato element to draw it on the screen

Chapter 12.2: Adding Tomato Targets 18

for (int i = 0; i < numberOfTomatoes; i++){ spriteBatch.Draw(tomatoes[i].SpriteTexture, tomatoes[i].SpriteRectangle, Color.White);}

for (int i = 0; i < numberOfTomatoes; i++){ spriteBatch.Draw(tomatoes[i].SpriteTexture, tomatoes[i].SpriteRectangle, Color.White);}

1. Tomato Row

Chapter 12.2: Adding Tomato Targets 19

This shows our tomatoes along the top row

At the moment the cheese doesn’t interact with them

Tomato Collisions

When the cheese hits a tomato we want the tomato to disappear

This is one way the player will score points

We can detect collisions between tomatoes and the cheese by using the Intersects method provided by the Rectangle type

However, we have to find a way of making a tomato vanish

Chapter 12.2: Adding Tomato Targets 20

Objects and State

Many objects in programs have “state” An order could be “pending,” “being

packed,” or “dispatched”

A bank account could be “open,” “closed,” or “suspended”

We need to add some state information to the sprites in our game so that we can track whether they have been killed or not

We will do this for all the GameSpriteStruct values

Chapter 12.2: Adding Tomato Targets 21

Adding a Visible State to GameSpriteStruct

We are going to add a “state” to our GameSpriteStruct that determines whether or not a sprite is visible Sprites which are not visible are not drawn

on the display

Sprites which are not visible cannot collide with other sprites

When an tomato is “killed,” its state is changed so that it is no longer visible

Chapter 12.2: Adding Tomato Targets 22

Adding a Visibility State

We have added a Visible field to the sprite

It is of type bool (either true or false)

Chapter 12.2: Adding Tomato Targets 23

struct GameSpriteStruct{ public Texture2D SpriteTexture; public Rectangle SpriteRectangle; public float X; public float Y; public float XSpeed; public float YSpeed; public float WidthFactor; public float TicksToCrossScreen; public bool Visible;}

struct GameSpriteStruct{ public Texture2D SpriteTexture; public Rectangle SpriteRectangle; public float X; public float Y; public float XSpeed; public float YSpeed; public float WidthFactor; public float TicksToCrossScreen; public bool Visible;}

Setting the Visibility State

The setupSprite method now has a parameter that can be used to set up the initial visibility of a sprite

Chapter 12.2: Adding Tomato Targets 24

void setupSprite( ref GameSpriteStruct sprite, float widthFactor, float ticksToCrossScreen, float initialX, float initialY, bool initialVisibility){ // original sprite setup code here sprite.Visible = initialVisibility;}

void setupSprite( ref GameSpriteStruct sprite, float widthFactor, float ticksToCrossScreen, float initialX, float initialY, bool initialVisibility){ // original sprite setup code here sprite.Visible = initialVisibility;}

Setting Up Each Sprite

When setupSprite is called the call must now supply visibility information as a parameter

This affects the setup of the bread, the cheese, and all of the tomatoes

Chapter 12.2: Adding Tomato Targets 25

setupSprite( ref cheese, // reference to the sprite to set up 0.05f, // width factor (a 20th) 200.0f, // ticks to cross the screen minDisplayX, // starting X position minDisplayY, // starting Y position true); // initially visible

setupSprite( ref cheese, // reference to the sprite to set up 0.05f, // width factor (a 20th) 200.0f, // ticks to cross the screen minDisplayX, // starting X position minDisplayY, // starting Y position true); // initially visible

Using Visibility to Control Drawing

We need to change the tomato drawing code

Now only tomatoes that are visible will be drawn

Note that you can use a logical value directly as a condition

Chapter 12.2: Adding Tomato Targets 26

for (int i = 0; i < numberOfTomatoes; i++){ if (tomatoes[i].Visible) { spriteBatch.Draw(tomatoes[i].SpriteTexture, tomatoes[i].SpriteRectangle, Color.White); }}

for (int i = 0; i < numberOfTomatoes; i++){ if (tomatoes[i].Visible) { spriteBatch.Draw(tomatoes[i].SpriteTexture, tomatoes[i].SpriteRectangle, Color.White); }}

Detecting Tomato Collisions

This code lets the cheese bounce off tomatoes and destroy them

Chapter 12.2: Adding Tomato Targets 27

for (int i = 0; i < numberOfTomatoes; i++){ if (tomatoes[i].Visible) { if (cheese.SpriteRectangle.Intersects( tomatoes[i].SpriteRectangle)) { tomatoes[i].Visible = false; cheese.YSpeed = cheese.YSpeed * -1; break; } }}

for (int i = 0; i < numberOfTomatoes; i++){ if (tomatoes[i].Visible) { if (cheese.SpriteRectangle.Intersects( tomatoes[i].SpriteRectangle)) { tomatoes[i].Visible = false; cheese.YSpeed = cheese.YSpeed * -1; break; } }}

Breaking Out of a Loop

This statement breaks out of a for loop because we only destroy one tomato per call of Update

Chapter 12.2: Adding Tomato Targets 28

for (int i = 0; i < numberOfTomatoes; i++){ if (tomatoes[i].Visible) { if (cheese.SpriteRectangle.Intersects( tomatoes[i].SpriteRectangle)) { tomatoes[i].Visible = false; cheese.YSpeed = cheese.YSpeed * -1; break; } }}

for (int i = 0; i < numberOfTomatoes; i++){ if (tomatoes[i].Visible) { if (cheese.SpriteRectangle.Intersects( tomatoes[i].SpriteRectangle)) { tomatoes[i].Visible = false; cheese.YSpeed = cheese.YSpeed * -1; break; } }}

2. Tomato Killer

Chapter 12.2: Adding Tomato Targets 29

This version of the game allows tomatoes to be destroyed

No actual tomatoes were harmed in the production of this code

Summary

You can create arrays of types that you have created

An array variable is a reference that refers to an array instance

Several objects can “share” a single object if they each have a reference to that object

It is often useful to make an object stateful by adding a field that holds its state

The break keyword allows a program to complete a loop early

Chapter 12.2: Adding Tomato Targets 30

True/False Revision Quiz

An array variable is actually a reference.

You can create arrays of structures that you have created.

The break statement causes your program to stop.

An object in memory can only have one reference referring to it.

The state of an object can be represented by the value of a field inside the object.

Chapter 12.2: Adding Tomato Targets 31

True/False Revision Quiz

An array variable is actually a reference.

You can create arrays of structures that you have created.

The break statement causes your program to stop.

An object in memory can only have one reference referring to it.

The state of an object can be represented by the value of a field inside the object.

Chapter 12.2: Adding Tomato Targets 32

True/False Revision Quiz

An array variable is actually a reference.

You can create arrays of structures that you have created.

The break statement causes your program to stop.

An object in memory can only have one reference referring to it.

The state of an object can be represented by the value of a field inside the object.

Chapter 12.2: Adding Tomato Targets 33

True/False Revision Quiz

An array variable is actually a reference.

You can create arrays of structures that you have created.

The break statement causes your program to stop.

An object in memory can only have one reference referring to it.

The state of an object can be represented by the value of a field inside the object.

Chapter 12.2: Adding Tomato Targets 34

True/False Revision Quiz

An array variable is actually a reference.

You can create arrays of structures that you have created.

The break statement causes your program to stop.

An object in memory can only have one reference referring to it.

The state of an object can be represented by the value of a field inside the object.

Chapter 12.2: Adding Tomato Targets 35

True/False Revision Quiz

An array variable is actually a reference.

You can create arrays of structures that you have created.

The break statement causes your program to stop.

An object in memory can only have one reference referring to it.

The state of an object can be represented by the value of a field inside the object.

Chapter 12.2: Adding Tomato Targets 36