Part 6
Cursor Control
In which we start to give the user some control over the
application, move the cursor around, and make our first guess
with some coloured balls...
Principles of Movement
How It Works, Part One, Playing in the Sand
Picture a children's play pit full of sand. It is perfectly
smooth. Now, assuming you were invisible how would you make
a small hole appear to run from one side of the pit to the
other?
One way to do it would be this. Use your finger to make a
hole and let everyone see it. Then, as quickly as possible,
fill the hole in and make another one just to the side of
where the first one was. If you do this over and over again,
really quickly, what will someone watching the sand see?
A hole moving across the sand.
And that's exactly how movement and animation work in a computer
program
How It Works, Part Two, Pixelating the Play Pit
So, if we have a blank (white) screen, how do we move a black
spot around the screen? Have a look at this snippet of code...
gUSE id%(9)
foo%=0
DO
gAT 200,foo%
gCOPY id%(1),0,0,20,20,1 : rem clear the 'older' spot
foo%=foo%+5
gAT 200,foo%
gCOPY id%(1),0,0,20,20,0 : rem copy the 'new' spot
UNTIL foo%=200
This code uses the basic building block of the DO... UNTIL...
loop that increases a foo% counter. The first gAT... gCOPY
clears away the old picture we've copied in (the picture being
whatever mbm was gLOADED with id%(1) previously), and the
second gCOPYs the mbm into the new location.
And that, in a nutshell, is how things move!
(I'll leave the relatively trivial exercise of how you'd
adapt this to using a Mask and a Background Image to your
imagination - it's not difficult to work out if you read Tutorial
5 closely).
What sort of things can move?
Have a think through the applications and you'll see movement
in many different places. As with many of the principles you're
seeing in this course, the above can be used in many different
places.
Think of the tile blocks moving in Vexed. Think of the moving
hand choosing cards in Card Deck. Think of the cursor moving
through names and addresses in Contacts. All these use movements
and masks - it's not difficult and it looks good. Which always
key in a good application.
Displaying the Cursor in Master
As you'll remember, we've broken the writing of our application
into small areas to work on. You'll remember that on the game
grid, up and down will move an on-screen cursor in the corresponding
direction, selecting where to place a colour.
So in essence, we're going to write a small routine to move
the cursor!
Where are We Going to Go?
Firstly, we need to know if the up and down cursor keys have
been pressed. As this is reading a keyboard event, we look
in PROC g_kbddrv:(.........). At the end of the procedure,
add in the following code...
ELSEIF Key&=63593 : rem Cursor Up
cursor%=cursor%-1
IF cursor%=0 : cursor%=4 : ENDIF
m_show_cursor:
ELSEIF Key&=63594 : rem Cursor Down
cursor%=cursor%+1
IF cursor%=5 : cursor%=1 : ENDIF
m_show_cursor:
Okay, so we've introduced a new variable here. cursor% (which
we set in PROC init_game: to be equal to 1) keeps track of
which row the cursor is currently in (the top row is 1, the
bottom row is 4). When we move the cursor up or down, we change
the value of cursor% to represent the new row, and then call
the procedure that will display the cursor.
The IF... ENDIF statement in the middle checks to see if
we have moved down while on the bottom row, or moved up when
on the top row. If we have, the value of cursor% is set to
the opposite end, so the cursor effectively wraps round the
rows.
Showing The Cursor
Once we move the cursor, we call this procedure...
PROC m_showcursor:
gUSE id%(1) : rem Make sure we are using the main window
rem *** clear the old cursor away by blanking the square, and
rem *** copying the ball back into the square.
m_showball:(turn%,old_cursor%,0)
m_showball:(turn%,old_cursor%,guess%(old_cursor%))
rem *** Now copy the cursor mask, and the cursor itself.
gAT (turn%*36)+5,((cursor%-1)*36)+5
gCOPY id%(11),36,0,36,36,1 : rem *** Copy the Mask, clearing pixels
gCOPY id%(11),72,0,36,36,0 : rem *** Copy the cursor into the pixels
old_cursor%=cursor%
ENDP
Time to Test!
If you were writing Master yourself, then now is a good time
to translate and see if the cursor moves up and down. If you're
keeping up with Master, have a look at the code at the end
of the tutorial and you'll see where the above fits in.
The tutorials cannot explain everything, but I'm aiming to
cover the broad principles here, and then hope you look at
the downloadable source code at the end of the tutorials to
see how it all fits together.
What we are doing in Master is creating a 'toolbox' of techniques
that you'll hopefully be able to apply to your own programs.
Making a Guess
For each turn, we are going to hold the temporary guess an
array called guess%(4). Once we've guess the four balls, we'll
hit enter and see how good our guess is. At the start of the
turn, we'll set the four array elements to zero. This is so
we can check that the player actually puts 4 colours into
the guess (i.e. all four values are non zero).
Left and Right, Red or White?
We've already got our cursor moving up and down, so now we
add in the left and right cursors into the PROC g_kbddrv:...
ELSEIF Key&=63591 : rem Cursor Left
guess%(cursor%)=guess%(cursor%)-1
IF guess%(cursor%)<1 : guess%(cursor%)=(skill_level%*2)+2 : ENDIF
m_showball:(turn%,cursor%,guess%(cursor%))
ELSEIF Key&=63594 : rem Cursor Down
guess%(cursor%)=guess%(cursor%)+1
IF guess%(cursor%)>(skill_level%*2)+2 : guess%(cursor%)=1 : ENDIF
m_showball:(turn%,cursor%,guess%(cursor%))
This is going to look pretty familiar to the movement code.
You'll see you increase or decrease the value of the guess%()
depending on the current cursor% value (1 through 4). Where
the value of guess% is more than the number of balls to choose
from, it loops back to one, and if it drops below one, then
it loops to the highest value.
Remember those Skill Levels
Yes, this highest value is determined by the skill level.
The easy skill level (skill%=1) gives you 4 balls to choose
from. Medium skill% (2) gives 6 balls, and Hard skill% (3)
gives 8 balls.
In the same way we called the show cursor routine, we do
the same here with the show ball routine, which we detailed
off in the last tutorial. See, it's all falling into place
now.
Conclusions
So, here's the OPL code
as it stands just now. Copy this onto your Communicator (or
into the emulator) and see how exactly we're doing everything.
MASTER is starting to look more and more like the finished
product, isn't it? When you get to this part of your own future
projects, you'll get a lovely thrill, because it's all working,
and on the screen. If you've followed the course up to here,
well done.
We're not stopping though. The next part is going to show
us how to interpret the guess we've made, and then let the
user have another guess.. and another... and another...
Source
Code
You can download the OPL source code for Master as it is at
the end of tutorial 5 here.
You can download the opo program (the runtime file) as it is
at the end of tutorial 6 here.
Got any questions or comments arising from this tutorial.
Need help with OPL. Head to the forums
for help from the friendly community.
|