Pre-requisite: it is assumed
that you have read through
the prior tutorials, and are familiar with basic I/O concepts, and how to
echo messages to the top and bottom of the screen in an XNACS1Lib-based
game, including data.
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 multiple shapes (specifically, multiple rectangles)
at the same time,
using the
XNACS1Lib
library
See an easy example of how more complicated programs are built up out of
smaller, less complex parts. This is an incredibly important theme in
computer programming
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 the first rectangle's
center at the top of the screen, and the last rectangle's center at the bottom
of the screen, along with three labeled rectangles, 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, as well as the
underlying XNA library. The goal of this tutorial is to show you the
basics of drawing shapes on-screen.
In the two previous tutorials, you learned how to work
with a
rectangle, and a circle. In this tutorial, you
will work with multiple rectangles on the screen at once. You will do this
simply by taking all the code that was needed to work with a single rectangle, and correctly
duplicating that code three times (you can't quite copy-and-paste, but the
changes that you will need to make are quite small). In terms of the actual
programming, this will be a very simple task. In fact, it's a deceptively
simple task.
Since you already know how to do all the individual parts
of this tutorial, you should instead focus on the incredibly power concept of
composition
, as you work through this tutorial. Notice that you can
create a new, bigger program simply by combining the smaller, individual parts
that you already know about in a new way. This idea that you can
compose
a program out of a new combination of stuff you already know is one
of the most important, core concepts of computer programming. As someone
learning to program, it's much more important that you get a solid understanding
of a smaller number of concepts, and get really really good at composing those
concepts in new ways, in order to solve increasingly complex problems.
So while the actual code for this tutorial should be very
easy, see if you can think about this idea of composing programs from smaller
pieces, as you work through this tutorial.
3. Examining The Program:
Let's examine the
C# source code that produces the behavior we see on-screen
Declaring the instance variables
We need to declare our instance variables before we can use them.
public
class Game1 :
XNACS1Base
{
private
XNACS1Rectangle
aRec, bRec,
cRec;
// Rectangle-A, B and C
// The one line
above is equivalent to:
// private
XNACS1Rectangle aRec; // Rectangle-A
// private
XNACS1Rectangle bRec; // Rectangle-B
// private
XNACS1Rectangle cRec; // Rectangle-C
Since we want to create three rectangles, and we want them to exist throughout our program, we'll
declare them as an
instance variables
.
Keep in mind that each rectangle needs it's own, unique name. We
can think of them as
A
,
B
, and
C
, and include that in
their names, along with something that will tell us what the variable is
referring to (since they refer to rectangles, we'll use the abbreviation Rec),
thus giving us aRec, bRec, and cRec.
Notice that we declare all three variables on one line.
Declaring them all on one line, like we've done here, is exactly
equivalent as doing
private
XNACS1Rectangle
aRec;
// Rectangle-A
private
XNACS1Rectangle
bRec;
// Rectangle-B
private
XNACS1Rectangle
cRec;
// Rectangle-C
Generally, declaring many variables on one line isn't recommended, as it
makes it harder to figure out where you've declared your variables - it's
very easy to skim over, say, bRec, and not notice it when you're looking for
it. Visual Studio does have a number of ways to help you find things
(look under the Edit
→Find And Replace menu;
Control+F is the keyboard shortcut for 'Quick Find'), but you generally
don't want to have to use something like that when you're looking to quickly
find something in your program.
Having said all that, once you do get a job
programming, you should plan on adopting whatever style your co-workers are
using. It's best for everyone on a team to be consistent, so everyone
knows what to expect.
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);
// Allocate and initialize Rectangles
aRec =
new
XNACS1Rectangle
();
aRec.LowerLeft =
new
Vector2
(10.0f,
10.0f);
aRec.Width = 20.0f;
aRec.Height = 30.0f;
aRec.Label =
"A LowerLeft at:"
+ aRec.LowerLeft;
bRec =
new
XNACS1Rectangle
();
bRec.LowerLeft =
new
Vector2
(40.0f,
10.0f);
bRec.Width = 20.0f;
bRec.Height = 30.0f;
bRec.Label =
"B LowerLeft at:"
+ bRec.LowerLeft;
cRec =
new
XNACS1Rectangle
();
cRec.LowerLeft =
new
Vector2
(70.0f,
10.0f);
cRec.Width = 20.0f;
cRec.Height = 30.0f;
cRec.Label =
"C LowerLeft at:"
+ cRec.LowerLeft;
}
Again, we have the exact same sequence of steps that we used in previous
tutorials, repeated here, for each of the shapes that we want to draw on
the screen.
Note that we need to be very careful,
especially when cutting and
pasting
, to make sure that we're using the correct variable name!
Notice that while this is a fair bit of code, it's easy to understand
because you can decompose the large block into three smaller blocks: one to
create and initialize the "A" rectangle, one to create and initialize the
"B" rectangle, and one to create and initialize the "C" rectangle.
Within each of those smaller blocks, you can clearly see all the individual
lines that you previously learned about in the prior tutorials.
You should go through each of these lines, and make sure that you're
clear on what each and every line does.
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(
"Rectangle-A
Center at:"
+ aRec.Center);
EchoToBottomStatus(
"Rectangle-C
Center at:"
+ cRec.Center);
}
Since we don't want to change anything, we don't need to update
anything.
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 referring 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.
Using rectangles on your own: positioning and sizing the rectangles
Start this exercise using
Exercise_
3
'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 rectangle is the same size it is now, but it's flush with
the lower-left corner of the screen.
The middle rectangle is the same size it is now, and but it's lower
corner is at (20, 30)
The right-most rectangle is the same size it is now, but it's flush with
the lower-right corner of the screen
The labels should be set to the rectangle's name (A, B, or C), as well
as the lower-left corner of the rectangle.
Using rectangles on your own: positioning and sizing the rectangles
Start this exercise using
Exercise_
4
'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 rectangle is now 10 wide and 10 tall, but it's flush with
the lower-left corner of the screen.
The middle rectangle is now 40 wide and 20 tall, and it's flush with the
bottom of the screen and the right edge of the left-most rectangle
The right-most rectangle is now 10 wide and 30 tall, and it's flush with
the bottom of the screen and the right edge of the middle rectangle
The messages must be drawn so that they are all visible (except for the
left one, which will go off the screen). The main thing is that the
label for rectangles A or C should NOT be covered up by rectangle B.
The labels should be set to the rectangle's name (A, B, or C), as well as
the lower-left corner of the rectangle.
Optionally, you can remove the messages from the top & bottom of the
screen, but you are not required to.
Using rectangles on your own: positioning and sizing the rectangles
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)
All rectangles are flush with the right edge of the screen.
The bottom-most rectangle is now 16 wide and 16 tall, and is flush with
both the right edge, and the bottom edge of the screen..
The middle rectangle is now 8 wide and 8 tall, and it's bottom edge is 4
units higher than the top of the rectangle below it.
The top-most rectangle is now 4 wide and 4 tall, and it's bottom edge is
4 units higher than the top of the rectangle below it.
It's ok for the labels to go off the screen, as pictured above.
The labels should be set to the rectangle's name (A, B, or C), as well as
the lower-left corner of the rectangle.
Optionally, you can remove the messages from the top & bottom of the
screen, but you are not required to.