Upload
ira-waters
View
212
Download
0
Tags:
Embed Size (px)
Citation preview
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