Basic Graphics: Drawing A Rectangle And Circle Together
References:
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 both a rectangle, and a circle
at the same time,
via the
XNACS1Lib
library
See an easy example of how more complicated programs are built up out of
smaller, less complex parts
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 rectangle's
center at the top of the screen, and circle's center at the bottom of the screen, along
with a rectangle and a circle in the window, 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 how to
combine the
basics of drawing a circle and drawing a rectangle.
In the two previous tutorials, you learned how to work
with a
rectangle, and a circle. In this tutorial, you
will simply combine the two.
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
MyRectangle;
// A Rectangle
private
XNACS1Circle
MyCircle;
// A Circle
Since we want the rectangle and the circle to exist throughout our program, we'll
declare them as an
instance variables
.
In order to make our source code easy to read, we will continue to put
each variable on it's own line, as we have been doing.
You'll notice that we can easily give each variable a meaningful name,
since each variable keeps track of something that's very different from the
other (one variable is for a rectangle, one is for a circle).
You'll notice that the statements required to declare both a circle, and
a rectangle, are the exact same as the statements required to declare either
one, individually. This is an example of how you can create a program
that has more functionality by composing the program from stuff you already
know.
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 the Rectangle
MyRectangle =
new
XNACS1Rectangle
();
MyRectangle.LowerLeft =
new
Vector2
(20.0f,
20.0f);
Again, we have the exact same sequence of steps that we used in previous
tutorials, repeated here.
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
Center at:"
+ MyRectangle.Center);
EchoToBottomStatus(
"Circle
Center at:"
+ MyCircle.Center);
}
Since we don't want to change anything, we don't need to update
anything.
Once again, notice the circle and the rectangle are drawn automatically.
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: Statements Are Executed In A Particular
Sequence
As a starting point, use the project from the above tutorial. As
it turns out, the XNACS1Lib will draw objects in the same order as the
objects where created. So if I create a rectangle, and then create a
circle (as is done in the provided tutorial, above), and the two shapes are
large enough that they overlap, you'll see an image like this:
Clearly, the rectangle was drawn on the screen, and then the circle was
drawn on the screen (over the rectangle).
What happens if your
program creates the circle first, then
the rectangle? In other words, what happens if you:
// Initialize the circle first
MyCircle =
new
XNACS1Circle
();
MyCircle.Center =
new
Vector2
(70.0f,
30.0f);
MyCircle.Radius = 20.0f;
MyCircle.CenterColor =
Color
.Black;
// set the color
so it's clear what's overlapping what
MyCircle.OutsideColor
=
Color
.Black;
// Initialize the Rectangle
second
MyRectangle =
new
XNACS1Rectangle
();
MyRectangle.LowerLeft =
new
Vector2
(20.0f,
20.0f);
What will happen if you create a small red circle centered at (2,2), and then a
larger blue circle centered at (2,2)?
Understanding the program: Statements Are Executed In A Particular
Sequence
As a starting point, use the project from the above tutorial.
Examine the code from the InitializeWorld method, and then examine the
following code.
Make sure to submit your answers to the questions below via whatever mechanism your instructor has
specified.
protected
override
void
InitializeWorld()
{
// Allocate
and initialize Rectangle and Circle
MyRectangle =
new
XNACS1Rectangle
();
MyCircle =
new
XNACS1Circle
();
MyRectangle.LowerLeft =
new
Vector2
(20.0f,
20.0f);
MyCircle.Label =
"Circle With
Radius="
+
MyCircle.Radius;
}
Notice that in the above snippet, the initialization steps for each of
the two separate objects are
interleaved
,
meaning that the steps to initialize the circle are placed in-between the
steps to initialize the rectangle. Will interleaving the code in this
way still
yields the same results as the original version of InitializeWorld? Why?
Is interleaving the initialization steps a good way to write code, even
if it is legal?
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 rectangle is the same size (40 units wide and 20 tall), but it's
lower-left corner is now at (30, 15)
The circle has a radius of 7, and is set up so that it's center is at
(70,40).
The shapes should look exactly like the above screenshot, in the sense
that the circle should be drawn
over
the rectangle, not the
other way around.
The labels should be set to the name of the shape's type (Rectangle or
Circle), as well as the radius (for the circle), and the height and width
for the rectangle.
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)
The rectangle is the 20 units wide, and 40 units tall, and it's flush
with the lower-left corner of the screen.
The circle has a radius of 10, and is set up so that it's left edge just
barely touches the left edge of the screen, and it's bottom edge just barely
touches the top of the rectangle.
The labels should be set to the name of the shape's type (Rectangle or
Circle), as well as the radius (for the circle), and the height and width
for the rectangle. It's ok if the labels go off the screen.
Using rectangles on your own: positioning and sizing the rectangles
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 rectangle is the 20 units wide, and 40 units tall, and it's flush
with the lower-right corner of the screen.
The circle has a radius of 10, and is set up so that it's right edge
just barely touches the right edge of the screen, and it's bottom edge just
barely touches the top of the rectangle.
The labels should be set to the name of the shape's type (Rectangle or
Circle), as well as the radius (for the circle), and the height and width
for the rectangle. It's ok if the labels go off the screen.
In the previous exercises, was it ever possible for you to hide the text
that's in the top/bottom status bars using the shapes (circle, rectangle)
that you draw on the screen?