1 >> John Nordlinger: Hello. Good afternoon. We're... those of you remotely that are joining us, welcome back. ...

advertisement
1
>> John Nordlinger: Hello. Good afternoon. We're going to start back up. And for
those of you remotely that are joining us, welcome back. This is Kelvin Sung. You may
remember he's a professor from University of Washington Bothell, a dynamic speaker
which you've already experienced, and now you'll find out the secrets to building one of
the most popular games in history, Breakout. Let's welcome Kelvin Sung back.
>> Kelvin Sung: Thank you, John.
[applause]
>> Kelvin Sung: So thank you for staying for this afternoon's session. So what we want
to do here is, you know, if you go look at game design books, they actually teach you
how to start designing a game and all that, and that's not what we're doing. What we're
doing is we are going to base on what we want to build and analyze that.
If the ultimate goal is to design teaching materials, this is the beginning, that you identify
an application and understand how you want to build it in this environment. Once you
get that going, once you understand how to build that, then what you would do is you will
analyze the concepts that you want to teach and then map that to an application.
Okay. So what we're going to do is we're going to build the application first, and if we
can do that in fast enough time, then we look at how we can analyze concepts and map
that to applications.
So to do that, so what I'm going to do here, is if we look at the Block Breaker game and
just put on our software developer had in terms of we all develop programs and then see
what's involved in there, and this is what I'm doing. I'm going to bring up my Block
Breaker game and play that game and see what actually happened is that there are my
world and then there is my paddle, and my paddle I can move, and this guy behaves like
those guys up there. These guys are the same, and then I have a ball that's bouncing
around.
Okay. And then, you know, this is -- what we're doing is we're taking somebody else's
application and analyzing it and see how we can implement that.
But in general if you do this for yourself -- we can talk about that. And so after that you
realize that this is what you have, and I'll show you how I designed this game. And this
is what I did.
We are at section 3 now and I'm going to bring up my -- this is -- this is where we're
working from, and we're in section 3 and Block Breaker, I'm going to bring up my design
now and you guys will laugh at me. This is my design. I feel like Einstein. You know, I
wrote something down and then I have to keep it and then show people that this is how
my brilliant ideas come by.
The reason I draw this in by hand [inaudible] on purpose, I want to illustrate the point
that you don't need to actually sit down and write a design document or anything to
actually start working on this. And because these applications are really trivial to do.
In general, let me show you if we look at this as slightly more formal way, while formal,
2
slightly my respectable. I'm not sure if this is whole lot more respectable. And this is
what I actually did when I wanted to do this. And I only showed you one of the first
thing I started thinking, and the first thing I started thinking is the most dominant object
in my world. And I'm not thinking about anything else other than the dimension.
When you want to implement an interactive gaming application, interactive graphics
application, the first thing you think about is dimension. And in this case, I started
looking at this one block I have and look at it. And then the nice thing about the
capability of designing your own world dimension, remember we can specify how big
our world is, is that you are free to use anything that's convenient and do that. So notice
they look at this, I go like, huh, the ratio of this I like it to be 2:1. Okay. Fine. So let's
use that as my world unit.
So I'll take the most dominant object in my world and define that my world according to
that object -- for example, if I look at this room, I mean, if I need to design this room, I
may start using the chair as my dimension because I know how many there are and will
give me nice proportion based on this chair. So obviously that's one unit, and that's what
I did. I said this is one unit.
Alternatively, you can say this is one unit in dev.5. Today I just feel like doing that. So
this is one unit.
So now I've defined the size of my block, and then the next thing I started doing is the
horseshoe disguise P. And then I say, well, you know, there will be like around 45
percent to 90 percent height. So this is what you do before you start coding. So 45
percent to 90 percent height, this is where my block will be.
And then based on that, I say lower left corner is zero zero because it's convenient. If it's
not convenient, one thing you can do is, for example, these guys can be minus one, minus
one, where your object will be defined between zero to one, between zero zero and the
rest, so what that means is that at the very border of your application there will be one
unit that's outside, which is kind of nice, it gives you a border around your application.
So you can do that without doing anything special other than defining these point
position. Maybe we can try that at the end of this whole thing.
And then -- so this is zero zero, and then now I'm thinking that if these guys is of size two
and started counting one, two, three, I will have 15 of these in -- 15 columns of this, that
means that my world is 30. So now I have an application that starts with zero zero, width
of 30. Notice that I don't have to worry about Xbox or Zune or anything. This is my
application, and dimensions will just be defined this way.
So this is between zero to 30, and then I have -- so that's the first thing -- I'm done. And
then after that I start looking at my hero. There's a dominant distributed object that takes
up most of the world, and then I want to look at the behavior of my hero, and in this case,
I'm sorry to say that I'll be the hero. So I'll look at my behavior.
So I'm looking at this and saying -- and for every hero we have for the dominant object
we have, is you can look at it as its behavior and its appearance. And for appearance, you
start looking at texture and all that fancy stuff way, way, way back. We just start by
3
looking at appearance. The appearance is just, well, four circles, a radius. And I'm
looking at how big should this thing be, and then if you draw it and kind of have some
sense of it, a radius of .5 seem right. So radius of .5 is about the same size as the block.
That seem okay.
And then so that's what I'm going to have. And then I'm going to define behaviors, say
this guy's shoot out by the user, he bounce off the window, he breaks block. And these
are important behavior because what's going on here is I've identified class one object.
Not only that, identified the class one object and [inaudible] the math it needs to have.
So what I can do is now I can implement this entire behavior without worrying about the
rest of the game. So if you identify each one of the objects you have, and this is really
easy to do because the games that we're defining are so easy. And then you can map
these to concepts later, and we'll see how we can try to map these two concepts.
So now we have -- and then the next thing I'm going to worry about, now this is a little
bit mathematics here, is that how fast should this guy be going. And then I look in my
world and go like the world is about 30 units, the world's 30 units big, and I have a pong
ball that's moving here, and I have a stopwatch and go like one, two, three, that looks like
about enough time to -- for my ball to travel entire 30 units in about three seconds.
So the speed is displacement over -- displacement over time. So the displacement I have
here is 30 units -- or actually I have it here. But it seems like writing's better. So I have
30 units to cover, and I have three seconds to cover my 30 units, so this is my speed.
Then I start to realize that how often do I update myself. How often do I update. And
I'm telling you that it's a system constant that the update happens 40 times a second. So
there's 40 updates, updates per second. And of course seconds cancels out. So my speed
is 30 divided by 120. That's the speed I want my object to be traveling at. All right. And
this -- I didn't pull it out from the blue sky, I want my ball to travel across my window in
about three seconds' time. So that's my speed.
Now I'm ready. I can start actually to code this thing now. And what you want to do is
kind of write this stuff on the side, and then you can start writing your code. And of
course if we're teaching student this, and then we start writing our design document and
all that, which I never do.
And the company I work for, we didn't do that either. We talked about some idea, that
sounds cool, and we all went and just rolled it. Of course it didn't work very well.
I told you which company I worked with, didn't I. Oh, man [inaudible]. It was a great
environment. It was so much fun.
And then I have my paddle here, and I'm looking at my paddle, I'm a big loser here, I
can't play pong very well, so my paddle needs to be very extra long, and then I want this
thing to be slightly smaller. And then this is a paddle. And then this guy has behavior. I
like the -- this decorating objects out here. They don't have behavior, they just have
appearance. The behavior here, this guy is controlled by the user and bounces the ball.
Right? So we're done.
4
So now we have -- oh, actually, the -- I think I have one more. The last one I should have
here is what is a block. You know, a block doesn't move and then it destroys by the ball.
So what we have here is to identify the objects we have, and then we define their
interaction, and then we are actually ready to implement. And then typically when I start
implementing something like this, I start with the hero most interesting objects. Notice
the way you start designing this application, I start from the most dominant one, you start
to define the coordinate system. Once the coordinate system is defined, you figure out
the most dominant object. I usually call this guy is the hero object. And then based on
the hero object we define behavior. And then we define all the interaction between all
these things.
So that's it. So now what we can do now is we can start and implement this now. And
let's start. What we'll do is we'll start with something that we have kind of worked with
before. This is the simple circle library. And if we've come in here, let's just start
working from here. This is simple circle library. So I'm in section 3B. And I'm just
going to open up this simple X and A.
And if we look at the source code that's given to us here, we're seeing that it doesn't have
a whole lot of things in there. All I have here is that I have a circle that I'm going to use
this as a pointer, and this kind of helps me a little bit. And then what I have done is, lo
and behold, is I'm doing what I promise I would do in terms of I set up my world
coordinates as such that my lower left corner is zero zero, and then my -- the application
width is 30, and then I have this thing that I call point. I initialize it a 5-2 with a radius of
1. That's kind of just like an indication of that my application is running for me.
And then I have my update world. In my update world what I'm doing here is that I let
the user change whatever they want to do with the left arm stick. The left arm stick is
mapped to I, J, M, K, so that's kind of annoying. It's not the keyboard, it's not a down
arrow key.
So, you know, if we compiled this, we run, we're going to see our very boring -- our very
boring circle from before. I'm going to compile this thing, I'm going to run this, and I can
move this with my I, J, M, K, and this is whole lot -- this is not interesting at all.
And what I want to do now is I want to implement the behavior of hero. And the
behavior and appearance of my hero, and I'm going to introduce a new file here. And
there are many, many ways of doing that. The simplest way I found is that this is what
you tell the student to never do. I'm going to click on a file, type control C and control V
while I have another file. This window right here behaved almost identically like your
Explorer. So now I have this file. And if you double click on this file, you're going to
get exactly the same thing as you had before.
Are we all there? And then what I'm going to do now is I'm going to come in here and
delete everything because I just need a template to start working from. And the -- I'm
going to call this thing my ball class. Be careful that you're are not working with the
original game, .cs, you're working with copy of game1.cs.
Okay. And then I'm going to change the file name here also. So you can rename the file
into something interesting, so I'm going to rename this into my ball class, ball.cs.
5
The ID really spoils you. This is like eMax. Have you guys worked with eMax before?
No, this is like eMax. Once you get into the ID, you don't go out anymore. Then you
start with -- can I read my e-mail through this? I want to read my e-mail through this.
Right? That's -- I don't use eMax. I think eMax users are evil.
So, anyway, so the nice thing about doing things this way is you cut and paste, is that we
have the entire template here. So this is -- the template's here and all nice and all that.
So here's my ball class. I'll say something and then I won't do it. The right thing to do is
if you think about it, if the ball is a circle, if the ball is a circle, we should subclass from
the circle. Okay. And then I'm not going to do that because suppose [inaudible] some of
this stuff is for CS1.
So, anyway, so let's assume we don't know that we can subclass. I'm going to create a
circle, and then my circle is -- I'm just going to call it a circle. And so I'm creating a
circle. And then my circle has -- well, I want to know that if it can die, so I'm going to
call it -- I'm going to give myself expire, so the circle can expire.
And then so that's kind of it. Because my circle object has the velocity in there, and then
I can just use that.
So after that what I would do is let's just start providing ourself with a construct and all
that. And notice that instance variable of my ball class, and what I've done here is I
forgot to type in private. If you don't type -- if you don't provide it, by default they are
private.
So, anyway, so I'm going to have my construct now. My construct is public so that
everybody can construct me. And I'm going to create my class ball. And I'd be mindful
that the ball will appear where the paddle is. So during the construction -- in the
construction what I want to do here is I want to let my user tell me where I should be
constructed at. So I'm going to accept a parameter. And then I will instantiate all my
variables, and then I'm going to create -- I want to create my circle, and I want to create
my circle at a position where it's specified, and then I will have my design document
beside me and my design document will tell me that my circle's radius is 0.5.
And the -- this [inaudible] tells you that treat a number as a float, now it's a double. If
you don't say that, a lot of times the compiler will complain. So I'm going to -- I have
create -- I have instantiated my circle, and then after instantiating my circle, what I want
to do is I want to set its -- so what this has done is instantiated my circle at this position
with that radius.
And then now I know that after my circle is created, because it's going to be my -- act as
my ball, the central object there, it has a velocity. So I'm going to set this velocity. And
here I'm just going to set its velocity direction and I will do this. I will type in the X and
Y separately so we don't get too clustered.
So here is my float. I'm going to set this X velocity. And I want to do something random
because when you shoot this guy out you want it to go randomly. You don't want to go
in a well-defined direction. So I need random number. And that is why -- the random
6
number is provided as part of the base class because almost anything you want to do
that's slightly interesting, you want some random access.
So I'm going to go into my -- I'm going to go into my base class X and A base, but I have
random float function. So I went to my base class and these are static functions on the
class so that you can access it from anywhere you want. This is a global functions, right,
just like backdoor global function.
So here I'm going to go random float and then what I can do is that these random number
of random floats lets you -- gives you random number with ranges, right, so if you want
just a simple random number, you just call it like that. If you want a random number
between zero and some max number, we'll call it that way, and then if we call it with a
minus five, minus 0.50.5 to 0.5, this will give you a random number between positive and
negative 0.5.
So and then I am going to get my Y to be one. So now I have a direction that's pointing
upward, and then 0.5 -- positive 0.5, that's where my bubble shoot out. And I will assign
that to be my velocity direction. So this is just a direction, this XY.
So now I have -- my ball has a velocity going upward and kind of like in some random
direction out there, and then I'm going to remember that I want my circle to have a speed,
and speed of 30F over 120F.
In real life you define all these to be constants, right? I mean, this is crazy to actually
type in numbers like that.
And then I will say my circle should travel. Now I'm done. So if I just instantiate my
circle, I'm going to get a random circle just shooting upward. And we can try that. So
I'm going to save this, and then I'm going to come back to my game1.cs.
So what we have done here is we basically coded a behavior we want from my circle.
And what we want to do now is that we want to say that if I press a shoot button, I will
shoot on my circle. And how would I do that? I'm going to go back into my game1.cs. I
think I should weight it a little bit.
For those of you who are done, you can go back to game1.cs and shoot the circle out.
Shoot the circle out from the point. We have a point in the -- we have a point in the main
program. You can shoot circle from the main program.
So I'm going to come into my game 1 now, and then what I will do here is that I'm going
to pull in a new instance variable under the game 1 class and I'm going to call it ball and
then M ball. So that's the ball I have. And then knowing that by default I don't have
anything -- the ball gets created when you do something interesting. So inside my
initialization, I'm going to set the ball to a now pointer. So ball is initialized to now. It's
just new now.
Need to talk to some of my students. I don't speak the language well, so in class students
give me a lot of hard time telling me that pronounce things -- I shouldn't say that. I have
a student here -- telling me that I'm pronouncing things wrong. So I'll say this is now,
they'll say it's not. And then it's -- my daughters do that also, pound and -- like a water
7
pond. Yeah. And then how heavy are you pound. I'm getting it down. I'm, okay, now.
Oh, man, my daughters love that. It's like hey, dad, you can speak.
>>: [inaudible]
>> Kelvin Sung: Okay?
>>: Yes.
>> Kelvin Sung: Thank you.
>>: Somehow it doesn't like my float.
[multiple people speaking at once]
>> Kelvin Sung: Okay. So we are going to? What we have done is that we come to the
game class. We create a blowup, we declare a [inaudible] here. And then during
initialization we send it to now. And then inside the update world, what we're going to
do is we're going to check for a button A click. When you press the button A what we
will do is we will create a ball.
And then he asks you for position, where do you want to create your ball at. And what
we're going to do is we're going to create it at my point. So this is a point that I can move
around, and I'm going to create my ball at that position. And if you compile this and it
should run.
So I'm going to compile and run now. And so here is my -- here is my app. And sorry.
I'm blocking you. So just want to check if A button is clicked. If it is, then you will
instantiate a new -- instantiate a new ball. And any of you got -- start -- has your ball
bouncing around? Not bouncing around, flying around. I'm hoping some of you have
that flying around. If you have it flying around, press A many times. And you're going
to see many balls, what's going on. So if you press, oh, my, God, look at that. Do we
have balls flying now? Yes.
>>: So I was wondering, all these balls, who is holding the set?
>> Kelvin Sung: Yeah.
>>: [inaudible]
>> Kelvin Sung: The library's holding the set.
>>: So then what if later on somewhere I want to refer to the M ball object, is it the most
recent one?
>> Kelvin Sung: Yeah. The one you have is the one that just got created and it's a real
problem that they're flying all over the place.
>>: Right. Is there any way to get to the set?
8
>> Kelvin Sung: Yeah. We have to remove it.
>>: [inaudible]
>>: [inaudible]
[multiple people speaking at once]
>> Kelvin Sung: Okay. Let me just -- one thing. I wonder if you have [inaudible].
[multiple people speaking at once]
>> Kelvin Sung: If you are done with this, let's have a little bit of fun before we start
fixing a problem. Let's bound the circle. Now we have a circle. We're shooting circle all
over the place, right? Let's bound -- or, no, we're only going to bound the last one. So
let's come into the ball class and if you remember the behavior of the ball that we talk
about, so if you remember what we're talking about here, we want our ball to bounce off
window.
So what we're going to do now is in the ball class we're going to have an update function.
In that update function we are going to bound ourself. So I'm going to come to the ball
class here, and then I'm going to add in a function called updates. So here I'm going to
have a public function called update and I'll type a little bit fast so that I can finish typing
and come around and see how we're doing.
In my update function what I'm going to do here is I want to bound my circle so it
bounces around within the bound of the application. So what I'm going to do here is that
I'm going to say during my -- my update function needs to have a type, it returns void,
and then what I'm going to do here is that I'm going to say bound collides, bound collides
status, status, and then this status will be a status between X and A base dot world dot
clamp. I'm going to clamp my circle at the world bound.
Let me -- so I'm clamping my circle at the world bound. This is the code we have done
before, and then I'm going to switch on -- make sure that -- make sure that my circle stays
in there. So bounds status dot collide bottom. If I collide the bottom or if I collide with
the top, I'm going to switch my Y direction. So I'm going to collide with bottom, and
then I'm also going to collide with the top.
So if I have bound or top collision what I want to do is I want to change my velocity's -- I
want to change my velocity's Y component. So this is something we did before the
break. I'll break here. Otherwise, what I will do is that I'll check for a left and right. And
for left and right, I will change the X direction.
Velocity X. I'll [inaudible] X velocity's direction. And that's what I need to do in update.
So when I want to update, I will either flip the Y direction or the X direction. And then
what I will do is that I will call this update function from within my update world. And I
will do that only if my ball exists. So here I'm going to say if now it's not equal to my
ball, what I want to do is I want to tell the ball to update itself.
Okay. Now the ball will bounce within the bound. And then you will only get created
9
when we're ready. You have a question?
>>: Is there not some kind of container that we can add the ball to and then it will just -its update will get called regularly?
>> Kelvin Sung: That's an interesting -- that's ->>: [inaudible] added the ball to the sprat [phonetic] batch, wouldn't it invoke update and
draw automatically?
>> Kelvin Sung: Sprat batch can include the ball. The -- now you asked me a
philosophical question. The short answer is no. But in -- I am doing some of that work.
Oh, man. No, no. It's a good question. Every time I talked about this thing, people ask
me a question, I go, man, why didn't I design it that way. Because you work that way.
That's a good question.
And if people understand the question, how come I have to call this update every time.
That's absolutely true. I shouldn't. And I'm doing some of the work in update anyway
because of the fact that the circle can move around, I'm updating it. And here I'm just
calling explicitly.
So next version of library, I'll put this into the -- yeah, because I can't have that anyway,
right, because ball is not derived from primitive. If ball is derived from primitive, then I
can do it that way.
>>: [inaudible]
>> Kelvin Sung: Okay. Let's not go there. So if we are confused, that's okay. We had a
sidetrack -- excellent question, though. But then -- but then what we can do here is that
the ball now has an update function and then the update function is call inside game, and
then if we compile this and run we will see that you can shoot balls out and all over the
place and then the last one we'll -- the last one you shoot we'll just bounce around
forever. And then if you shoot a lot of them, only the last one will bounce around.
Because the other ones don't know that they belong to the ball.
Okay. So what's going on is this thing. I'm going to bring up my -- the update here so
you can look at the update if you want to. There's the library. And then here's your code.
Your code has an object -- this is ball. And ball creates a circle. This is the circle. Circle
is actually owned by the library. So whenever you create an object it's owned by the
library, this guy is called an auto draw set. Everything in this set gets automatically
redraw.
Now, C# is a managed system. So what that means is that when I say ball create another
one, what happens is that my -- I should draw my -- this way. My ball actually referred
to an object that's created inside the library. When I allocate the new ball, what happened
is that I just reassigned this pointer. This is my new circle. This is the new ball I've
created. This guy is still in the set. That's why it's still being drawn.
However, the behavior of this guy -- the behavior of this old guy, because there's no more
reference from my code, I can't control it anymore. And I'm controlling the one that I'm
10
referring to currently. So for that reason, if you have more than one of these guys going,
this is gone, this is memory leak. It's still referred by the library.
So what you need to do is when something is out of the bound of you don't need it
anymore, you actually have to delete it explicitly. And that's what we're going to do here,
is that when you want to create a new ball, instead of just creating a new one, you need to
check if you have an existing one. If you have existing one, you have to tell it to go
away.
So what I'm going to do here is I'm going to tell the old ball to go away. So I'm going to
check if now is not equal to M ball, what I'm going to do here is I have to tell the ball to
delete the draw circle. And that's the math that we don't have yet. So I'm going to come
out here and say M ball dot delete circle. And we'll go implement this method inside
ball, and here I'm just going to -- I just came over to the ball function and here I'm just
going to delete the circle. And this is how I delete a circle. Public, void, delete circle.
And then all I need to do is tell the circle to remove itself from the auto draw set.
So this last function that I call line 59 tells the circle to reprove itself from this set. So it's
not here anymore. So before you create a new ball, you tell the old one to remove itself
from the set. Okay. Now, this is the price you pay for having things happening
automatically. You create an object, you always draw itself, then when you don't want it
to draw itself you have to let it know.
It kind of takes away the nice thing about C# in terms of memory management. We kind
of have to do a little memory management here. The good thing about this thing, though,
is that your students don't need to know anything about this. So if we compile this and
run, what we're going to have is we're going to have my circle now. And then when I
shoot it, then I only have one of these guys instead of having many one of these.
Because I always remove the existing ones. So what I'm going to do now is I'm going to
show the update function. And then I walk around a little bit for those of you who are
trying to follow and [inaudible] stuck. I wonder if I can help. Yeah.
>>: So if you are not planning to come and see, there is no requirement that we need to
[inaudible] the ball.
>> Kelvin Sung: Yeah.
>>: [inaudible]
>> Kelvin Sung: Yes.
>>: [inaudible]
>> Kelvin Sung: Absolutely. You have to have a list of looking at all of them.
Otherwise you will lose track of them.
>>: [inaudible]
>> Kelvin Sung: Because you're not [inaudible].
11
>>: [inaudible]
>> Kelvin Sung: [inaudible] so if you go to game1.cs [inaudible].
>>: [inaudible] update world?
>> Kelvin Sung: Oh, you are. You're calling the update function.
>>: Okay. So where did I go wrong [inaudible]?
>> Kelvin Sung: No. You are always setting [inaudible] yes. You want to initialize that.
You okay? Okay. Are you okay? Okay.
So what we have here is actually we have this ball bouncing in our environment. And
then we want to know that when the ball collided with the bottom right here, the first
condition, we -- when that happened, we just wanted the ball to go away. So when that
happened what we want to do is we actually want to just delete the ball. Delete the circle
I mean. So I'm in the ball class right now, and then there's one special case for the delete
circle -- for the bouncing, is that if I touch the bottom, I just want the ball to go away.
So what I have right now is that every one of the -- every one of the sites are fair play
except the bottom. If you touch the bottom, the circle just go away. So that's the
indication for us that the circle has [inaudible] and then in the Block Breaker game, that's
exactly what you want.
And there we have it. We have the behavior of the ball. And if you remember our -when we start working with the ball and say how the ball should behave, that's all we say,
that you will bounce around from the side. If he touches the bottom, he dies. And then
one more behavior we don't have is the interaction of the ball with the rest of the object,
with the paddle. So that is one thing we don't have. And that's what we're going to call
next. Do we have a bouncing ball? If you don't, you're not going to let me know, right?
Are we okay? Okay. Cool.
So what we're going to do now is that now that we have the ball class, what we will do is
that we -- let's define the paddle class. And instead of trying to salvage what you have
done so far, let's work with the next version of the code so that you don't have to work
with what you have done so far. I hope what you have done so far is that you see that
you have a ball bouncing in the environment and then let's go to the next source code.
So what we have done is that we have implemented a wall class, and we're going to
implement a block and paddle class. Okay. And then after block and paddle class, then
we're basically done. So just bear with me. We have two more examples, and then we
have the Block Breaker game. That's all we have. We have like three objects, we define
our world, we have the world, and the ball. Now we can get the block and paddle
working. Then we are good.
So I'm going to take this away, and then I am going to go to my source code, and we are
done with B -- we're done with C here. This is the ball class we have. The next one we
want to go to is we want to come and look at the block and paddle class. And what we
12
want to do, though, is that we will open up source code C and start from C. We are
building towards D.
So if you open up source code as C and if you open that up, what you'll have is you'll
have a ball class and looks very similar to what we have done except that it's a little bit
prettier because we have our radius, we have our speed, and then it has an expire, it has a
count. And then if you look at the code, it's the same thing as what we have done before.
The only thing that's slightly different is my ball has a more beautiful color than what
we've seen on it. I gave you a label.
Also that's slightly interesting, is that I gave some randomness to the ball I'm shooting
out, about 30 percent randomness. So it doesn't cover the region in three seconds exactly.
There's a -- it's somewhere between two to four seconds, so that we have some
randomness in the system.
So here's my ball class. And it knows how to count itself, it can let you have access to its
velocity, it tells you where it is and then it tells you its radius. And then if you look at the
update function, that was the time -- that was the function that we kind of spend a little
bit of time in there, we see that it has an expire flag, it tells itself that it has expired. And
then for the expired, what we do is that we will remove it from the draw set. That's it.
And nothing interesting. And then you can delete the ball, and we've seen that working.
And if you just compiled this source code that we just opened up and run this, so what
you have is -- I'm going to run it now. It's exactly what we saw just now, the behavior in
terms of -- so you can shoot this guy up there in red color. And if they reach the bottom,
they go away. So what we want to do now is to -- we want to include paddles for this so
that we can bounce this ball.
Actually, even before we do that, if we want to just bounce the ball around right this time,
this is our paddle. We can use this as our paddle. So how do we do that. And let's just
see this working. So what we can do here is we come into update. I'm going to come
into update into the game1.cs, that's my main loop place. In my game1.cs, I'm going to
keep my initialized world closed for now inside the update world.
We can manipulate the pointers, so I define regions so that we can hide the code that we
don't want to look at. I can manipulate the pointer. The pointer is just changing the
center of my circle that's called endpoint. That's fine. And then here's my ball's
behavior. If we look at the ball behavior, nothing spectacular. We've seen this before. If
you click the button A, if the ball already exists, I'll tell the ball to go away and create a
new one and count.
And then I will also say if the ball is now now, if the ball exists, I will update it in the it
has expired, I'll just delete it. So these are the -- these are the behavior we've seen before.
And then I print messages out from here. These are some messages I can print out for the
user. So what I'm going to do here is that I'm just going to add in a couple of lines of
code to give the ball some behavior here.
So what I'm going to do now is I'm going to say if my point -- this is the point, collided
with my M ball dot get circle, so if my point -- this is the point I have, if that collide with
13
my circle, inside the ball, and I know that there's syntax error because we don't have that
function yet, the get circle function, if there's a collision, what I want to do is I want to
change the ball's direction, just bounce it upward.
So I'm going to say M ball dot velocity -- okay, because of syntax error, it will not let
me -- the intelligence is messed up. So what I'm going to do now is I'm going to go to the
ball class and define this get circle function so we can work with that.
So I'm going to come back to the ball class and just define the get circle function. And
the get circle function is right here. I'm going to say public [inaudible] circle, this
function will return a circle, and then you will just return the reference to the circle that I
have. So I'm going to just return that. And that's going to return that circle. So that's
done in the ball class. So the ball lets the rest of the world see the circle.
Yeah.
>>: A quick typo in that [inaudible].
>> Kelvin Sung: Really? Get circle?
>>: There you go.
>> Kelvin Sung: You know, the problem with intelligence is that you don't notice these
things anymore because they just go all over the place, and after a while you don't know
how to spell circle anymore. I have a real problem with that. I didn't know how to spell
circle to begin with. No, I really don't.
So now what I can do is that I can come up here and change the ball's velocity, and so
here I have my ball I can get at this velocity -- I'm going to flip its velocity. Oh, gee.
Don't tell me that, please.
So I'm flipping the ball's velocity. Man. This is -- I'm doing realtime programming here,
and I shouldn't. I thought I can just show you something for fun very fast.
In order to do this, what we need to do is that we need to get an instance of it and then
flip the value and then send it back again. So this is what we need to do. I'm really sorry
that I did this. So I'm going to get the -- get an instance of the velocity, and then assign
it.
And now what happened is you can use the point as a collider to actually bounce the ball
up.
>>: [inaudible] now or does that go away on its own?
>> Kelvin Sung: It's going to go away on its own because it will be garbage collected.
[inaudible] reference to it. It will be gone. To switch from C++ or C to this was very
difficult. It's like, man, should I create an instance of this, am I okay? I always have the
problem with that. But what we can do now is that we can actually start bouncing the -oh, what happened? Why is there no pointer?
14
>>: [inaudible]
>> Kelvin Sung: Oh, thank you very much. M ball may not be defined. M ball needs to
be shot. So if I want to use it, I have to check if now is equal to M ball, if not equal to,
then I will shoot the -- I don't even need -- if it's not equal -- now it's note equal to M ball,
then I can shoot -- I can do the collision.
The ID really helps you in terms of formatting and all that. You get in this really bad
habit of not formatting yourself. So what we can do now is we can shoot one of these
guys and then hey, what's going on? So I can bounce it. But I can bounce it and start
playing the pong game now. But then when I shoot, what's going on?
>>: [inaudible] because they're overlapping.
>> Kelvin Sung: Yeah. Look at that. Is that like a bug?
>>: Yeah.
[laughter]
>>: It's a feature.
>> Kelvin Sung: No, no, no. It is. I was trying to solve this problem in the library, and
then I realized I don't know what the user wants. You can't decide users' behavior. But
then I also realized that that's a really good bug to show the student and explain to them
that hey you want to be careful because I'm creating my circle inside the ball after I create
it and I start colliding it immediately, there is collision. And when there is collision I
change its Y component, so the ball started bouncing around. And if you're not
[inaudible] it's going to stay there forever. It's nice that we have X direction velocity so it
moves away. Otherwise it's just going to stay there forever. So now we have solve that
problem.
But in any case, at this point, we have like a slightly -- not a really fun but it's like a -- so
anyway, so we have something working. And what we want to do now is we want to
replace this functionality here with a paddle. Are there any questions or anything?
Anything I can help with? So if we want to create paddle, the thing that we notice is that
a paddle is just a block. A paddle is just a block, a block that can't move.
So what I want to do now is that I want to create my block. I want to create my paddle as
a subclass from block. So I'm going to copy the ball class and do the trick again, and
then this is my copy of ball. I'm going to call this my block. And I'm going to create a
block class now. Then this is my new block class, and then I'm going to delete
everything in between, and then I'm going to delete everything between here's my ball
class, I don't want it anymore. And then I'm going to define the behavior from my block.
And my block is nothing other than a rectangle. So inside my block I'm going to create a
[inaudible] rectangle. So inside my block, that's what I'm going to do. I'm going to raise
this to the top so we can see it. In the block class I'm going to create something called
rectangle, and then I will have an instantiate -- I will have a construction for my block,
and block, because I want to put them everywhere in the world, so in its constructure, I
15
will have its X and Y -- I will have its X and Y -- I will have the specified position.
And then inside here, all I do is I'm going to instantiate my instance variable that is my
rectangle. And what I'm doing here is I'm going to figure out my rectangle's position, my
rectangle's position is defined by the -- so in the correction, the first thing I'm going to do
is I'm going to define my XY position for my rectangle, that will tell me where the center
is.
And then the next thing I'm going to do is I'm going to specify the width and the height of
the rectangle, so this rectangle's constructure let me specify center, the width and the
height. And if you remember, the width and the height for the central piece of our entire
coordinate system and width is of size 2, height is 1.
So here I'm just going to specify 2 and 1. So that's kind of easy. Because that's what my
rectangle is. That's why my blocks are. And since my block don't move, I don't need to
do anything else. I just instantiate a rectangle.
And blocks, all it does is that it knows how to interact with my ball, so what a block
needs to do is that I have a public -- it will collide with ball. This is the main thing that a
block needs to do, collide with ball. And a ball, I will pass in a ball B, and then the block
will know how to collide with it. And it will return a Boolean telling me if a collision
indeed happened.
The reason why there's the red underlines is because the ID complaints are not returning
anything. Not yet, at least.
Okay. And then now I want to implement collide with ball, and then luckily the collision
is very simple because all I need to do is I will collide my -- I will collide my rectangle
with a circle, and then those guys know how to collide with each other.
So I'm going to declare a Boolean variable to remember the status, the hit status. I'm
going to say hit, and that is the same as -- that's a result of having my rectangle collided
with my ball's circle. So I'm going to get the circle out here. And that's my hit status,
whether there's a real collision.
Okay. And then one other thing I wanted to do that's slightly detailed is that -- is that
the -- if my circle hits my block on the side, I want it to bounce this way. If my circle hits
the block from the bottom, I want it to -- so if my circle hits the block from the bottom, I
want to refract this way. And if my circle hits the block on the side -- so basically I want
my circle to behave differently, depends on how it hit the block. Otherwise you have a
Block Breaker game that's kind of not a whole lot of fun because you can't collide it from
the side.
So I want to do a side collision. And this is what I'm doing. I'm going to get reference to
my circle. I should have done that earlier, but that -- pardon me. So I'm going to get a -I'm going to get a local variable that points to my actual -- I'm going to get a circle.
Because my circle is going to interact with my rectangle very often now. So I'm going to
get an instance of that. And then I want to check how did I collide with the -- how am I
colliding with the block.
16
So I'm going to say if indeed I hit the block, then I want to test. So if my circle -- my
circle touched my rectangle, then I'm going to check whether this type of situation is
mapping. And if it is, I want to react accordingly.
So how do I check that? So if there is a collision, I'm going to say I'm going to check if
my circle, which C in this case is to the right of the rectangle.
So if my circle is on the right side of my rectangle -- I'm checking this condition. If my
circle is on the right side of my rectangle, what I want to do is that I want to detect if this
is happening. If this happening, I want my reflection to go in this direction and what I
will need to do is I will need to flip the X component of the velocity.
So I'm going to check. If I am on the right side of the rectangle and my circle's velocity
in the X -- velocity X is pointing towards the -- oh, my God, I didn't think about this,
pointing towards the left, so if it's less than zero, then what I want to do is I want to flip
the circle's velocity. So I want to flip that.
So there are conditions you need to check so that you collide the block from the sides so
that things looks cooler, and else the reverse is -- else I can check the reverse. If my
circle is towards the left of my rectangle and my velocity -- if I'm approaching the left
and my velocity is towards the positive X direction and my velocity is of -- my X
velocity is greater than zero, then what I want to do is I want to flip my X velocity again.
So these are the only tricky lines for block, that I want to be able to handle the ball
colliding from the side. If you don't have that in your code, the Block Breaker games do
work. It just looks a little bit weird.
And then, finally, if I'm not on the left or I'm not on the right, then I'm just going to shut
my eyes and flip my Y direction. And then I will tell what happened to me to whoever
calls me.
So one option I think I can do is I will just present this stuff. Isn't that a whole lot more
boring, if I just save this? So what I have -- what we have done here is we have defined a
block class that knows how to collide with a ball. Not only does it know how to collide
with the ball, it knows how to tell the ball how to behave after the collision. Because
we're messing around with the ball's velocity. And we will tell ourself the collision status
afterwards.
>>: [inaudible]
>> Kelvin Sung: Yes.
>>: Just to be one of those troublesome students, so if we have a collision and the circle
is to the right of the block, could there ever be a case where the velocity of the circle is
not less than zero?
>> Kelvin Sung: Oh, you know, if this were in the physical world, it will not. But then
this kind of things can happen. And, by the way, these are great -- what happened when
student asked a request is you talk about stuff you like to talk about. And then you don't
teach them the stuff they need to know.
17
So this is where this circle is towards the right of the block. Okay. Notice that there's
some collision. And then the circle can be traveling in any direction at this point. If this
can happen because we work in the discratized [phonetic] world because the circle's
position may be out here.
In the previous update, these guys were traveling really fast, in the next update you got to
here. Or the circle can be like -- so in this case, you don't want to bounce off that way,
but then if the circle were out here before and you want an update that comes out to here.
Now, if this collision happened and you bounce off that way, then that doesn't look right.
Right? So you want to -- you know, that all the circle can come in any direction. It's a
real problem. That's why -- okay. So if we're okay with the ball and -- anyway, and then
so what I want to do now is that our block is actually done. I mean, that's all we want to
do with the block. The block doesn't move. And they just collide with the ball, and that's
all we care. And then the next thing we want to do here is that we want to define the
paddle class so that we can actually paddle the ball around.
So I'm going to copy the block function and paste block. What I did was I just copy and
paste block. Okay. And then I'm going to work with the block class and I'm going to call
this my paddle class. And my paddle class will be a subclass of block. I think I made a
mistake somewhere. My paddle class is a subclass of block.
And then I'm going to delete everything in this file so that I will define a new behavior
for my paddle because paddle's behavior is slightly different from the block. So now I
have a new clean file to work with. And I think it's my block -- oh. I didn't save it.
That's all. And that's my ball class. Okay, that's good. So here's my paddle class. My
paddle class I will subclass from the block and then I don't have any instance variable
because my behavior depends on the rectangle that's in the block.
So I don't need to have anything certain here. All I need to have is some behavior that's
slightly different from my parent, so I'm going to have an instance, I'm going to have a
constructor here.
Now, the paddle is -- unlike a block, you don't create those things on the fly. You only
have one of those things. So the paddle as constructed doesn't need to have -- the paddles
constructed, we do not need to have -- we do not need to have a parameter.
And then what we're going to do is that we're going to call our base class constructor, and
our base class constructor's a block. And block constructor expects you to tell you where
it is. And I'm going to create my paddle in the middle of the screen, and then height. My
paddle is like somewhere -- I don't know, I'm going to give it like 0.5, 0.8 above the
bottom. So this is the location of my paddle. So my paddle is a block.
And then what else I'm going to do here, is that I'm going to -- after I create this thing,
I'm going to make my paddle slightly bigger and slightly narrow -- slightly bigger, longer
and narrower. So what I'm going to do here is I'm going to change its width to -- I think I
want it to be five, and I want to change its height of the width and height that is on the
rectangle. So I'm going to change the rectangle's width and the rectangle's height to be
0.8.
18
One thing is the block needs to let the paddle see the rectangle. So this guy right here
must be protected, not private. So the paddle can actually see the -- the paddle can
actually see the rectangle.
And the paddle can move. So I'm going to come out here and define a function void so
that paddle can move. And the paddle will move by according to users command, so you
will have an input parameter X so that I can change the paddle's center position. So the
paddle's behavior is that you will move in the X direction and I will let the rectangle -- I
will change the rectangle center position accordingly.
And I'm actually done. Now we can have a paddle that I can bounce a ball around. It
looks kind of weird, but it works.
So I'm compiling here. And I will run my program. And of course you see that it doesn't
work because I don't have a paddle. Where's my paddle? I didn't create it. So I'm going
to come into my main function, I'm going to create my paddle. So here is my paddle. I'm
in my instance variable. I'm going to create paddle, p-a-d-d-l-e, paddle, I'm going to call
it M paddle. And then I will instantiate during initialization -- in the world initialization.
So here I'm going to go M paddle -- wait. M paddle, get new paddle. So I've created a
paddle for myself. Yeah.
>>: In your previous iteration of this, you had a big circle down there, and that was your
MPT.
>> Kelvin Sung: Yeah.
>>: So can't you reuse that instance variable and then just bind it? You know, instead of
having now both M points as your paddle ->> Kelvin Sung: Yeah. It's through here. The M point's a circle. The paddle is a
rectangle.
>>: [inaudible]
>> Kelvin Sung: Yeah. That's what I should do. Yeah. I can -- you're saying that I
should just delete this guy.
>>: Because you won't allow the logic based on endpoint that you want to translate ->> Kelvin Sung: Oh, I see what you're saying. Yeah. Let's do that. So this is what Barb
is suggesting there, now I have instantiated my paddle, and then I will come down to the
[inaudible] oh, right, right here. This is the place where I'm colliding my point with my
paddle -- my point with my ball, and I can just do it right here, right?
The thing, though, is that my paddle is a whole lot smaller than this circle. Because what
my paddle knows how to do is my paddle is a block that knows how to collide with the
circle. So I have more sophisticated behavior, so I can do my M paddle dot collide with
ball. How about that? Ball -- oh, sorry. So I'm colliding with the ball actually, right?
19
>>: Right.
>> Kelvin Sung: How cool is that. So if the ball is there and I'll collide with it, and what
if I collided with it? I don't really care. If I collided with it, I'm fine. Because my
collision function is so smart that you would actually flip the ball direction for me. So
that's all I need to do. Now I can actually do something smart. Right? So I can shoot out
the ball. My paddle can actually bounce the ball for me.
So if we come out here and then -- oh, look at that. Hey, I can't move my paddle, man,
because I forgot. So what I need to do of course is that I have to say my paddle M paddle
dot -- I can say dot move, move by what? Let's move it with our right thumb stick. So
I'm going to move this with my game pad dot thumb stick dot right, I'm going to use the
X movement to move my paddle.
So now I can do this thing. Oh, it moves. I can use the left thumb stick to move my ball,
and this is the shooting point. And then boom, I can shoot the circle. And then when the
circle comes around, I can bounce it with my paddle. I can do this all day. That's not
funny.
So, hey, let me show you this. So we can let the ball go away and then it behaves
properly. That's kind of cool. And here's the problem: I'm going to shoot the ball out
now from this point, it doesn't make sense. I'm going to shoot the ball out from my
paddle here. Right? So I'm going to come in here and the behavior is such that I just
opened up the ball behavior, is that if you press your button A here, if ball's not known,
I'll create one. If the ball is new, I'll create a new ball, and the new ball position should
come from my paddle.
And my paddle -- oh, this is the part where I'm going to get the position of the paddle.
Hey, notice that when I inherited my paddle, I didn't say how I'm inheriting it. So it's
inheriting as a private. So what I need to do is I think I need to do this. So what I've -oh, no. Wait. I need to make my paddle class public or else I can't get access to the
block. Because what I want to do here is that I need to get my -- okay, now I'm stuck.
What I want to do is I want to get the block's position so that I can shoot the ball. Now,
why can't I get at the position? Somebody knows C# here?
>>: So you just want to access your block?
>> Kelvin Sung: Yeah, I want to access blocks. And I thought what I need to do is I
need to make my -- when I'm inheriting block, I need to ->>: [inaudible] block public?
>> Kelvin Sung: Okay, thank you. Okay. There we go. So block needs to be public.
That's the problem. So at this point I can access the -- hold on. Okay. So what are we
missing here. I should be able to get access to the blocks ->>: [inaudible]
>> Kelvin Sung: Oh, no, it's not defining here. I need to get a block's position. Sorry,
sorry, sorry. So block needs to be able to return to its position so that we can actually get
20
access to it. I'll return it from the paddle. So paddle will return position. So here what I
can do is I'll return the position of public vector too and I will return its position that I can
create -- I can create the ball and this guy will return the position of the rectangle center.
So now I can in my game when I want I can get the block's position. This is impossible
to follow, isn't it?
>>: No.
>>: It might not be impossible for people in this room, but if you're a CS 1 student ->> Kelvin Sung: Oh, no, no, no, no.
>>: Is that what you're talking about?
>> Kelvin Sung: No, no, no. No, I'm saying for people in this room. If you are CS 1,
this is way out of -- you will not be doing any of this.
What we want to do here is we want to collide -- hold on. Sorry. I am inside my -- I'm
inside the -- when the A button's clicked, I want to bounce the -- I want to bounce the
ball -- I want to create a new ball and then based on the paddle position, and we have
that. And I think the -- it's -- wait.
So this is what's it's complaining about, that there's no access to this. I will think -- did I
make ball public? I keep on forgetting to make my classes public. And then when that's
passed around, it gets confused.
So now I'm going to shoot my ball out from the paddle, and then we can see that it gets
stuck in the paddle. And we know that that problem with that is because of the -- is
because of the -- it's because of overlapping in collision. So if you run this -- well,
whenever you try to create, boy, it's gets stuck in the paddle. And sometimes it goes up,
sometimes it doesn't.
So what that means is that during collision, besides figuring out where the objects collide,
for paddle areas we're interested in knowing that the ball is not inside the paddle. The
ball should never be inside the paddle.
Okay. So what we do is that for the paddle collision we define new function for paddle,
and we can call this function public, and then we can -- public [inaudible], so for paddle's
collision with ball, we're going to go collide with ball, so paddle knows how to collide
with ball.
And in paddle's case, what you would do is you would test to see if you are hitting the -to see if you're hitting with the ball by calling the base classes collide. So we'll call the
base class collide with ball. If there is a collision for paddle, we need to do something
special.
If there is a collision for paddle, what we want to do is we want to push the ball outside
of the paddle. So what we can do here is I'm going to get an instance of a -- I'm going to
get a circle from the ball. So what I want to do is that if the paddle and the circle collide,
21
what I want to do is I want to push the circle outside of the paddle, literally push it out.
Yes.
>>: [inaudible] when you start it up, why not just start it a little bit higher in the first
place?
>> Kelvin Sung: Because it doesn't just happen when you start it up. Because what's
happened -- in discratized world, this happens all the time. If your ball is traveling down
this direction and then -- well, we can try that. If the ball is traveling down in this
direction and then if my paddle -- if I'm out here in one update and then by the next
update if that happens, sometimes the ball gets stuck.
No. But that's a good point. So we can try that.
So if we just return my base class -- so instead of returning the center position, this is
what we're suggesting. Sorry. We're going to get my -- plus my height divided by 2.
Oh, I guess yeah, I can't be too lazy.
>>: [inaudible]
>> Kelvin Sung: I'm just going to compute the Y position so that it's right on top of the
rectangle. So here I'm going to add my right Y position by the height divided by 2, and
I'll return this P.
So what this is is that as suggested when you press the A button, what I'm going to do
now is I'm going to look at a paddle, I'm going to look at the center position, and that's
what this is, that's the center position, and then what I'm going to do now is I'm going to
push the Y value up by the height divided by 2.
And I guess I need to actually know the circle. So I'm going to return this position. And
that won't work either because what's going to happen is now the circle we created right
here. So it's still going to overlap. So if I cheat a whole lot, this is cheating a little bit.
Because I know the circle's radius, so if I come out here and go P dot Y, plus equals to
0.5, that's the circle's radius.
Now, that's going to push you out and then this will work now. I didn't push it far
enough. Almost. Rectangle's height divided by 2. Well, I wonder what's going on, why
is that not enough. Now we're really hacking. Now this will work. There we go. It
works now. But then if you hit the circle at the right angle, you're going to see the circle
get unstuck again, just like this situation can happen.
Well, that's why I quit.
>>: Cut it right on the corner.
>> Kelvin Sung: We can try to make [inaudible] happen again, but then we all know it
can happen. So we won't -- oh, there we go. So that can happen. That's why you want to
kind of push it out and make sure that that -- it doesn't actually lap.
The -- and I'll save the code for that. The next thing we can do is -- and I won't do that
22
anymore, for some reason something's not going right here. [inaudible] sightly smoother
than this. I really apologize. Yes.
>>: [inaudible]
>> Kelvin Sung: Yes. Yes.
>>: Is it different for [inaudible]?
>> Kelvin Sung: See, what we want to do is that -- the behavior is slightly different in
terms of the paddle, and after the collision the paddle is still alive, versus the block. Once
the block touches the ball, it goes away.
So whether after -- the behavior afterwards you don't care. That is why the paddle will
actually have a different behavior. That is why here after the collision you want to make
sure that the ball doesn't overlap the paddle anymore.
So that's what I was going to put in the code here. I will not test your patience. So what
I'll do next is I won't just go through this code and type all these things out. I will just tell
you what happened next. And like I say, I apologize. I'm not sure why this is not going
as smooth as it should be. But then -- and happen in classroom also. And let's pretend
it's just a really bad class.
The important thing that I hope you will walk away is that this -- to work with game-type
situations, you want to create your object and you want to update the state. The engine
should be somehow just calling your update. And if the engine is slightly more
sophisticated, you will call your draw function also. So it's initialize update draw. It
always works that way. Okay.
And then if you have that in your mind, remember when you want to see something
moving, don't write a 4 loop around it or don't write a [inaudible] loop around it. That's
something that's very difficult for me in the beginning. Just let it happen, because you
will. So update things incrementally.
So if we're okay with that, the afternoon session, the past one and a half hours that
seemed like five years, is that I'm trying to explain to you that when you want to write a
single graphics application, draw it out on the paper first. Figure out the dominant object.
Define your coordinate space based on that dominant object. It makes that world a whole
lot easier. Okay.
And then typically because we're not doing very sophisticated graphics programming, we
typically have a central object that's dominating, that's our hero. Interact would allow a
bunch of supporting things.
Implement, define that central object first like we're doing for our ball. And typically it's
not very difficult. So implement that object define that object, and then define just what
we're doing that seems just like the past four years we're doing this thing, did fine the
paddle that to interact with. And then when you have that working, the application
basically works. And that's what we have here. It's limping a long here but it basically
works.
23
The next thing we want to do is in the you will believe me that block is actually there,
that you can interact with the ball. We actually see that it knows how to interact with a
ball. All we need now is to have an array. We need to have another array to put blocks
out here.
And because we did so so carefully, that the blocks, there are 15 positions of this thing.
And then the first position is position 1, 2, 3, 4 -- you know, this is 15 of this same
because we defined these guys so carefully. So we just go through a two-dimensional
array and lay these guys out and we are done.
So [inaudible] showed you the code for that and then we don't have to suffer through this.
And if you will still let me speak, I will tell you a little bit more about how we design
assignments around these things.
So what we have here, I'm compiling this thing and I'm running and then -- oh, sorry. I
started the wrong one. This is the one that we're building. So I'm going to come out a set
of blocks, and we can see that all we need is a set of these guys. And so I'm compiling a
set of blocks. And that's what we have.
So instead of just creating the blocks all the time, I have a random number, say between
zero to eight. If a number is between zero to eight, I will create a block. If the number I
got is bigger than 0.8, I won't create a block.
So, again, a random number between zero to 1. If the number is less than 0.8, I will
create a block 80 percent of the time the blocks are created. That's why we have this. So
every time when I regenerate this, I whether get a different set. And then what I can do
now is I can move my paddle and then the paddle will just interact with each one of the -there's no new in functionality here. All I have is I go through an array of this stuff.
Okay.
So this is the last part. And then this part, what we have, I want to see that this is your
Block Breaker game. So we are almost there. And I don't want to try my luck, give you
the last class that I -- I'll show you the code a little bit, show you indeed it's really, really,
really trivial.
>>: [inaudible] work on a keyboard or the pad?
>> Kelvin Sung: Yeah, yeah. So at this point because this is running from our library, I
can move this thing -- I can -- you know, I can shoot the ball out. And I think G will
recreate it. Because we are updating this thing every -- I can recreate how I want. And
students always ask me this is not fun because you can never lose. And I'll say, yeah, I'm
not writing this for fun, I just want to see if I can do this.
This is the code that I want to show -- we didn't write. This is the code that we didn't
write. And this is the blockable probability where we don't -- we want to create -- it's 70
percent of the time we want to create, and here is the data structure of all the blocks I
have.
And then when I want to initialize the block, the first thing I do is I will delete all the
24
ones before, making sure that I'm not in the draw set anymore, and then I will create a
new one. And to create a new one, like I said, I'm going from zero to 15 in the horizontal
direction. I'm going to zero to 8 in the vertical direction. And then here I'm computing
the coordinate position of my block. It's C times 2 plus 0.5. That tells me where my
blocks are. And this tells me the Y positions of [inaudible] so it's not at the very bottom.
And then after you create them you put into the set, and then when the block -- the block
set knows how to interact with the ball, so break blocks -- the update function, we'll call
this break block, and all we do is we do a linear search through my array colliding with
the ball. If there is a collision, I delete it. And when -- because whenever a block
collided, I can delete it. I don't have to worry about behavior afterwards. So the collision
is much easier. And if there's a collision, I just remove it.
So that's the last part of the code that we didn't type in. I guess if I were a little bit more
coherent, we could do that.
So, anyway, so this is the game that we didn't build. I promise you we will. We didn't.
The thing that after that is that you can start putting in file texture. We know how to put
in file texture. You can start putting audio effect. And then what you do, to compare the
last one we see this with one. This is the actually very, very last one. And then if you
look at this and you look at the one we saw earlier, this looks more fun. And if you put in
sound, then this is actually indeed more fun.
The point I'm trying to make is that the last version, the one we're seeing here and then
the one without a texture and the sound, they're identical. There's no conceptual
difference whatsoever. And then if you give student this assignment, they are much more
motivated. They'll actually spend time working on it.
So I have about half an hour more I guess. Yeah. I have about half an hour more. I will
go through something really quickly to show you how this stuff is made into assignments,
and then maybe we can have some discussion. And I apologize for this. I don't know
what happened in the last hour or so. Maybe it was the food. I think pasta is not good for
my brain. I can usually -- I'm [inaudible].
So, anyway, so here I just want to show you the -- developing a simple game theme
application -- when -- develop a simple game theme application. This is kind of a
summary of what we just went through. And this is where on the second day of the
workshop where we will be organized into groups and we'll write our own games. And
then the goal is to implement a game like the Block Breaker game we have seen and this
is how the task will be separate -- will be divided.
And whenever you develop interactive application the first time, interactive graphics
application the first time, it's important to recognize the logic part from the graphics part.
You want to minimize the logic. The logic is the behavior of objects in your application.
You really want to minimize that and you want to maximize the graphics.
So you want to concentrate on working on the graphics part. Because in game AI or the
behavior of the object, what we have, the behavior of your objects, it's our bouncing ball.
It's really straightforward. And you want to keep that. You don't want to have like object
25
A is moving around and object B knows how to follow object A or object B knows how
to locate object A as object A is moving around.
Those things are really difficult to implement if you have never done it before. If you
look at the map, it's actually not that bad. But if you've never done it before, it can be
very tricky to implement. So if you want to do this in class, do those things last. Do the
things that are easy to implement. Use randomness. And then what you want to do is
you want to choose some kind of a game type.
Now, for example you want to choose -- here we tried to separate out in three categories,
these have graphics pictures, animation with visualization, and more interactive graphics.
Let me show you what I mean. And graphics pictures are things that show -- your game
type will respond to user's command and you will draw something static that's not
interactive.
And then if you want to have something with the animation or visualization, you can
have like a ball that drops and bounces around. And you can visualize random samples.
So these are all graphical visualization of what you will do anyway.
And for interaction, what you did is after initial objects set up, you will have one or
multiple objects interact, and one of those will be under your users' control, your students'
control. And let me show you this.
So, for example, what you can do is you can set things up like card games or you can set
things -- define board games or interactive games. So let me show you this is a snake and
ladder. And so what this, this is a programing assignment on two-distributional array. So
this is two-dimensional array of objects.
And then what you will do is that you will -- what we have done is we've developed this
so that your user -- your students do not need to worry about the graphics. Actually, our
assertion is that you don't even need to worry about the graphics. If you use this
assignment in class, this is an array of objects assignment. All the graphics is provided
for you. And all you need to do is give the assignment. And all student needs to do is be
able to reference to objects, delete objects or create objects based on the offset that's
given to you.
And so I think -- that's moving. And then if I come to a goal, I will take the goal. And so
on. So these type of assignments are for practicing, just like a CS 2 assignment.
And then let me show you a couple more. So here is -- you guys play Othello? So here
you can -- so now you just play [inaudible]. I don't know how to give sound to this game.
So at night it was like 3 o'clock in the morning, I was really tired of looking for sound
effect, so I go [makes noise]. That was me. That was me. That was my blip just because
I was so tired looking for effects. It's just what the hell, I can do this myself. And then
there are others.
And so those are like term based, nothing happened in between. User press a button, you
make something happen and then you stop. And then these type of assignments are
slightly more difficult to implement where -- so this is a hierarchy. This is object
hierarchy where we want to students to see the difference between a rock. So this is a
26
rock. Those are all me. And then this is a -- this is a firework. That was too far. This is
a firework.
So and if you look at the behavior of the rock and the firework, they are the same. So this
assignment is for students, to give students some framework and they have to look at the
behavior of a rock. And it's actually a [inaudible] object and they have to implement rock
and fireworks to -- and that's what this assignment's about.
And, finally, let me just show you this, and maybe we can all go. This is alphabet hero.
This is -- this is binary search tree. Right. So there I have my binary search tree, and
then all the flying guys are insert command. So now I'm going to come in and get a Q
insertion. And he tells me Q is duplicated. Q is duplicated and these guys are search
commands.
So I'll come here and touch V, V found V. Now, if you don't have the binary search tree
behind the game, nothing works. All the graphics and everything is there, just nothing
works. But then you have binary search tree, then it works. And in this case what you
can do is you can I think duplicate the tree is X, so I can clone the tree.
So what the students do is implement a cloning of a binary search tree. If it's not done
correctly, then this will not show up correctly. And finally you can balance a tree. So
here I'm balancing the tree. And students can implement all those.
And if you look at this assignment, when I was a student when this assignment was
given, I have a character screen and if you type in A, they say input a character, you put
C and then say print it out, you print it out, they say C. That was not very satisfactory.
And you can argue this is not very satisfactory either. When student use this type of
assignment, they spend a lot of time making work, and then after it's working they all get
angry because they can not improve it. We have a very tight definition so that students
can't change too much, and that's by purpose.
Because what studies have shown is that when you have this type of assignment in class,
those two dominant students that you have in class that knows the world anyway, they're
going to build a gigantic game and then show it to everyone in class. And the rest of
students in class is going to look at that and go like I should just kill myself.
So what we've done is we provide them with this really tight interface. You can't can do
anything else. Implement this thing. And those good students, they get so angry in the
feedback form, you really affected our score. So when we write papers, we can't lie
about this stuff. So we have to say student satisfactory is not that high.
And our papers don't get accepted anywhere because of it. [inaudible] but then if you
look at the amount of time students spend on an assignment, it's giganteus. They spend
so much time on the assignment and their projects don't have bugs. Because when they
start playing this game, if it crashes, they know, they test it really, really well.
Okay. Whoever will listen, I'm not sure, I think half of audience here really don't care
about what I'm saying. But whoever will listen I'll say it because they won't let us
publish this and we can't show students we're really excited about this thing. So there' a
27
balance somewhere. If you use this stuff [inaudible] to entice student, watch those couple
of alpha students that's going [inaudible] rest of the World. But then the if you watch too
hard, students get angry, and they are really resentful. That's what we learned.
So, in any case, so and we went through this exercise, we want to draw the world. And
then so this is all there anyway. I just go -- I promise you in about five minutes we'll be
all done, and I really apologize. Typically my presentations are of slightly better
technology.
So what we have here is what I showed you is that at the very last I give you a proposal
of what you can do yourself. And then what we have done is we come up with guidelines
to kind of work for you, if you really want to do these things, we give you steps that you
can follow. And that's what these guys are. These are steps that we are recommending
what you can do if you want to do this stuff in your class. And then here are guides to
design your own assignments. And I won't brother with those things.
Are there questions? I feel really bad that the past hour was -- I should stop apologizing.
But John is here. He's not going to fund me for the rest of my life. Yeah. Yeah.
>>: What text would you use if you were going to incorporate this and make your 161 or
162 ->> Kelvin Sung: What would I use?
>>: Yeah, fully game centric. Would you use [inaudible]?
>> Kelvin Sung: This is a preset question. My view is that -- and my view is the right
view, is that -- why is that funny? No -- is that concepts in textbook are independent. All
the textbooks are teaching the same concept. And we're trying to demonstrate that in our
work and we're not completely done yet. When we are done, this will be what we see.
So I'm going to come here and show you -- so here is the release of the work that's online.
And here we describe what we are doing and everything. Let me show you there. Like I
said, we have all these examples, and then here's a basic IO display of screen output
sequence structure and stuff like that [inaudible]. We map all these example to three
textbooks. We're still mapping that out.
This is the first example. It maps to PLD. I'll show you what that is, C# for
programmers, C# for whatever. So there are three textbooks. Same example. So if idea
is that if you use any of this textbook it doesn't matter. And if you use a textbook that's
text based, all the better. So students can see how this is presented normally and they can
see an extra example. So this material works really well if you teach your regular class in
the regular way, and then just give this to student to go play with it.
And then what happened is that in here we have step-by-step guide on how we implement
this stuff anyway. So what your student can do is look at this and go like, oh, this is quite
a bit of reading. And then they can go like, okay, and then we show them where are the
code put, and then we describe what's going on. And then the source code is given. So
they can just compile this in run.
28
And then if you look at the actual code, it's like three lines of code you need to change.
So the idea is I don't think you need to have a textbook for this, but we are fishing for
publishers that we can publish stuff as textbook, and we would like to. But that's way
down the line.
So thank you for the question. Are there any excellent questions like that that I can show
more of the work that we have done?
I really thank for your patience. And are there any other questions?
>> John Nordlinger: I have one.
>> Kelvin Sung: Please.
>> John Nordlinger: Kelvin's being a little bit too modest. When he said papers don't get
accepted, he's actually been accepted [inaudible] conferences. So if you wanted to pull
up his papers [inaudible].
>> Kelvin Sung: Yes. We have our hits and misses. So some of the works are
published. And people's reaction to this is actually quite positive, that wow, this is
interesting. So I should be careful with what I say in terms -- especially in the public. It's
like, oh, everybody hates me. I'm not sure if that's true. They may.
Well, I got to stop anyway. So thank you very much. Thank you for your patience.
Thank you.
[applause]
Download