Aha! It started a level after a couple of key presses. OK, I have a square with a little red dot. When I type on the numeric keypad (the 1 2 3 and 4 5 6 and 7 8 9 thing), the square moves around. Plus, the little red dot seems to point wherever I'm moving (although it seems to start off in a wierd spot.. why is that?).
Hey! I can probably keep running the program as I build my solution as long as I'm careful to do it piece by piece! That should make debugging way easier!
main
. Why? Because that's where the computer will start
looking when it executes my program. So, I'll open up hw4.c.
main
. I'll look over the rest of
the code up there later. For now, I just want to get an overall
sense for the program. Read main
's comment. (Boy, who wrote this code?
These comments are great!)
quit
becomes true. Well,
let's start by figuring out when quit
might become
true. It must be assigned somewhere (or a pointer to it is passed to
some function!).
switch
. If the event is a
keyboard event (GP142_KBD
), and the key pressed was a 'q'
, then
quit
becomes true. Let's see... then, we hit the
break
. So, we exit the switch
.. and, that's the end of the loop! That
means we quit the loop and drop right back out to the GP142_close
call
and the end of main
!
'q'
straight off. Does
it quit? If so, we've understood the start of the code!
main
. For now, though, we'll just
assume any function that's called does about what we expect it to do
if we can.
main
, again. It opens GP142, turns off logging (whatever
that is! better look at the GP142 documentation later), starts
animation, and "seeds the random number generator". All that
is straight from the names of the functions and the
comments. Hmmm.. seeding the random number generator is that thing
where you get random numbers kicked off, right? We learned about that
a bit in HW#2.
'q'
, of course!). So, if I
hit '9'
it sends my player up and to the right. If I hit '0'
, it's
supposed to fire. I'll look at how that works later. Maybe part
of that is what we're supposed to make work!
GP142_KBD
case. Let's look at this
GP142_PERIODIC
thing. According to the comment, these just
come up a few times a second no matter what the user does.. even if
she's just sitting there not touching any keys, I suppose!
gameStatus
and GAME_PLAYING
to find out!
gameStatus
isn't very useful. It's just an
int
. And, GAME_PLAYING
doesn't seem to be in this file. Where could it
be? Well, it must be #included into this file or it wouldn't work!
#include "tron.h"
it says that tron.h
"defines symbolic constants". Let's open up that file and
see if GAME_PLAYING
is there!
GAME_PLAYING
in tron.h
! And, it's under a comment labeled
"Game Status". So, what about the other statuses? Actually,
looking at them, they make sense. Although, I'm glad I can use the
symbolic constants and not deal with the numbers directly: those
numbers make no sense. Back to main
!
drawScreen
's comment says it "Draw[s] the entire
screen." updateScreen
says it "Perform[s] one frame of
animation by updating the positions of everything." Ah! It
doesn't actually draw anything, it says! It just
moves stuff around. That makes sense: updateScreen
moves things around
while drawScreen
doesn't worry about that; it just draws everything
wherever it actually is right now. Updating is like moving the clay in a claymation
move. Drawing is like taking a picture to get one frame of the movie!
That make sense.. let's head back to main
.
updateScreen
isn't called if we're not playing the
game. Why move stuff around when you're not actually playing?
I'm going to try filling in the very
first TODO I found: startLevel
.
According to the directions:
At the start of each level, [I should] clear the screen, place the hero in the middle of the screen, and randomly place 1 enemy on the screen.
From my call graph I know that's called from three different
places! handleInput
calls it (looks like when the level ends),
startGame
calls it, and updateScreen
calls it (when the player is hit
by an enemy? I'm not sure I get that.. later!). Anyway, the good news
is as long as I do what the function descriptions says I need to do, I
shouldn't have to worry about where it's called from or how it's used!
It'll just work because it keeps its contract. I love
functional decomposition!
OK, I've read the function comment, and it makes sense. (Although.. why does it single out the level number as important?) The TODO comment in the function repeats everything the instructions said to do and also says to "set the bullet's status appropriately". I'll ignore that for now, but I'll make sure not to delete that part of the TODO so that I know I haven't done it! OK, here goes nothing!
startLevel
can only change the things that get passed to it as pointer
parameters. So, I know I'm not going to change level
. However,
everything else is up for grabs!
playerX
and playerY
variables. Perhaps I should set those both to 0
? What
would put things in the middle of the screen. Aargh! I can't find if
(0, 0) is the middle of the screen in the code!! Well.. maybe if I
look at how the player is drawn? I bet that function is called
drawPlayer
(according to the naming conventions). I'll
look around for it.
tronDraw.c
. It just calls some GP142 functions with the x and y
locations it's given. I guess that means that GP142 decides where the
center of the screen is! Off I go to the GP142 documentation!
playerX
and playerY
to 0
inside startLevel
and see what happens.
playerX
and playerY
are pointers to int
s. So, I
don't set them to 0
, I set *playerX
and *playerY
to 0
. I wonder why
the compiler doesn't warn me that I'm doing something wrong
when I do that?!
#define PLAYER_START_FACING (-LEFT)Hmm... what is
LEFT
and why is it negative?
LEFT
back in tron.h
again. There's a great comment that explains
why the negative sign is there, too. But, if all that is right, isn't
the PLAYER_START_FACING
already set up to work? I'll run it again and
check.
PLAYER_START_FACING
doesn't do anything! I need
to tell the computer to use my starting facing, and that must
be supposed to happen in startLevel
!
startLevel
function. I'm going to go ahead and set the
playerFacing
to PLAYER_START_FACING
. But, this time I'll remember the
*
! Let's run it again and see if it worked.
startLevel
. I'll call that to create my enemy. Then, I'll
rerun it to see what happens.
That is so cool! The game actually works now (sort of). And, I've
taken care of everything in startLevel
's TODO list except setting the
bullet status. I bet I can take that to.
Warning: descending into madness. Hey, I can finish this. I can do it right now! I'll do Part B today, too. And, I think I'll go ahead and ace the midterm but take only ten minutes of the period on it as well. Plus, I think I will polish Steve's bike!
P.P.S. If you're curious about the answers to any of the questions in this walkthrough, maybe you should post to the newsgroup about them. Remember to know what's cheating and what isn't first, though! No assignment code on the newsgroup!