Pre-requisite: it is assumed
that you have read through
the prior tutorials, and are familiar with the concepts covered in those
tutorials.
It may be useful to refer to refer to
the diagram illustrating the Draw-Update loop
(which explains that your
initialization code will be called once, and then the XNACS1Lib will repeatedly call your Update method
(after which it will Draw the screen) ), in order to have a clear picture of how your game executes.
Goals:
In this tutorial, we will:
Examine how to work with a circle via the
XNACS1Lib
library
1. Obtain the example code
Here is the
zip file
to the source
files and compiled executable of this example.
Download and unzip the zip file and you will see an
ExampleProgram
folder. Open the
ExampleProgram
folder, the
EXE
folder contains the compiled program and you can double click on the
.sln
file to work with the source code.
Once we compile and run this project, the program displays "
Circle
Center at {X:70 Y:30}
" at the top of the screen, and "
Circle
Center Color: {R:127 G:255 B:212 A:255}
" at the bottom of the screen, along
with a circle near the middle-right of the window. The circle is labeled
with it's radius, like so:
Other than exiting when the player presses the 'Back' button (or the keyboard
equivalent), the program does not respond to user input.
2. Background
:
The tutorials that follow this one will begin to make
greater use of the graphical capabilities of XNACS1Lib. The goal of this tutorial is to show you the
basics of drawing a Rectangle on-screen so that in future tutorials you can
focus on other topics in computer programming, without having to simultaneously
learn about graphics.
Please note that since the process of drawing a circle is
very similar to the process of drawing a rectangle, this tutorial is very
similar to the prior tutorial on drawing a rectangle. Most of the verbiage
has been retained in this tutorial, and you may want to read through this
tutorial before reading through the rectangle tutorial
3. Examining The Program:
Let's examine the
C# source code that produces the behavior we see on-screen
Declaring the instance variables
public
class Game1 :
XNACS1Base
{
private
XNACS1Circle
MyCircle;
// A Circle
Since we want the circle to exist throughout our program, we'll
declare the circle as an
instance variable
.
Since we want to have access to the circle, we'll need to declare a reference to a
circle
object
. We do this with the line
private
XNACS1Circle
MyCircle;
.
As discussed in the tutorial on instance variables, the word
private
is
basically boilerplate text, the word
MyCircle
is the name that we've chosen to give the
circle, and the semi-colon at the end is required by C#.
What's new is the word
XNACS1Circle
. As you
might guess from the '
XNACS1
'
part of the word, this type of circle is not a normal circle that's
built into basic XNA, but instead is a new, enhanced, and easier-to-use
circle built into the XNACS1Lib library.The XNACS1Lib is already
included in the project that you can download for this tutorial.
In this particular program, the circle will never change, but in most
games, it normally would be changed. So even though we could get away
with declaring
MyCircle
to be a
local variable inside, say, the Update method, we have decided instead to make
it into an instance variable. Again, we're setting things up so you
will be familiar with how things are normally done, even if there's a
slightly better approach that could have been used in this particular,
contrived example.
For now, we're just going to
use
the rectangle, and not worry
about to
create
our own types of objects (creating multiple objects,
and the multiple classes that define them, are at the core of
object-oriented programming, and will be left till later).
InitializeWorld():
We told C# to create instance variables for our Game1. It's
important that we give our variables well-defined values before we use them,
like so:
protected
override
void
InitializeWorld()
{
World.
SetWorldCoordinate(
new
Vector2
(0,0),
100.0f);
// Initialize circle
MyCircle =
new
XNACS1Circle
();
MyCircle.Center =
new
Vector2
(70.0f,
30.0f);
MyCircle.Radius = 10.0f;
MyCircle.Label =
"Circle With
Radius="
+
MyCircle.Radius;
}
Much like in the previous tutorial on instance variables, we will first
initialize the circle, before we use it. However, you'll notice
that unlike initializing the
float
s
,
there is an extra step here:
MyCircle =
new
XNACS1Circle
();
For now, it's enough to simply memorize that all the new data types that
you'll see in the XNACS1Lib will need two steps to use them:
Declare a variable of the right type (for example, the instance
variable
private
XNACS1Circle
MyCircle;
)
Create a new object of the right type (for example,
MyCircle =
new
XNACS1Circle
();
in the InitializeWorld method)
In case you're curious, where's what's going on: Data types in C# can be
divided into 2 broad categories:
value types
, and
reference types
.
A value type is any variable holds a value directly. A
float
is a value
type because
float
variables holds a single, floating point number itself. A
Vector2
is a value type because
Vector2
variables directly holds a pair of
float
s - one to
store the
X
value, and one to store the
Y
value.
(Technically, value types can be further subdivided into
simple types
,
like
float
s, and
regular,
struct
, value types, like
Vector2
s). With a
reference type
, on the other
hand, the variable does NOT store a value directly. Instead, the
variable holds a
reference
to an object. This will
actually be really handy later on, but for right now, we just need to
remember that for a reference type, we need to go through two steps, rather
than just one: (1) declare the variable, and (2) create a
new
object to use. Given the following code (which,
technically, creates 3 local variables):
float
aNumber;
aNumber = 3.14f;
Vector2
aPoint;
aPoint.X = 3f;
aPoint.Y = 2f;
XNACS1Circle
aCircle;
aCircle =
new
XNACS1Circle
();
Here is a picture of what the computer's memory would look like after
the above code has run:
The key point to note is that the
value types
store their values
(essentially) directly inside the variable, while a variable for a
reference type
actually contains a memory reference (a reference to a
different location in memory) to the actual object, which is located
elsewhere in memory.
You may be asking yourself "Based on what was just explained, it's
really important that I remember to create a
new
XNACS1Circle
object.
But in that prior tutorial, why did we use
new
with the
Vector2?" In a nutshell - with reference types, you
have
to use
new
, but with value
types, you have the
option
of using
new
.
Having created a 'blank' circle (one that is composed of a number of
different properties (a.k.a. data fields), each of which has the default
value (this is why there are all those zero's in the circle object in the
above picture)), we need to go on to initialize each of the different
properties.
MyCircle.Center =
new
Vector2
(70.0f,
30.0f);
By setting the Center property, you set location of the
center point of the circle. Notice that since since the
location of that center is a point, we can conveniently set that location by
creating and initializing a temporary
Vector2
variable:
MyCircle.Center=
new
Vector2
(70.0f,
20.0f);
and then copying an entire
Vector2
directly into the LowerLeft property:
MyCircle.Center =
new Vector2
(70.0f,
20.0f);
Notice that this is a great example of
using
new
to initialize (but not
create) a value type - the Vector2 the represents the center of the circle.
MyCircle.Radius = 10.0f;
Once we have positioned the
circle, we then need to tell the
circle how large it should be. We do that by
assigning a floating point number to the Radius properties, as
demonstrated above.
MyCircle.Label =
"Circle With Radius="
+ MyCircle.Radius;
Lastly, we set the message that we want
to display on the rectangle. You'll notice that we use the same
approach here, that we used with the EchoToTopStatusBar message: we have
textual messages that we enclose in double-quotes, concatenated with numbers
using the + symbol.
Unlike the EchoToTopStatus command, here we do not put the message
inside parentheses. Instead, we assign the message to the Label
property, which tells the circle to remember the message until it's time to
draw itself.
One quick note: Since the output never changes, we never need to (re)adjust
anything after we've initialized it. So for this tutorial, it is
sufficient to initialize everything, and then do nothing.
UpdateWorld():
At this stage, we'll make use of the UpdateWorld
method in order to have our Update step actually do something.
protected
override
void
UpdateWorld()
{
if
(GamePad.ButtonBackClicked())
this
.Exit();
EchoToTopStatus(
"Circle
Center at:"
+ MyCircle.Center);
EchoToBottomStatus(
"Circle
Center Color:"
+ MyCircle.CenterColor);
}
Since we don't want to change anything, we don't need to update
anything.
In the previous steps, we declared a variable that can refer to a
circle, then we actually created the circle object, and then we
initialized the circle with it's location, radius, and label.
Once again, notice the circle is being drawn automatically.
Notice that
our UpdateWorld never actually changes the circle in any way.
FURTHER EXERCISES::
Start from a blank starter project (1000.201, if you need it), and re-do
the code from memory as much as possible. On your first try, do what
you can, and keep the above code open so that when you get stuck, you can
quickly look up what you forgot (and that after you finish a line, so that
you can compare your line to the 'correct' line). On the next try, do
the same thing, but try to use the finished code less. Repeat this
until you can type everything, without refering the tutorial's code.
Repeat this exercise daily for several days, so that you really get the
hang of this. As you go on, periodically review this by re-doing this
exercise.
Understanding the program: Object Creation
As a starting point, use the project from the above tutorial. Try removing the line that creates the circle object, and see what
error message it generates. One way to do this would be to comment
this line out:
MyCircle =
new
XNACS1Circle
();
Make sure that you remember this error message, because it's a very
distinctive error message - it (basically) only happens when you've
forgotten to create an object. Also make sure that you
remember whether this error occurred at compile-time, or when the
program was running.
Understanding the program before you code
By hand, calculate the location of the center of the circle, for each of the
following situations. Make sure to submit your answers via whatever
mechanism your instructor has specified.
the lowest edge of the circle just touches the line Y = 10 (i.e,. the
lowest edge is 10 units from the bottom of the screen), the left-most edge
just touches the line X = 10 (i.e,. the leftmost edge is 10 units from the
left side of the screen), and the radius is 10.
the lowest edge of the circle just touches the line Y = 3 (i.e,. the
lowest edge is 3 units from the bottom of the screen), the left-most edge
just touches the line X = 33 (i.e,. the leftmost edge is 33 units from the
left side of the screen), and the radius is 7.
Understanding the program before you code
By hand, calculate the location of the top-most, left-most, bottom-most, and
right-most point on each of the following of the circles, given their
centers and radii. Make sure to submit your answers via whatever
mechanism your instructor has specified.
Center = (20,20), radius = 10
Center = (50,20), radius = 12
Center = (-2, 20), radius = 17
Using circles on your own: positioning and sizing a circle
Start this exercise using
Exercise_
5
's starter project
,
which is a nearly identical copy of the project that was used in the above
tutorial.
Change the program so that your program looks like the following picture
(details of where stuff needs to go is listed after the picture)
The circle's size is the same (radius is 10.0f), but the location of the
circle's center is now (20.0f, 50.0f). It's ok if the circle goes off the
screen.
The circle's label should be set "Circle with radius=10"
Using circles on your own: positioning and sizing a circle
Start this exercise using
Exercise_
6
's starter project
,
which is a nearly identical copy of the project that was used in the above
tutorial.
Change the program so that your program looks like the following picture
(details of where stuff needs to go is listed after the picture)
The left-most edge of the circle touches the left edge of the screen,
and the bottom-most edge of the circle touches the bottom of the screen.
The circle's radius is 15.
The circle's label should be set "Circle with radius=10"
Using circles on your own: positioning and sizing a circle
Start this exercise using
Exercise_
7
's starter project
,
which is a nearly identical copy of the project that was used in the above
tutorial.
Change the program so that your program looks like the following picture
(details of where stuff needs to go is listed after the picture)
The right-most edge of the circle touches the right edge of the screen,
and the bottom-most edge of the circle touches the bottom of the screen.
The circle's radius is 23.
The circle's label should be set "Circle with radius=23"
Using circles on your own: coloring a circle
Start this exercise using
Exercise_
8
's starter project
,
which is a nearly identical copy of the project that was used in the above
tutorial.
Change the program so that your program looks like the following picture
(details of where stuff needs to go is listed after the picture)
The circle is in the same place (70,30) as in the tutorial, and has the
same radius.
The circle's label should be set "Circle with radius=10"
In order to get the same colors as used in the picture, you can use the
following code, in the InitializeWorld method (putting this after the line
that assigns the label is good)
MyCircle.CenterColor =
Color
.DarkGreen;
MyCircle.OutsideColor =
Color
.FloralWhite;
MyCircle.LabelColor =
Color
.Yellow;
For this exercise, you must choose new colors for the center color of the
circle, the outside color of the circle, and the color of the label.
Choose whatever you want. You can do this most easily in (at least)
two ways:
Go to the line
MyCircle.CenterColor =
Color
.DarkGreen;
,
and delete the
.
DarkGreen
.
Don't forget to delete the period!! Then type in ., and let IntelliSence
offer you a lot of choices.