1
Adding a Bread BatSession 12.1
Session Overview We have created a cheese sprite that bounces
around the display We now need to create a bread bat sprite that the
player will control and can be used to hit the cheese
In this session, we find out the best way to manage multiple sprites in a game, how a player can control the position of a sprite, and how to detect and respond to collisions between the two objects
At the end, we will have the first game play element of “Bread and Cheese”
Chapter 12.1: Adding a Bread Bat 2
Cheese Sprite Information
This is all the information that is required to represent the cheese on the screen
It includes the texture, size, and speed information for the sprite
Chapter 12.1: Adding a Bread Bat 3
Texture2D cheeseTexture;Rectangle cheeseRectangle;float cheeseWidthFactor = 0.05f;float cheeseX;float cheeseXSpeed;float cheeseY;float cheeseYSpeed;float cheeseTicksToCrossScreen = 200.0f;
Creating a Bread Sprite
To create a bread sprite we could declare a set of variables with information about the bread
Each variable matches the purpose of the corresponding cheese variable
Chapter 12.1: Adding a Bread Bat 4
Texture2D breadTexture;Rectangle breadRectangle;float breadWidthFactor = 0.05f;float breadX;float breadXSpeed;float breadY;float breadYSpeed;float breadTicksToCrossScreen = 200.0f;
Variables and Design From a design point of view, it is not sensible to
just declare a whole set of extra variables Although from a technical point of view it would
work, from a programming point of view a large number of variables with similar names is not a good play
Instead of using a convention that the word at the start of the variable name sets out which sprite it is part of, it would be nice if we had a way of grouping sprite information together
C# provides a mechanism called a structure to collect together related elements
Chapter 12.1: Adding a Bread Bat 5
The C# Struct A struct is a C# construction that brings
together methods and data Structures are very good for holding “lumps of
data” The XNA Framework and C# system library
use structures a lot A DateTime value is a struct type A Color value is a struct type
We are going to create a structure to hold a sprite
Chapter 12.1: Adding a Bread Bat 6
Cheese Sprite Information
The GameSpriteStruct type is one we have invented to hold all the data fields that this type needs
Chapter 12.1: Adding a Bread Bat 7
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;}
Creating GameSpriteStruct variables
We have added a new type to the ones available to the program
Once we have declared the structure GameSpriteStruct,we can now create variables of this type
Each variable that we declare contains all the fields of the struct that we declared
Chapter 12.1: Adding a Bread Bat 8
GameSpriteStruct cheese;GameSpriteStruct bread;
Accessing Structure Fields
A program can access fields in a structure by giving the variable name followed by the name of the required field
The statements above set the texture fields for the bread and the cheese
This works because these fields have been made public in the GameSpriteStruct declaration
Chapter 12.1: Adding a Bread Bat 9
cheese.SpriteTexture = Content.Load<Texture2D>("Images/Cheese");bread.SpriteTexture = Content.Load<Texture2D>("Images/Bread");
Public Access Modifiers in GameSpriteStruct
The fields in GameSpriteStruct are all public This makes them useable in code outside it
Chapter 12.1: Adding a Bread Bat 10
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 and Private Fields
Fields that should not be used by code outside a structure can be made private
They will be accessed by calls to public methods
Chapter 12.1: Adding a Bread Bat 11
struct BankAccount{ private float bankBalance; public void PayInFunds ( float amount) { } public void WithDrawFunds (float amount) { }}
Scaling the Bread and Cheese
We can now add statements to the ScaleSprites method to set up the bread as well as the cheese
The bread is made larger than the cheese and is able to move slightly faster
The relative speed of the bread and the cheese is something we might want to return to later
Chapter 12.1: Adding a Bread Bat 12
bread.WidthFactor = 0.15f;bread.TicksToCrossScreen = 120.0f;// rest of calculations here
1. Bread and Cheese
Chapter 12.1: Adding a Bread Bat 13
This shows the bread and the cheese together on the screen
At the moment only the cheese moves, however
Controlling the Bread Bat with a Thumbstick We are going to use the
left thumbstick to control the movement of the bread around the screen
The thumbstick provides float values in the range -1 to 1 for the X and Y directions
The values are obtained from a GamepadState variable
Chapter 12.1: Adding a Bread Bat 14
Moving the Bread Bat
The bread speed is multiplied by the position of the thumbstick
The further the thumbstick is moved, the faster the bread will move
Chapter 12.1: Adding a Bread Bat 15
GamePadState gamePad1 = GamePad.GetState(PlayerIndex.One);
bread.X = bread.X + (bread.XSpeed * pad1.ThumbSticks.Left.X);bread.Y = bread.Y – (bread.YSpeed * gamePad1.ThumbSticks.Left.Y);
bread.SpriteRectangle.X = (int)bread.X;bread.SpriteRectangle.Y = (int)bread.Y;
2. Moving the Bread
Chapter 12.1: Adding a Bread Bat 16
With this version of the game we can move the bread around
The level of control is very good, for such simple code
Improving the Program Design with Methods At the moment, the program works OK, but
some of the code still looks a bit messy The scaleSprites method is a bit of a mess
in that it contains a lot of statements that set different parts of the sprites
It would be easy to miss out one of the settings and find that a sprite did not behave correctly
A way to improve this would be to write a method that is given a set of parameters to set up a sprite
Chapter 12.1: Adding a Bread Bat 17
The setupSprite Method Header
The parameters to the method give the initial sprite settings
The setup values are calculated and used to set the sprite up
Chapter 12.1: Adding a Bread Bat 18
void setupSprite( GameSpriteStruct sprite, float widthFactor, float ticksToCrossScreen, float initialX, float initialY){ // sets the values of the sprite in here}
The setupSprite Method Body
Chapter 12.1: Adding a Bread Bat 19
{ sprite.WidthFactor = widthFactor; sprite.TicksToCrossScreen = ticksToCrossScreen; sprite.SpriteRectangle.Width = (int)((displayWidth * widthFactor) + 0.5f); float aspectRatio = (float)sprite.SpriteTexture.Width / sprite.SpriteTexture.Height; sprite.SpriteRectangle.Height = (int)((sprite.SpriteRectangle.Width / aspectRatio) + 0.5f); sprite.X = initialX; sprite.Y = initialY; sprite.XSpeed = displayWidth / ticksToCrossScreen; sprite.YSpeed = sprite.Xspeed;}
Calling setupSprite
The setupSprite method is called twice, to set up the cheese and the bread
The values are the ones that have used before
Chapter 12.1: Adding a Bread Bat 20
void setupSprites(){ setupSprite(cheese, 0.05f, 200.0f , minDisplayX, minDisplayY); setupSprite(bread, 0.15f, 120.0f, displayWidth / 2, displayHeight / 2);}
A Clearer Call of setupSprite
This call works in exactly the same way However, I have added some comments to
make it clear what each parameter does I find this format much clearer
Chapter 12.1: Adding a Bread Bat 21
setupSprite( cheese, // 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
3. Using Methods to Break Programs
Chapter 12.1: Adding a Bread Bat 22
The code is now much clearer and well designed
Unfortunately it doesn’t work
We need to find out why
The Broken Method Call
There is nothing wrong with the method There is nothing wrong with the values we
are using to call it Unfortunately, the problem is that we are
not using parameters correctly
Chapter 12.1: Adding a Bread Bat 23
setupSprite( cheese, // 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
Passing Parameters by Value
These are the parameters that are passed into the setupSprite method
They are all passed by value This is what is causing our problem
Chapter 12.1: Adding a Bread Bat 24
void setupSprite( GameSpriteStruct sprite, float widthFactor, float ticksToCrossScreen, float initialX, float initialY){ // sets the values of the sprite in here}
Passing Parameters by Value When a parameter is passed by value this
tells C# to send a copy of the value into the method that is called
The method then works on the copy This means that setupSprite will work on a
copy of the GameSpriteStruct it was given, not the original
So it will not change the fields in the cheese variable, it will change fields in the copy, which means the cheese variable will not be set up
Chapter 12.1: Adding a Bread Bat 25
Passing Parameters by Reference
We can tell the compiler we want to pass the sprite as a reference by using the keyword ref
Now the method is given a reference to the parameter variable, not a copy of it
Chapter 12.1: Adding a Bread Bat 26
void setupSprite( ref GameSpriteStruct sprite, float widthFactor, float ticksToCrossScreen, float initialX, float initialY){ // sets the values of the sprite in here}
Supplying a Reference in the Call
If you tell C# a parameter is being passed by reference you have to give a reference in the call too
This is done by putting the ref keyword in front of the variable in the method call
You can pass other types by reference too
Chapter 12.1: Adding a Bread Bat 27
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
4. Mending Methods
Chapter 12.1: Adding a Bread Bat 28
Passing references into the methods means that they are set up correctly, and the game will now work
Making the Bread Hit the Cheese When the bat hits the cheese it should
“bounce” back up the screen We can make the cheese bounce, just by
reversing the direction of the Y speed, as we do when the cheese hits the top or bottom
But we have to know when the two sprites collide
The program must detect when the player hits the cheese with the bread
Chapter 12.1: Adding a Bread Bat 29
Collisions and Rectangles
A simple collision detection can be implemented by detecting when the bread and cheese rectangles intersect
The Rectangle type provides a very easy way to do this
Chapter 12.1: Adding a Bread Bat 30
Using the Intersects Method
A Rectangle value provides an Intersects method
This is given another Rectangle to test against The method returns true if the two rectangles
intersect We can use this to bounce the cheese off the
bread
Chapter 12.1: Adding a Bread Bat 31
if (cheese.SpriteRectangle.Intersects(bread.SpriteRectangle))
{ cheese.YSpeed = cheese.YSpeed * -1;}
5. Bouncing Cheese
Chapter 12.1: Adding a Bread Bat 32
Adding just that one condition to the Update method turns the program into a game of sorts
Summary A C# struct is a way to bring together related fields Members of a struct can be private (only usable by
methods in the struct) or public (useable by all) Variables of struct type are managed by value Parameters are usually passed by value If a method is to change the value of a parameter
the parameter must be passed by reference The Rectangle class has an Intersects method that
can be used to detect when game objects collide
Chapter 12.1: Adding a Bread Bat 33
True/False Revision Quiz A C# struct can contain methods and data
fields. A C# struct is managed by value. Private fields in a struct cannot be changed. Parameters are usually passed into methods by
value. If a method is to change the value of a parameter,
the method must be passed by reference. The gamepad thumbsticks return a value between
0 and 100.
Chapter 12.1: Adding a Bread Bat 34
True/False Revision Quiz A C# struct can contain methods and data
fields. A C# struct is managed by value. Private fields in a struct cannot be changed. Parameters are usually passed into methods by
value. If a method is to change the value of a parameter,
the method must be passed by reference. The gamepad thumbsticks return a value between
0 and 100.
Chapter 12.1: Adding a Bread Bat 35
True/False Revision Quiz A C# struct can contain methods and data
fields. A C# struct is managed by value. Private fields in a struct cannot be changed. Parameters are usually passed into methods by
value. If a method is to change the value of a parameter,
the method must be passed by reference. The gamepad thumbsticks return a value between
0 and 100.
Chapter 12.1: Adding a Bread Bat 36
True/False Revision Quiz A C# struct can contain methods and data
fields. A C# struct is managed by value. Private fields in a struct cannot be changed. Parameters are usually passed into methods by
value. If a method is to change the value of a parameter,
the method must be passed by reference. The gamepad thumbsticks return a value between
0 and 100.
Chapter 12.1: Adding a Bread Bat 37
True/False Revision Quiz A C# struct can contain methods and data
fields. A C# struct is managed by value. Private fields in a struct cannot be changed. Parameters are usually passed into methods by
value. If a method is to change the value of a parameter,
the method must be passed by reference. The gamepad thumbsticks return a value between
0 and 100.
Chapter 12.1: Adding a Bread Bat 38
True/False Revision Quiz A C# struct can contain methods and data
fields. A C# struct is managed by value. Private fields in a struct cannot be changed. Parameters are usually passed into methods by
value. If a method is to change the value of a parameter,
the method must be passed by reference. The gamepad thumbsticks return a value between
0 and 100.
Chapter 12.1: Adding a Bread Bat 39
True/False Revision Quiz A C# struct can contain methods and data
fields. A C# struct is managed by value. Private fields in a struct cannot be changed. Parameters are usually passed into methods by
value. If a method is to change the value of a parameter,
the method must be passed by reference. The gamepad thumbsticks return a value between
0 and 100.
Chapter 12.1: Adding a Bread Bat 40