783 lines
24 KiB
Plaintext
783 lines
24 KiB
Plaintext
ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ·
|
|
º Week 1, Day 1 º
|
|
ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄĽ
|
|
|
|
Today you will learn how to make a PACMAN symbol move across the screen.
|
|
|
|
Start QBasic and type in the following program:
|
|
|
|
CLS
|
|
PRINT "Below is PACMAN himself!"
|
|
PRINT "C"
|
|
|
|
Now RUN the program by pressing ALT-R and then S.
|
|
Is the graphics a little unconvincing? Well, we have to start somewhere!
|
|
|
|
The command CLS clears the screen and we'll use it often.
|
|
|
|
Lets put PACMAN in the middle of the screen.
|
|
The command you need is LOCATE.
|
|
Type (or edit) and RUN the following:
|
|
|
|
CLS
|
|
LOCATE 12,40
|
|
PRINT "C"
|
|
|
|
Easy as pie!
|
|
The first value between the brackets indicates the row, ranging from 1 at the
|
|
top to 23 at the bottom on the screen.
|
|
The second value is the column and ranges from 1 at the left to 80 at the right
|
|
on the screen.
|
|
|
|
Now to make PACMAN move!
|
|
You could do it this way:
|
|
|
|
LOCATE 12,1
|
|
PRINT "C"
|
|
LOCATE 12,1
|
|
PRINT " " :REM delete the old picture
|
|
LOCATE 12,2
|
|
PRINT "C" :REM draw a new picture to the right
|
|
|
|
(REM statements are ignored by the computer and you dont have to type )
|
|
(them in. )
|
|
(I will use REM statements to clarify and comment upon my programming.)
|
|
|
|
This method will take forever to program so lets start using variables.
|
|
|
|
A variable is described has a name and contains a value.
|
|
This illustrates the difference between a numeric- and a string variable:
|
|
|
|
contents ÄÄÄ-> ³ 10 ³ ³ "twenty" ³
|
|
ÀÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÙ
|
|
name ÄÄÄ-> apples pears$
|
|
(numeric) (string)
|
|
|
|
The "$" in "pears$" is pronounced "string" and identifies it as a string
|
|
variable.
|
|
When you PRINT a variable its contents is shown, not its name.
|
|
Type (or edit) and RUN:
|
|
|
|
CLS
|
|
apples = 10
|
|
pears$ = "twenty"
|
|
PRINT "Amount of apples are "; apples
|
|
PRINT "Amount of pears are "; pears$
|
|
|
|
Notice how the text between the double quotes is displayed literally while
|
|
the variable name is replaced by its contents.
|
|
The "=" operator assigns a value to a variable and does it by working from
|
|
right to left, e.g. in "apples = 10" the "10" goes into "apples".
|
|
The ";" causes the computer to remember where it last PRINTed and the following
|
|
PRINT will continue at that position.
|
|
PRINT "ABC" will give the same output as PRINT "A"; "B"; "C"
|
|
|
|
While PACMAN is warming up for his jog, lets make things even easier on
|
|
ourselves.
|
|
You might have figured that I want to use variables in the following way:
|
|
|
|
column = 1
|
|
LOCATE 12,column :REM This translates to LOCATE 12,1
|
|
PRINT "C"
|
|
column = column + 1 :REM Lets calculate the value:
|
|
:REM column + 1 gives you 1 + 1, in other words 2
|
|
LOCATE 12,column :REM This translates to LOCATE 12,2
|
|
PRINT "C"
|
|
|
|
Still lots of repetition!
|
|
An easier way is to make the computer go in a "loop", increasing the value of
|
|
"column" and printing PACMAN.
|
|
Type (or edit) and RUN:
|
|
|
|
CLS
|
|
FOR column = 1 TO 80
|
|
LOCATE 12,column
|
|
PRINT "C"
|
|
NEXT column
|
|
|
|
Hope I haven't put you off programming altogether with that one!
|
|
You've implemented as so-called "FOR..NEXT loop" and here's the low-down on it:
|
|
The "FOR" line tells the computer that a variable called column will start off
|
|
at 1 and then increase in value until it reaches 80.
|
|
The "NEXT" line increases column's value with one and makes the program jump
|
|
back to the "LOCATE" line.
|
|
Everything between the "FOR" and the "NEXT" is thus the actual loop and gets
|
|
repeated 80 times.
|
|
|
|
If you still dont understand the concept of the "FOR..NEXT loop" then type and
|
|
RUN:
|
|
|
|
CLS
|
|
FOR values = 1 TO 10
|
|
PRINT values
|
|
NEXT values
|
|
|
|
Hope you've found the experience enlightening!
|
|
|
|
Clearly also is that everything is happening too fast.
|
|
PACMAN completes his trip in the blink of an eye or, depending on how fast
|
|
your computer is, even less!
|
|
The solution is to use the SLEEP command which waits a number of seconds.
|
|
Type (or edit) and RUN:
|
|
|
|
CLS
|
|
FOR column = 1 TO 80
|
|
LOCATE 12,column
|
|
PRINT "C"
|
|
SLEEP 1
|
|
NEXT column
|
|
|
|
Too slow now!
|
|
Another way is to use an empty FOR..NEXT loop that does nothing but kill time.
|
|
That way you can change the value of the loop untill it provides an acceptable
|
|
delay for your computer.
|
|
|
|
Another problem was that the PACMAN isn't deleted in its old position and you
|
|
are left with a whole row of "CCCCCC"s. We'll solve that now.
|
|
Here's the final code for the PACMAN 100m sprint:
|
|
Type (or edit) and RUN!
|
|
|
|
CLS
|
|
FOR column = 1 TO 79
|
|
LOCATE 12,column
|
|
PRINT " C"
|
|
FOR nothing = 1 TO 100 :REM <ÄÂÄ This just delays the computer
|
|
NEXT nothing :REM ÄÙ
|
|
NEXT column
|
|
|
|
If you didnt see a thing the program is probably still too fast for your
|
|
computer, so try changing the limit of the "nothing" loop to 300 or more.
|
|
|
|
The space before PACMAN cleverly deletes its old position.
|
|
How? Two characters are displayed (a " " and a "C") but the position only
|
|
shift one to the right.
|
|
When the two characters are displayed at their new position, the " " overlaps
|
|
with the "C" previously displayed and effectively deletes it.
|
|
That's all for today!
|
|
|
|
-------------------------------------------------------------------------------
|
|
ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ·
|
|
º Week 1, Day 2 º
|
|
ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄĽ
|
|
|
|
Watching PACMAN move is fun, but being in control opens up endless
|
|
possibilities..
|
|
Enough said!
|
|
Remember the FOR..NEXT loop?
|
|
Lets have a look at a different kind of loop.
|
|
Type (or edit) and RUN:
|
|
|
|
CLS
|
|
value = 1
|
|
DO WHILE value < 11
|
|
PRINT value :REM <ÄÂÄ This is the loop
|
|
value = value + 1 :REM ÄÙ
|
|
LOOP
|
|
|
|
This displayed numbers 1 through 10.
|
|
The program loops while "value" is less than 11.
|
|
We will now use the DO..WHILE loop to read the keyboard and display the
|
|
characters that you press.
|
|
However, there's one snag. The program will loop "forever" unless you stop it!
|
|
Pressing CTL and BREAK at the same time will do this.
|
|
Type (or edit) and RUN:
|
|
|
|
CLS
|
|
DO :REM there's no WHILE, so DO forever..
|
|
keyed$ = INKEY$ :REM make keyed$ = the key pressed
|
|
IF keyed$ <> "" THEN PRINT keyed$ :REM if keyed$ isnt empty then display it
|
|
LOOP
|
|
|
|
I bet INKEY$ has you confused!
|
|
INKEY$ is a special string variable.
|
|
The computer always sets the value of INKEY$ to the key that you press.
|
|
While you're not pressing any keys it will contain nothing (nothing is "").
|
|
The IF command is very straight forward.
|
|
IF something is true THEN do something.. got it?
|
|
So IF keyed$ is not equal to nothing THEN its value gets PRINTed.
|
|
If I didnt include the IF clause then keyed$ would always be PRINTed, whether
|
|
it contained a value or not.
|
|
Try leaving out the IF..THEN part and you'll see what I mean!
|
|
Lots and lots of "nothings" fill the screen!
|
|
|
|
Armed with our new commands we can finally control PACMAN with the keyboard.
|
|
Type (or edit) and RUN:
|
|
|
|
CLS
|
|
row = 12
|
|
column = 40
|
|
DO
|
|
DO :REM <Ä¿ this loop waits for a key to be pressed
|
|
keyed$ = INKEY$ :REM ³
|
|
LOOP UNTIL keyed$ <> "" :REM ÄÙ
|
|
LOCATE row, column
|
|
PRINT " " :REM this erases the "C"
|
|
IF keyed$ = "q" THEN row = row - 1
|
|
IF keyed$ = "a" THEN row = row + 1
|
|
IF keyed$ = "o" THEN column = column - 1
|
|
IF keyed$ = "p" THEN column = column + 1
|
|
LOCATE row, column
|
|
PRINT "C" :REM shows the "C" at the new position
|
|
LOOP
|
|
|
|
Note that you can use your own choice of keys by replacing "q","a","o" and "p".
|
|
Using special keys like the cursor keys is another cup of tea.
|
|
|
|
If you move PACMAN outside the screen boundaries you'll get an error message.
|
|
To prevent this you must add checks to the program.
|
|
Just replace the IFs with the following lines and RUN:
|
|
|
|
IF (keyed$ = "q") AND (row > 1) THEN row = row - 1
|
|
IF (keyed$ = "a") AND (row < 23) THEN row = row + 1
|
|
IF (keyed$ = "o") AND (column > 1) THEN column = column - 1
|
|
IF (keyed$ = "p") AND (column < 80) THEN column = column + 1
|
|
|
|
This should do for today.
|
|
Hope you enjoyed this as much as I did!
|
|
|
|
-------------------------------------------------------------------------------
|
|
ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ·
|
|
º Week 1, Day 3 º
|
|
ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄĽ
|
|
|
|
A playing area is essential to any game so lets design a maze for our PACMAN.
|
|
|
|
First I'll have to tell you about arrays.
|
|
Take a look at this example:
|
|
|
|
DIM values(3)
|
|
values(1) = 5
|
|
values(2) = 92
|
|
values(3) = 45
|
|
|
|
Arrays are variables containing multiple elements.
|
|
Each element is named after the array followed by a number to specify the
|
|
position of the element.
|
|
Each element has its own value.
|
|
Type (or edit) and RUN the following to see how arrays can save you from a lot
|
|
of repetitive programming:
|
|
|
|
CLS
|
|
DIM values(10)
|
|
FOR count = 1 TO 10
|
|
values(count) = count
|
|
NEXT count
|
|
FOR count = 1 to 10
|
|
PRINT values(count)
|
|
NEXT count
|
|
|
|
Remember that "count" ranges from 1 to 10 so the line "values(count) = count"
|
|
translates to "values(1) = 1, values(2) = 2, values(3) = 3" etc.
|
|
|
|
Now lets define our maze. Type (or edit) and RUN:
|
|
|
|
CLS
|
|
DIM maze$(6)
|
|
maze$(1) = "#########"
|
|
maze$(2) = "# # #"
|
|
maze$(3) = "# # # # #"
|
|
maze$(4) = "# # # #"
|
|
maze$(5) = "# # #"
|
|
maze$(6) = "#########"
|
|
FOR count = 1 to 6
|
|
PRINT maze$(count)
|
|
NEXT count
|
|
|
|
Now lets put PACMAN in the maze.
|
|
Wait - there's nothing that will keep him from moving over the walls.
|
|
To solve that problem I'll show you how to inspect the maze (the contents of
|
|
maze$).
|
|
|
|
The command MID$ allows you to look at parts of a string variable.
|
|
It has the following format: MID$(name of string, starting position, number of
|
|
letters).
|
|
Lets look at an example:
|
|
alphabet$ = "ABCDE"
|
|
PRINT MID$(alphabet$, 1, 2) :REM displays "AB"
|
|
PRINT MID$(alphabet$, 3, 1) :REM displays "C"
|
|
|
|
Every time PACMAN moves we'll use his position (row and column) to see if he
|
|
overlaps a wall in the maze.
|
|
Type (or edit) and RUN: (you'll have to press CTRL-BREAK to stop the program)
|
|
|
|
CLS
|
|
DIM maze$(6)
|
|
maze$(1) = "#########"
|
|
maze$(2) = "# # #"
|
|
maze$(3) = "# # # # #"
|
|
maze$(4) = "# # # #"
|
|
maze$(5) = "# # #"
|
|
maze$(6) = "#########"
|
|
row = 5
|
|
column = 3
|
|
DO
|
|
LOCATE 1, 1
|
|
FOR count = 1 to 6
|
|
PRINT maze$(count) :REM PRINT the maze
|
|
NEXT count
|
|
LOCATE row, column
|
|
PRINT "C" :REM PRINT PACMAN
|
|
DO
|
|
keyed$ = INKEY$
|
|
LOOP UNTIL keyed$ <> ""
|
|
oldRow = row :REM remember old position of PACMAN
|
|
oldColumn = column
|
|
IF keyed$ = "q" THEN row = row - 1
|
|
IF keyed$ = "a" THEN row = row + 1
|
|
IF keyed$ = "o" THEN column = column - 1
|
|
IF keyed$ = "p" THEN column = column + 1
|
|
IF MID$(maze$(row), column, 1) = "#" THEN
|
|
row = oldRow :REM <ÄÂ move PACMAN back to his
|
|
column = oldColumn :REM ÄÙ old position
|
|
END IF
|
|
LOOP
|
|
|
|
All that needs mentioning is that I used the "IF..END IF" structure to allow
|
|
for more than one action.
|
|
|
|
If you type in the examples you can save yourself some time by saving the
|
|
PACMAN game to disk (press ALT-F then S), because we will re-use the game
|
|
during the rest of the week.
|
|
|
|
Tomorrow we'll add dots and a ghost to the maze!
|
|
|
|
-------------------------------------------------------------------------------
|
|
ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ·
|
|
º Week 1, Day 4 º
|
|
ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄĽ
|
|
|
|
Add the dots to the maze by changing the following lines:
|
|
|
|
maze$(1) = "#########"
|
|
maze$(2) = "#...#...#"
|
|
maze$(3) = "#.#.#.#.#"
|
|
maze$(4) = "#.#...#.#"
|
|
maze$(5) = "#...#...#"
|
|
maze$(6) = "#########"
|
|
|
|
As you might have guessed we'll inspect the maze each time PACMAN moves and
|
|
keep count of the number of dots he eat.
|
|
A dot has to be removed when eaten.
|
|
When our count reaches 21 (count them!) dots, the game ends.
|
|
|
|
MID$ can be used to change a string variable as well as inspecting it.
|
|
Look at the following example:
|
|
|
|
alphabet$="ABCDE"
|
|
MID$(alphabet$, 2, 3) = "XYZ"
|
|
PRINT alphabet$ :REM displays "AXYZE"
|
|
|
|
We'll use MID$ to replace the dots with blanks when PACMAN eats them.
|
|
Type (or edit) and RUN: (changes in the program are marked)
|
|
|
|
CLS
|
|
DIM maze$(6)
|
|
maze$(1) = "#########"
|
|
maze$(2) = "#...#...#"
|
|
maze$(3) = "#.#.#.#.#"
|
|
maze$(4) = "#.#...#.#"
|
|
maze$(5) = "#...#...#"
|
|
maze$(6) = "#########"
|
|
row = 5
|
|
column = 3
|
|
dots = 21 :REM <ÄÄ- new
|
|
DO
|
|
LOCATE 1, 1
|
|
FOR count = 1 to 6
|
|
PRINT maze$(count)
|
|
NEXT count
|
|
LOCATE row, column
|
|
PRINT "C"
|
|
:REM <ÄÂÄ new
|
|
IF dots = 0 THEN
|
|
LOCATE 8, 1 :REM ³
|
|
PRINT "You have won!" :REM ³
|
|
END :REM ³
|
|
END IF :REM ÄÙ
|
|
DO
|
|
keyed$ = INKEY$
|
|
LOOP UNTIL keyed$ <> ""
|
|
oldRow = row
|
|
oldColumn = column
|
|
IF keyed$ = "q" THEN row = row - 1
|
|
IF keyed$ = "a" THEN row = row + 1
|
|
IF keyed$ = "o" THEN column = column - 1
|
|
IF keyed$ = "p" THEN column = column + 1
|
|
IF MID$(maze$(row), column, 1) = "#" THEN
|
|
row = oldRow
|
|
column = oldColumn
|
|
END IF
|
|
:REM <ÄÂÄ new
|
|
IF MID$(maze$(row), column, 1) = "." THEN
|
|
MID$(maze$(row), column, 1) = " " :REM ³
|
|
dots = dots - 1 :REM ³
|
|
END IF :REM ÄÙ
|
|
LOOP
|
|
|
|
(QBasic does not allow me to place a ":REM" next to a IF..THEN line. )
|
|
(So if you suspect a REM is missing, see if its next tot an IF..THEN.)
|
|
|
|
The reason why we dont do the "IF dots = 0" test directly after inspecting the
|
|
maze is because we want to draw PACMAN in his new position before ending the
|
|
game.
|
|
|
|
Here is a better (or clearer) way of inspecting keyed$ and maze$:
|
|
|
|
REM examine the keys
|
|
SELECT CASE keyed$
|
|
CASE IS = "q"
|
|
row = row - 1
|
|
CASE IS = "a"
|
|
row = row + 1
|
|
CASE IS = "o"
|
|
column = column - 1
|
|
CASE IS = "p"
|
|
column = column + 1
|
|
END SELECT
|
|
|
|
REM examine the maze
|
|
SELECT CASE MID$(maze$(row), column, 1)
|
|
CASE IS = "#"
|
|
row = oldRow
|
|
column = oldColumn
|
|
CASE IS = "."
|
|
MID$(maze$(row), column, 1) = " "
|
|
dots = dots - 1
|
|
END SELECT
|
|
|
|
SELECT makes it a lot easier to read the program.
|
|
Also notice the way I put spaces before (indent) some words.
|
|
Another good idea is to use blank lines to seperate the various parts of your
|
|
program.
|
|
|
|
Lets place a ghost in the maze.
|
|
We'll just display the ghost for now and detect whether PACMAN collides with
|
|
it. Tomorrow we can make it move.
|
|
|
|
Detecting whether there's a collision is a simple matter of comparing PACMAN's
|
|
and the ghost's positions (row and column).
|
|
Type (or edit) and RUN:
|
|
|
|
CLS
|
|
|
|
DIM maze$(6)
|
|
maze$(1) = "#########"
|
|
maze$(2) = "#...#...#"
|
|
maze$(3) = "#.#.#.#.#"
|
|
maze$(4) = "#.#...#.#"
|
|
maze$(5) = "#...#...#"
|
|
maze$(6) = "#########"
|
|
|
|
row = 5
|
|
column = 3
|
|
ghostRow = 2 :REM <ÄÂÄ new
|
|
ghostColumn = 7 :REM ÄÙ
|
|
dots = 21
|
|
|
|
DO
|
|
|
|
LOCATE 1, 1
|
|
FOR count = 1 to 6
|
|
PRINT maze$(count)
|
|
NEXT count
|
|
|
|
LOCATE row, column
|
|
PRINT "C"
|
|
|
|
LOCATE ghostRow, ghostColumn :REM <ÄÂÄ new
|
|
PRINT "G" :REM ÄÙ
|
|
|
|
IF dots = 0 THEN
|
|
LOCATE 8, 1
|
|
PRINT "You have won!"
|
|
END
|
|
END IF
|
|
:REM <ÄÂÄ new
|
|
IF ((row = ghostRow) AND (column = ghostColumn)) THEN
|
|
LOCATE 8, 1 :REM ³
|
|
PRINT "You've been caught!" :REM ³
|
|
END :REM ³
|
|
END IF :REM ÄÙ
|
|
|
|
DO
|
|
keyed$ = INKEY$
|
|
LOOP UNTIL keyed$ <> ""
|
|
|
|
oldRow = row
|
|
oldColumn = column
|
|
|
|
REM examine the keys
|
|
SELECT CASE keyed$
|
|
CASE IS = "q"
|
|
row = row - 1
|
|
CASE IS = "a"
|
|
row = row + 1
|
|
CASE IS = "o"
|
|
column = column - 1
|
|
CASE IS = "p"
|
|
column = column + 1
|
|
END SELECT
|
|
|
|
REM examine the maze
|
|
SELECT CASE MID$(maze$(row), column, 1)
|
|
CASE IS = "#"
|
|
row = oldRow
|
|
column = oldColumn
|
|
CASE IS = "."
|
|
MID$(maze$(row), column, 1) = " "
|
|
dots = dots - 1
|
|
END SELECT
|
|
|
|
LOOP
|
|
|
|
Phew! I need a rest after that!
|
|
Remember to save the program for tomorrow.
|
|
|
|
-------------------------------------------------------------------------------
|
|
ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ·
|
|
º Week 1, Day 5 º
|
|
ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄĽ
|
|
|
|
Lets give the ghost some "artificial intelligence".
|
|
|
|
As you might have suspected we will compare his positions with PACMAN's and
|
|
move him one position nearer.
|
|
Allowing the ghost to move diagonally will give it an unfair advantage so
|
|
ghostRow and ghostColumn will not change at the same time.
|
|
Of course the ghost will also have to be blocked by the walls of the maze.
|
|
We dont have to check for dots because the ghost dont eat them.
|
|
|
|
So what are we waiting for? Type (or edit) and RUN!
|
|
|
|
CLS
|
|
|
|
DIM maze$(6)
|
|
maze$(1) = "#########"
|
|
maze$(2) = "#...#...#"
|
|
maze$(3) = "#.#.#.#.#"
|
|
maze$(4) = "#.#...#.#"
|
|
maze$(5) = "#...#...#"
|
|
maze$(6) = "#########"
|
|
|
|
row = 5
|
|
column = 3
|
|
ghostRow = 2
|
|
ghostColumn = 7
|
|
dots = 21
|
|
|
|
DO
|
|
|
|
LOCATE 1, 1
|
|
FOR count = 1 to 6
|
|
PRINT maze$(count)
|
|
NEXT count
|
|
|
|
LOCATE row, column
|
|
PRINT "C"
|
|
|
|
LOCATE ghostRow, ghostColumn
|
|
PRINT "G"
|
|
|
|
IF dots = 0 THEN
|
|
LOCATE 8, 1
|
|
PRINT "You have won!"
|
|
END
|
|
END IF
|
|
|
|
IF ((row = ghostRow) AND (column = ghostColumn)) THEN
|
|
LOCATE 8, 1
|
|
PRINT "You've been caught!"
|
|
END
|
|
END IF
|
|
|
|
DO
|
|
keyed$ = INKEY$
|
|
LOOP UNTIL keyed$ <> ""
|
|
|
|
oldRow = row
|
|
oldColumn = column
|
|
|
|
REM examine the keys
|
|
SELECT CASE keyed$
|
|
CASE IS = "q"
|
|
row = row - 1
|
|
CASE IS = "a"
|
|
row = row + 1
|
|
CASE IS = "o"
|
|
column = column - 1
|
|
CASE IS = "p"
|
|
column = column + 1
|
|
END SELECT
|
|
|
|
REM examine the maze
|
|
SELECT CASE MID$(maze$(row), column, 1)
|
|
CASE IS = "#"
|
|
row = oldRow
|
|
column = oldColumn
|
|
CASE IS = "."
|
|
MID$(maze$(row), column, 1) = " "
|
|
dots = dots - 1
|
|
END SELECT
|
|
|
|
REM move ghost closer to PACMAN :REM <Ä¿ everything from this point
|
|
:REM ³ onwards is new
|
|
oldRow = ghostRow
|
|
SELECT CASE ghostRow
|
|
CASE < row
|
|
ghostRow = ghostRow + 1
|
|
CASE > row
|
|
ghostRow = ghostRow - 1
|
|
END SELECT
|
|
IF MID$(maze$(ghostRow), ghostColumn, 1) = "#" THEN ghostRow = oldRow
|
|
|
|
IF ghostRow = oldRow THEN
|
|
oldColumn = ghostColumn
|
|
SELECT CASE ghostColumn
|
|
CASE < column
|
|
ghostColumn = ghostColumn + 1
|
|
CASE > column
|
|
ghostColumn = ghostColumn - 1
|
|
END SELECT
|
|
IF MID$(maze$(ghostRow), ghostColumn, 1) = "#" THEN ghostColumn = oldColumn
|
|
END IF
|
|
LOOP
|
|
|
|
Notice that I test whether ghostRow has stayed the same ( = oldRow) before
|
|
testing for ghostColumn.
|
|
This prevents diagonal movement for the ghost.
|
|
Another problem is that the ghost waits for you to make a move before moving
|
|
himself.
|
|
The loop that waits for a key to be pressed is the culprit.
|
|
Now we will have to put a delay somewhere in the program because the ghost will
|
|
move at blinding speed!
|
|
Replace the following lines in the program and RUN it:
|
|
|
|
DO
|
|
keyed$ = INKEY$
|
|
LOOP UNTIL keyed$ <> ""
|
|
|
|
with:
|
|
|
|
keyed$ = INKEY$
|
|
REM: kill time
|
|
FOR nothing = 1 TO 500
|
|
NEXT nothing
|
|
|
|
If the game is still too fast then change the limit of "nothing" to 1000 or
|
|
more.
|
|
|
|
The game is still too difficult because the ghost is too intelligent - it
|
|
follows you at every possible opportunity.
|
|
To add some randomness to its pattern we will use the command RND.
|
|
The value of RND is never the same (for all practical purposes) but is always
|
|
a value between 0 and 1.
|
|
The condition "IF RND < 0.1 " is true roughly 10% of the time.
|
|
Here is the entire listing with the changes added: (Type (or edit) and RUN)
|
|
|
|
CLS
|
|
|
|
DIM maze$(6)
|
|
maze$(1) = "#########"
|
|
maze$(2) = "#...#...#"
|
|
maze$(3) = "#.#.#.#.#"
|
|
maze$(4) = "#.#...#.#"
|
|
maze$(5) = "#...#...#"
|
|
maze$(6) = "#########"
|
|
|
|
row = 5
|
|
column = 3
|
|
ghostRow = 2
|
|
ghostColumn = 7
|
|
dots = 21
|
|
|
|
DO
|
|
|
|
LOCATE 1, 1
|
|
FOR count = 1 to 6
|
|
PRINT maze$(count)
|
|
NEXT count
|
|
|
|
LOCATE row, column
|
|
PRINT "C"
|
|
|
|
LOCATE ghostRow, ghostColumn
|
|
PRINT "G"
|
|
|
|
IF dots = 0 THEN
|
|
LOCATE 8, 1
|
|
PRINT "You have won!"
|
|
END
|
|
END IF
|
|
|
|
IF ((row = ghostRow) AND (column = ghostColumn)) THEN
|
|
LOCATE 8, 1
|
|
PRINT "You've been caught!"
|
|
END
|
|
END IF
|
|
|
|
keyed$ = INKEY$
|
|
|
|
FOR nothing = 1 TO 500 :REM change if your computer is faster
|
|
NEXT nothing
|
|
|
|
oldRow = row
|
|
oldColumn = column
|
|
|
|
REM examine the keys
|
|
SELECT CASE keyed$
|
|
CASE IS = "q"
|
|
row = row - 1
|
|
CASE IS = "a"
|
|
row = row + 1
|
|
CASE IS = "o"
|
|
column = column - 1
|
|
CASE IS = "p"
|
|
column = column + 1
|
|
END SELECT
|
|
|
|
REM examine the maze
|
|
SELECT CASE MID$(maze$(row), column, 1)
|
|
CASE IS = "#"
|
|
row = oldRow
|
|
column = oldColumn
|
|
CASE IS = "."
|
|
MID$(maze$(row), column, 1) = " "
|
|
dots = dots - 1
|
|
END SELECT
|
|
:REM <ÄÂÄ new
|
|
IF RND < 0.1 THEN
|
|
:REM ÄÙ
|
|
REM move ghost closer to PACMAN
|
|
oldRow = ghostRow
|
|
SELECT CASE ghostRow
|
|
CASE < row
|
|
ghostRow = ghostRow + 1
|
|
CASE > row
|
|
ghostRow = ghostRow - 1
|
|
END SELECT
|
|
IF MID$(maze$(ghostRow), ghostColumn, 1) = "#" THEN ghostRow = oldRow
|
|
|
|
IF ghostRow = oldRow THEN
|
|
oldColumn = ghostColumn
|
|
SELECT CASE ghostColumn
|
|
CASE < column
|
|
ghostColumn = ghostColumn + 1
|
|
CASE > column
|
|
ghostColumn = ghostColumn - 1
|
|
END SELECT
|
|
IF MID$(maze$(ghostRow), ghostColumn, 1) = "#" THEN ghostColumn = oldColumn
|
|
END IF
|
|
END IF :REM <ÄÄÄ new
|
|
LOOP
|
|
|
|
Another way to slow down the game is to use a variable "wait" and add 1 to it
|
|
every time the program loops.
|
|
Only when "wait" = 20 the ghost is allowed to move.
|
|
Remember to reset "wait" to 0 after moving, or its value will be 21, 22, etc.
|
|
and never again 20!
|
|
If you use this method you must remove the FOR..NEXT loop that kills time.
|
|
|
|
Next week we'll do an RPG!
|
|
|
|
-------------------------------------------------------------------------------
|